summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2015-01-12 10:46:53 -0800
committerJames Bottomley <JBottomley@Parallels.com>2015-01-24 17:31:32 -0800
commit6436c3346e8f19bc8220bcc5266129aa070a9520 (patch)
tree315b674a64de12f66747a45d88d3f28f47713d2b
downloadQuark_EDKII-6436c3346e8f19bc8220bcc5266129aa070a9520.tar.gz
v1.0.1
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.c705
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.h401
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf104
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/Exception.h137
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecific.c177
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecificDef.h99
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.S574
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.asm588
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/IA32/Exception.c329
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.c463
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.h50
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.c113
-rw-r--r--IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.h85
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/Analysis.c197
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/Cpu.h298
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf179
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/DataCollection.c765
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/Feature.h43
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecific.c143
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecificDef.h84
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/AsmInclude.inc59
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.S56
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.asm69
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.c52
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.h184
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/Exception.c327
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.S449
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.asm440
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.c149
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.h82
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.c162
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.h77
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.c578
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.h367
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/MpService.c1478
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/MpService.h554
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/ProcessorConfig.c571
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Cache.h108
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CacheSubClass.c587
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CpuSmbios.c126
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Processor.h172
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorData.c203
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorSubClass.c537
-rwxr-xr-xIA32FamilyCpuBasePkg/CpuMpDxe/SelectLfp.c221
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/Setting.c351
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/Strings.unibin0 -> 3978 bytes
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/Xd.c167
-rw-r--r--IA32FamilyCpuBasePkg/CpuMpDxe/Xd.h82
-rw-r--r--IA32FamilyCpuBasePkg/CpuPei/Bist.c198
-rw-r--r--IA32FamilyCpuBasePkg/CpuPei/Bist.h82
-rw-r--r--IA32FamilyCpuBasePkg/CpuPei/Cache.c156
-rw-r--r--IA32FamilyCpuBasePkg/CpuPei/CpuPei.h58
-rw-r--r--IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf85
-rw-r--r--IA32FamilyCpuBasePkg/CpuPei/CpuPeim.c141
-rw-r--r--IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec144
-rw-r--r--IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dsc207
-rw-r--r--IA32FamilyCpuBasePkg/Include/AcpiCpuData.h53
-rw-r--r--IA32FamilyCpuBasePkg/Include/CpuHotPlugData.h52
-rw-r--r--IA32FamilyCpuBasePkg/Include/Guid/HtBistHob.h52
-rw-r--r--IA32FamilyCpuBasePkg/Include/Guid/IA32FamilyCpuPkgTokenSpace.h44
-rw-r--r--IA32FamilyCpuBasePkg/Include/Library/CpuConfigLib.h702
-rw-r--r--IA32FamilyCpuBasePkg/Include/Library/CpuOnlyResetLib.h50
-rw-r--r--IA32FamilyCpuBasePkg/Include/Library/PlatformSecLib.h82
-rw-r--r--IA32FamilyCpuBasePkg/Include/Library/SmmCpuPlatformHookLib.h137
-rw-r--r--IA32FamilyCpuBasePkg/Include/Library/SocketLga775Lib.h185
-rw-r--r--IA32FamilyCpuBasePkg/Include/Ppi/Cache.h84
-rw-r--r--IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuService.h231
-rw-r--r--IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuSync.h131
-rw-r--r--IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuSync2.h224
-rw-r--r--IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfig.c1002
-rw-r--r--IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfig.h92
-rw-r--r--IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf74
-rw-r--r--IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.c340
-rw-r--r--IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.inf66
-rw-r--r--IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.c53
-rw-r--r--IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf76
-rw-r--r--IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.c101
-rw-r--r--IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf76
-rw-r--r--IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.c143
-rw-r--r--IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf65
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.c449
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf78
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPrivate.h56
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.c291
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf84
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuS3.c454
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuService.c500
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuService.h213
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.S186
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.asm190
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c116
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/Semaphore.c78
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.S171
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.asm176
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiException.S1196
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiException.asm883
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmInit.S122
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmInit.asm132
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c84
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.h116
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/MpService.c1813
-rwxr-xr-xIA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c1530
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h782
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf156
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmFeatures.c380
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmFeatures.h191
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfile.c1376
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfile.h83
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfileInternal.h184
-rw-r--r--IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SyncTimer.c130
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/FindPeiCore.c218
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/Ia32/ResetVec.S16116
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/Ia32/ResetVec.asm16125
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/Ia32/Stack.S97
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/Ia32/Stack.asm101
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/SecCore.inf90
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/SecMain.c400
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/SecMain.h154
-rw-r--r--IA32FamilyCpuBasePkg/SecCore/Vtf0SecCore.inf86
-rw-r--r--LICENSE26
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf66
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Cst/Cpu0Cst.asl430
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Ist/Cpu0Ist.asl190
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Tst/Cpu0Tst.asl164
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/CpuPm/CpuPm.asl104
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/LpcDev.asi277
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciHostBridge.asi226
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciIrq.asi582
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PcieExpansionPrt.asi158
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Platform.asl325
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNC.asi80
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCApic.asi63
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCLpc.asi54
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QuarkSouthCluster.asi121
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Tpm.asi70
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.aslc104
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.h60
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.h133
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt1.0.aslc106
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt2.0.aslc166
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.aslc96
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.h76
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.aslc102
-rw-r--r--QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.h87
-rw-r--r--QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.c1435
-rw-r--r--QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.h347
-rw-r--r--QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c819
-rw-r--r--QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.h146
-rw-r--r--QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf221
-rw-r--r--QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/Madt.h238
-rw-r--r--QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c331
-rwxr-xr-xQuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf100
-rwxr-xr-xQuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.S68
-rwxr-xr-xQuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.asm75
-rwxr-xr-xQuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/SetIdtEntry.c81
-rwxr-xr-xQuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.c403
-rwxr-xr-xQuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.h94
-rwxr-xr-xQuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c1040
-rwxr-xr-xQuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h199
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf109
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c408
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h174
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c137
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h90
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf104
-rwxr-xr-xQuarkPlatformPkg/Applications/CapsuleApp.efibin0 -> 22784 bytes
-rwxr-xr-xQuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.c489
-rwxr-xr-xQuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.inf71
-rw-r--r--QuarkPlatformPkg/Bds/BdsDxe/Bds.h88
-rw-r--r--QuarkPlatformPkg/Bds/BdsDxe/BdsDxe.inf144
-rw-r--r--QuarkPlatformPkg/Bds/BdsDxe/BdsEntry.c1003
-rw-r--r--QuarkPlatformPkg/Bds/BdsDxe/HwErrRecSupport.c61
-rw-r--r--QuarkPlatformPkg/Bds/BdsDxe/HwErrRecSupport.h51
-rw-r--r--QuarkPlatformPkg/Bds/BdsDxe/Language.c152
-rw-r--r--QuarkPlatformPkg/Bds/BdsDxe/Language.h49
-rw-r--r--QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenu.c760
-rw-r--r--QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenu.h81
-rw-r--r--QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuApp.inf73
-rw-r--r--QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuStrings.unibin0 -> 4880 bytes
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsBoot.c2199
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsConnect.c365
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsConsole.c827
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsHotkey.c997
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsLoadOption.c1003
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsMisc.c496
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/Capsules.c217
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/InternalBdsLib.h474
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/Performance.c413
-rw-r--r--QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/UefiBootManagerLib.inf132
-rw-r--r--QuarkPlatformPkg/Binary/Payload/PayloadSample.efibin0 -> 6368 bytes
-rw-r--r--QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.binbin0 -> 129 bytes
-rw-r--r--QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.binbin0 -> 129 bytes
-rw-r--r--QuarkPlatformPkg/Binary/PlatformData/galileo-fabe-platform-data.binbin0 -> 129 bytes
-rw-r--r--QuarkPlatformPkg/Binary/PlatformData/galileo-gen2-platform-data.binbin0 -> 129 bytes
-rw-r--r--QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.binbin0 -> 129 bytes
-rw-r--r--QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.binbin0 -> 129 bytes
-rw-r--r--QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.binbin0 -> 129 bytes
-rw-r--r--QuarkPlatformPkg/Binary/SIZE_8KB.bin1
-rw-r--r--QuarkPlatformPkg/Cpu/Sec/ResetVector/CallbackServices.c98
-rw-r--r--QuarkPlatformPkg/Cpu/Sec/ResetVector/CallbackServices.h39
-rwxr-xr-xQuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Flat32.S787
-rw-r--r--QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Flat32.asm669
-rw-r--r--QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Platform.inc162
-rw-r--r--QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/ResetVec.S16107
-rw-r--r--QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/ResetVec.asm16118
-rwxr-xr-xQuarkPlatformPkg/Cpu/Sec/ResetVector/QuarkResetVector.inf74
-rw-r--r--QuarkPlatformPkg/Include/CommonIncludes.h142
-rw-r--r--QuarkPlatformPkg/Include/Cpu/CpuRegs.h60
-rw-r--r--QuarkPlatformPkg/Include/EfiFlashMap.h148
-rwxr-xr-xQuarkPlatformPkg/Include/FlashLayout.h66
-rw-r--r--QuarkPlatformPkg/Include/FlashMap.h172
-rw-r--r--QuarkPlatformPkg/Include/Guid/AcpiVariable.h187
-rw-r--r--QuarkPlatformPkg/Include/Guid/CapsuleOnDataCD.h54
-rw-r--r--QuarkPlatformPkg/Include/Guid/CapsuleOnFatFloppyDisk.h54
-rw-r--r--QuarkPlatformPkg/Include/Guid/CapsuleOnFatIdeDisk.h55
-rw-r--r--QuarkPlatformPkg/Include/Guid/CapsuleOnFatUsbDisk.h55
-rw-r--r--QuarkPlatformPkg/Include/Guid/FlashMapHob.h52
-rw-r--r--QuarkPlatformPkg/Include/Guid/MemoryConfigData.h47
-rw-r--r--QuarkPlatformPkg/Include/Guid/PlatformDataFileNameGuids.h102
-rwxr-xr-xQuarkPlatformPkg/Include/Guid/PlatformInfo.h120
-rw-r--r--QuarkPlatformPkg/Include/Guid/PlatformMemoryLayout.h92
-rwxr-xr-xQuarkPlatformPkg/Include/Guid/QuarkCapsuleGuid.h73
-rw-r--r--QuarkPlatformPkg/Include/Guid/QuarkVariableLock.h47
-rw-r--r--QuarkPlatformPkg/Include/Guid/SystemNvDataHobGuid.h60
-rw-r--r--QuarkPlatformPkg/Include/Iio/IioRegs.h51
-rw-r--r--QuarkPlatformPkg/Include/Iio/IioUniversalData.h94
-rw-r--r--QuarkPlatformPkg/Include/Iio/PciAccess.h51
-rw-r--r--QuarkPlatformPkg/Include/Library/LogoLib.h92
-rw-r--r--QuarkPlatformPkg/Include/Library/MfhLib.h252
-rw-r--r--QuarkPlatformPkg/Include/Library/PlatformBootManagerLib.h90
-rwxr-xr-xQuarkPlatformPkg/Include/Library/PlatformDataLib.h223
-rw-r--r--QuarkPlatformPkg/Include/Library/PlatformHelperLib.h305
-rw-r--r--QuarkPlatformPkg/Include/Library/PlatformPcieHelperLib.h87
-rw-r--r--QuarkPlatformPkg/Include/Library/PlatformSecServicesLib.h87
-rw-r--r--QuarkPlatformPkg/Include/Library/QuarkBootRomLib.h221
-rwxr-xr-xQuarkPlatformPkg/Include/Library/RecoveryOemHookLib.h63
-rw-r--r--QuarkPlatformPkg/Include/Library/SmmScriptLib.h161
-rw-r--r--QuarkPlatformPkg/Include/Library/SwBpeLib.h66
-rw-r--r--QuarkPlatformPkg/Include/Library/UefiBootManagerLib.h740
-rw-r--r--QuarkPlatformPkg/Include/Mfh.h122
-rw-r--r--QuarkPlatformPkg/Include/Pcal9555.h48
-rwxr-xr-xQuarkPlatformPkg/Include/Platform.h142
-rwxr-xr-xQuarkPlatformPkg/Include/PlatformBoards.h185
-rwxr-xr-xQuarkPlatformPkg/Include/PlatformData.h191
-rw-r--r--QuarkPlatformPkg/Include/Ppi/FlashMap.h78
-rw-r--r--QuarkPlatformPkg/Include/Ppi/SStateBootMode.h54
-rw-r--r--QuarkPlatformPkg/Include/Protocol/FirmwareVolumeBlockSecurity.h86
-rw-r--r--QuarkPlatformPkg/Include/Protocol/FvbExtension.h70
-rw-r--r--QuarkPlatformPkg/Include/Protocol/GlobalNvsArea.h103
-rwxr-xr-xQuarkPlatformPkg/Include/Protocol/IioUds.h62
-rw-r--r--QuarkPlatformPkg/Include/Protocol/PlatformSmmSpiReady.h54
-rwxr-xr-xQuarkPlatformPkg/Include/Protocol/PlatformType.h74
-rw-r--r--QuarkPlatformPkg/Include/Protocol/SecureBootHelper.h765
-rw-r--r--QuarkPlatformPkg/Include/QuarkPlatformDxe.h42
-rw-r--r--QuarkPlatformPkg/Include/QuarkPlatformPeim.h41
-rw-r--r--QuarkPlatformPkg/Include/Tbd/EfiBootScript.h244
-rw-r--r--QuarkPlatformPkg/Library/LogoLib/Logo.c866
-rw-r--r--QuarkPlatformPkg/Library/LogoLib/LogoLib.inf86
-rw-r--r--QuarkPlatformPkg/Library/MfhLib/MfhLib.c491
-rw-r--r--QuarkPlatformPkg/Library/MfhLib/MfhLib.inf74
-rwxr-xr-xQuarkPlatformPkg/Library/PlatformBootManagerLib/BdsPlatform.c1383
-rw-r--r--QuarkPlatformPkg/Library/PlatformBootManagerLib/BdsPlatform.h268
-rw-r--r--QuarkPlatformPkg/Library/PlatformBootManagerLib/MemoryTest.c326
-rwxr-xr-xQuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf132
-rwxr-xr-xQuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformData.c197
-rw-r--r--QuarkPlatformPkg/Library/PlatformBootManagerLib/Strings.unibin0 -> 7518 bytes
-rw-r--r--QuarkPlatformPkg/Library/PlatformCapsuleLib/IA32/TrigSmi.S90
-rw-r--r--QuarkPlatformPkg/Library/PlatformCapsuleLib/IA32/TrigSmi.asm93
-rwxr-xr-xQuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.c246
-rw-r--r--QuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.inf80
-rwxr-xr-xQuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.c409
-rw-r--r--QuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.inf73
-rw-r--r--QuarkPlatformPkg/Library/PlatformHelperLib/CommonHeader.h69
-rw-r--r--QuarkPlatformPkg/Library/PlatformHelperLib/Crc32.c339
-rw-r--r--QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf110
-rw-r--r--QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf82
-rw-r--r--QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c553
-rw-r--r--QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperLib.c308
-rw-r--r--QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperPei.c241
-rw-r--r--QuarkPlatformPkg/Library/PlatformHelperLib/PlatformSecureBoot.c515
-rw-r--r--QuarkPlatformPkg/Library/PlatformPcieHelperLib/CommonHeader.h92
-rw-r--r--QuarkPlatformPkg/Library/PlatformPcieHelperLib/DxePlatformPcieHelperLib.inf83
-rw-r--r--QuarkPlatformPkg/Library/PlatformPcieHelperLib/PeiPlatformPcieHelperLib.inf79
-rw-r--r--QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperDxe.c198
-rw-r--r--QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.c143
-rw-r--r--QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperPei.c81
-rw-r--r--QuarkPlatformPkg/Library/PlatformPcieHelperLib/SocUnit.c149
-rw-r--r--QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.c240
-rw-r--r--QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.inf86
-rw-r--r--QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.c70
-rw-r--r--QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf60
-rw-r--r--QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.c369
-rw-r--r--QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.inf85
-rw-r--r--QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.c341
-rw-r--r--QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.inf61
-rw-r--r--QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Flat32.S688
-rwxr-xr-xQuarkPlatformPkg/Library/QuarkSecLib/Ia32/Flat32.asm616
-rw-r--r--QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Ia32.inc45
-rwxr-xr-xQuarkPlatformPkg/Library/QuarkSecLib/Ia32/Platform.inc131
-rw-r--r--QuarkPlatformPkg/Library/QuarkSecLib/Ia32/SecCpu.S56
-rw-r--r--QuarkPlatformPkg/Library/QuarkSecLib/Ia32/SecCpu.asm65
-rw-r--r--QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.c133
-rw-r--r--QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.h60
-rw-r--r--QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.inf99
-rwxr-xr-xQuarkPlatformPkg/Library/RecoveryOemHookLib/CommonHeader.h48
-rwxr-xr-xQuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.c79
-rwxr-xr-xQuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.inf68
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/CommonHeader.h118
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootCrypto.c185
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootCrypto.h185
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.c241
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.inf98
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootPeImage.c711
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootPeImage.h73
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootVariable.c1694
-rw-r--r--QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootVariable.h233
-rw-r--r--QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.c149
-rw-r--r--QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.inf66
-rw-r--r--QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.c446
-rw-r--r--QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.inf51
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/CommonHeader.h52
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/DsConfig.c101
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/DsConfig.h112
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/Ia32/SwBpeAccess.S234
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/Ia32/SwBpeAccess.asm261
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/PeiDsAlloc.c183
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/SwBpe.h103
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.c154
-rw-r--r--QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.inf80
-rw-r--r--QuarkPlatformPkg/Override/BaseTools/Conf/build_rule.template559
-rwxr-xr-xQuarkPlatformPkg/Override/BaseTools/Conf/tools_def.template5123
-rw-r--r--QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c2128
-rw-r--r--QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf100
-rw-r--r--QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c1071
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf94
-rw-r--r--QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c991
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c1037
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c1407
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf144
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c780
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf90
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf93
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c1326
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c553
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c407
-rwxr-xr-xQuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf79
-rw-r--r--QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c2778
-rw-r--r--QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf110
-rwxr-xr-xQuarkPlatformPkg/Override/MdePkg/Include/Library/DebugLib.h505
-rw-r--r--QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c1132
-rw-r--r--QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf82
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TisPc.c222
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmAccess.c324
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmAccess.h127
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmCommLib.inf78
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.c857
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf99
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TisDxe.c454
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TpmComm.c440
-rw-r--r--QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TpmComm.h301
-rwxr-xr-xQuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c1106
-rwxr-xr-xQuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf98
-rwxr-xr-xQuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.c1484
-rwxr-xr-xQuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.h422
-rwxr-xr-xQuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.inf91
-rwxr-xr-xQuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridgeSupport.c171
-rwxr-xr-xQuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostResource.h93
-rwxr-xr-xQuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridge.h727
-rwxr-xr-xQuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c1640
-rw-r--r--QuarkPlatformPkg/Pci/Dxe/PciPlatform/CommonHeader.h56
-rw-r--r--QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.c226
-rw-r--r--QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.h112
-rw-r--r--QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.inf79
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.c459
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.h89
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.inf84
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClassStrings.unibin0 -> 4656 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/PlatformInit/DxeFvSecurity.c242
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/PlatformInit/DxeFvSecurity.h73
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformConfig.c762
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.c307
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.h114
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.inf100
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.c152
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.inf73
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/Setup/CommonHeader.h83
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/Setup/DxePlatform.inf109
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/Setup/KeyboardLayout.c295
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/Setup/QNCRegTable.c113
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/Setup/SetupPlatform.c130
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/Setup/SetupPlatform.h108
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/Setup/Strings.unibin0 -> 5790 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/Setup/processor.c93
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/CommonHeader.h60
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturer.unibin0 -> 4388 bytes
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturerData.c69
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturerFunction.c202
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendor.unibin0 -> 3948 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendorData.c123
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendorFunction.c256
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBootInformationData.c55
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBootInformationFunction.c102
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturer.unibin0 -> 4110 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturerData.c67
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturerFunction.c199
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscDevicePath.h73
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscNumberOfInstallableLanguagesData.c59
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscNumberOfInstallableLanguagesFunction.c273
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemString.unibin0 -> 3582 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemStringData.c44
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemStringFunction.c112
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDevice.unibin0 -> 3980 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDeviceData.c80
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDeviceFunction.c136
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignator.unibin0 -> 9772 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignatorData.c215
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignatorFunction.c323
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturer.unibin0 -> 4276 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturerData.c63
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturerFunction.c229
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionString.unibin0 -> 3700 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionStringData.c54
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionStringFunction.c115
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignation.unibin0 -> 5192 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignationData.c388
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignationFunction.c314
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotOnboardDevices.unibin0 -> 4206 bytes
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMisc.h169
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDataTable.c140
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDxe.inf332
-rwxr-xr-xQuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscEntryPoint.c113
-rw-r--r--QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscStrings.unibin0 -> 4296 bytes
-rw-r--r--QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/AccessViolationHandler.c242
-rw-r--r--QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/AccessViolationHandler.h54
-rwxr-xr-xQuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.c837
-rwxr-xr-xQuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.h169
-rwxr-xr-xQuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.inf98
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.c271
-rw-r--r--QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.h71
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf104
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.c676
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.h64
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf92
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/BootMode.c274
-rw-r--r--QuarkPlatformPkg/Platform/Pei/PlatformInit/Capsule.c416
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/Common/FlashMap.c290
-rw-r--r--QuarkPlatformPkg/Platform/Pei/PlatformInit/CommonHeader.h112
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/Generic/Recovery.c539
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c319
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c1845
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.h205
-rw-r--r--QuarkPlatformPkg/Platform/Pei/PlatformInit/PeiFvSecurity.c151
-rw-r--r--QuarkPlatformPkg/Platform/Pei/PlatformInit/PeiFvSecurity.h91
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.c703
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.h311
-rwxr-xr-xQuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf234
-rw-r--r--QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformErratas.c203
-rw-r--r--QuarkPlatformPkg/Platform/SpiFvbServices/FvbInfo.c264
-rwxr-xr-xQuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.c2146
-rw-r--r--QuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.h338
-rw-r--r--QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.c63
-rw-r--r--QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.inf116
-rw-r--r--QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSpi.inf113
-rwxr-xr-xQuarkPlatformPkg/Platform/SpiFvbServices/SpiFlashDevice.c360
-rw-r--r--QuarkPlatformPkg/Platform/SpiFvbServices/SpiFlashDevice.h215
-rwxr-xr-xQuarkPlatformPkg/QuarkPlatformPkg.dec949
-rwxr-xr-xQuarkPlatformPkg/QuarkPlatformPkg.dsc736
-rwxr-xr-xQuarkPlatformPkg/QuarkPlatformPkg.fdf1485
-rwxr-xr-xQuarkPlatformPkg/QuarkPlatformPkgConfig.dsc39
-rwxr-xr-xQuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.c464
-rwxr-xr-xQuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.exebin0 -> 412160 bytes
-rwxr-xr-xQuarkPlatformPkg/Tools/CapsuleCreate/GNUmakefile55
-rw-r--r--QuarkPlatformPkg/Tools/CapsuleCreate/Makefile42
-rwxr-xr-xQuarkPlatformPkg/Tools/CapsuleCreate/QuarkPlatformPkgCapsuleComponents.inf98
-rwxr-xr-xQuarkPlatformPkg/Tools/QuarkSpiFixup/QuarkSpiFixup.py432
-rwxr-xr-xQuarkPlatformPkg/Tools/SignTool/DummySignTool.c289
-rwxr-xr-xQuarkPlatformPkg/Tools/SignTool/DummySignTool.exebin0 -> 375808 bytes
-rwxr-xr-xQuarkPlatformPkg/Tools/SignTool/GNUmakefile55
-rwxr-xr-xQuarkPlatformPkg/Tools/SignTool/Makefile42
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/BaseLib.inf517
-rwxr-xr-xQuarkSocPkg/Override/MdePkg/Library/BaseLib/CpuDeadLoop.c68
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c63
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/GccInline.c1705
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/LShiftU64.S62
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/LShiftU64.c70
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/MsrUtils.S95
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/MsrUtils.asm96
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/RShiftU64.S65
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/RShiftU64.c70
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/WriteCr4.c59
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/QuarkMsr.c105
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/QuarkMsr.h142
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/ReadMsr64.c77
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseLib/WriteMsr64.c82
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf118
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.S73
-rw-r--r--QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.asm76
-rwxr-xr-xQuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.c55
-rwxr-xr-xQuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.inf62
-rw-r--r--QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.c1717
-rw-r--r--QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf60
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/IntelProprietaryLicense.txt14
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/QuarkMicrocode.inf50
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.binbin0 -> 16384 bytes
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/IntelProprietaryLicense.txt14
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/QuarkMicrocode.inf50
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.binbin0 -> 8192 bytes
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/DdrMemoryController.h275
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Guid/RedirectServicesHob.h49
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCBase.h41
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCConfig.h124
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCDxe.h41
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCPeim.h41
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCRegs.h72
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Library/IntelQNCLib.h327
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Include/Library/QNCAccessLib.h179
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Library/RedirectPeiServicesLib.h92
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Ppi/CltMemoryInit.h83
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchInfo.h79
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchPlatformPolicy.h74
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PlatformPolicy.h62
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Protocol/QncS3Support.h115
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmIchnDispatch2.h139
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmRtProtocol.h173
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/Protocol/Spi.h376
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/QNCAccess.h208
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Include/QNCCommonDefinitions.h381
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Include/QuarkNcSocId.h780
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.c246
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.inf68
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/CommonHeader.h56
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c870
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf87
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c967
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/BaseAccess.c52
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.c341
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf63
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeAccess.c166
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeQNCAccessLib.inf69
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c235
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf68
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServices.c392
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServicesLib.inf74
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.c340
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf70
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/CommonHeader.h49
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c771
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf74
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.c83
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.h59
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf96
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/core_types.h74
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/gen5_iosf_sb_definitions.h762
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/general_definitions.h108
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c560
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.h97
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/io.h163
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/lprint.c411
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.c2663
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.h46
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.c1598
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.h115
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/memory_options.h108
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.c64
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.h184
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/platform.c217
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.c211
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.h39
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/CommonHeader.h93
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.c636
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.h229
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyInterrupt.c240
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyInterrupt.h58
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.c261
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.h222
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.c431
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.h87
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf148
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCRootPorts.c123
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbus.h104
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbusExec.c264
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/SmartTimer.c480
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/SmartTimer.h195
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.c448
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.h142
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf90
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf80
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c422
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.h253
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDriver.c384
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf80
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.c890
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.h114
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.inf78
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/CommonHeader.h69
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmGpi.c63
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmHelpers.c573
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmPeriodicTimer.c455
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmQncn.c238
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSw.c121
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c178
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmm.h896
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmCore.c806
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf108
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.c397
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.h249
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmRegisters.h43
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCxSmmHelpers.h208
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.c406
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf77
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.c300
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf75
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.c975
-rwxr-xr-xQuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.h341
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.c236
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.h104
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpiRuntime.inf112
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.c146
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.h73
-rw-r--r--QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpiSmm.inf75
-rwxr-xr-xQuarkSocPkg/QuarkSocPkg.dec261
-rwxr-xr-xQuarkSocPkg/QuarkSocPkg.dsc264
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/CommonHeader.h70
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2C.c962
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2C.h405
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2CDxe.inf97
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/CEATA.h138
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/I2CRegs.h90
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/Ioh.h277
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/IohAccess.h49
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/IohCommonDefinitions.h374
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/Library/IohLib.h47
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/MMC.h295
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/Protocol/I2CHc.h226
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/SDCard.h170
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Include/SDHostIo.h348
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/CommonHeader.h79
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohBds.h111
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohData.c77
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.c80
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.h41
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf107
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Library/IohLib/CommonHeader.h53
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.c81
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf67
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.c406
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.h63
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.inf74
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.c251
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.h165
-rwxr-xr-xQuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.c1701
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.h334
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf82
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c676
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c414
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.c239
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.h163
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c482
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c1730
-rwxr-xr-xQuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.c345
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.h485
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf85
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/ComponentName.c269
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.c1797
-rwxr-xr-xQuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.h857
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/SerialDxe.inf95
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c344
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.h62
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf81
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.c243
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.h165
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Descriptor.h156
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.c2515
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.h695
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.c102
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.h66
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf101
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.c1417
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.h944
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.c548
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.h246
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.c913
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.h411
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.c584
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.h176
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/Descriptor.h155
-rwxr-xr-xQuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c1426
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.h277
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf85
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.c1412
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.h899
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.c247
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.h132
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.c584
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.h255
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.c517
-rw-r--r--QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.h158
-rwxr-xr-xbuildallconfigs.sh47
-rw-r--r--edksetup.bat171
-rwxr-xr-xedksetup.sh70
-rwxr-xr-xquarkbuild.bat232
-rwxr-xr-xquarkbuild.sh244
-rwxr-xr-xsvn_externals.txt13
-rwxr-xr-xsvn_setup.py232
704 files changed, 201010 insertions, 0 deletions
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.c b/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.c
new file mode 100644
index 0000000..145d3a6
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.c
@@ -0,0 +1,705 @@
+/** @file
+
+ Entry point of CPU DXE driver.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Cpu.c
+
+**/
+
+#include "Cpu.h"
+
+//
+// CPU System Memory Map Definition
+//
+#define CPU_MSI_MEMORY_BASE 0xFEE00000
+#define CPU_MSI_MEMORY_SIZE 0x100000
+
+BOOLEAN mIsFlushingGCD;
+EFI_HANDLE mHandle = NULL;
+
+//
+// Vector Table for user's interrupt handlers
+//
+EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[INTERRUPT_VECTOR_NUMBER];
+
+//
+// The Cpu Architectural Protocol that this Driver produces
+//
+EFI_CPU_ARCH_PROTOCOL mCpuArchProtocol = {
+ FlushCpuDataCache,
+ EnableInterrupt,
+ DisableInterrupt,
+ GetInterruptStateInstance,
+ Init,
+ RegisterInterruptHandler,
+ GetTimerValue,
+ SetMemoryAttributes,
+ 1,
+ 4,
+};
+
+/**
+ This function flushes CPU data cache.
+
+ This function implements FlushDataCache() service of CPU Architecture Protocol.
+ It flushes a range of the processor's data cache.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param Start Physical address to start flushing from.
+ @param Length Number of bytes to flush. Round up to chipset granularity.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS Cache is flushed.
+ @retval EFI_UNSUPPORTED Flush type is not supported.
+ @retval EFI_DEVICE_ERROR 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) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ This function enables interrupt processing by the processor.
+
+ This function implements EnableInterrupt() service of CPU Architecture Protocol.
+ This function enables interrupt processing by the processor. This function is
+ used to implement the Boot Services RaiseTPL() and RestoreTPL().
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are enabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ EnableInterrupts ();
+ return EFI_SUCCESS;
+}
+
+/**
+ This function disables interrupt processing by the processor.
+
+ This function implements DisableInterrupt() service of CPU Architecture Protocol.
+ This function disables interrupt processing by the processor. This function is
+ used to implement the Boot Services RaiseTPL() and RestoreTPL().
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are disabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ DisableInterrupts ();
+ return EFI_SUCCESS;
+}
+
+/**
+ This function retrieves the processor's current interrupt state.
+
+ This function implements GetInterruptState() service of CPU Architecture Protocol.
+ This function retrieves the processor's current interrupt state.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param State A pointer to the processor's current interrupt state.
+ Set to TRUE if interrupts are enabled and FALSE if interrupts are disabled.
+
+ @retval EFI_SUCCESS The processor's current interrupt state was returned in State.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetInterruptStateInstance (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = GetInterruptState ();
+ return EFI_SUCCESS;
+}
+
+/**
+ This function generates an INIT on the processor.
+
+ This function implements Init() service of CPU Architecture Protocol.
+ This function generates an INIT on the processor.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InitType The type of processor INIT to perform.
+
+ @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
+ @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported by this processor.
+ @retval EFI_DEVICE_ERROR The processor INIT failed.
+
+**/
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function Registers a function to be called from the processor interrupt handler.
+
+ This function implements RegisterInterruptHandler() service of CPU Architecture Protocol.
+ This function Registers a function to be called from the processor interrupt handler.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InterruptType Defines which interrupt or exception to hook.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ If this parameter is NULL, then the handler will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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.
+ @retval 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;
+ }
+
+ if (InterruptHandler != NULL) {
+ SetInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType);
+ } else {
+ //
+ // Restore the original IDT handler address if InterruptHandler is NULL.
+ //
+ RestoreInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType);
+ }
+
+ mExternalVectorTable[InterruptType] = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function returns a timer value from one of the processor's internal timers.
+
+ This function implements GetTimerValue() service of CPU Architecture Protocol.
+ This function returns a timer value from one of the processor's internal timers.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue.
+ This parameter must be between 0 and EFI_CPU_ARCH_PROTOCOL.NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each
+ increment of TimerValue. If TimerValue does not increment at a predictable
+ rate, then 0 is returned.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL.
+ @retval EFI_INVALID_PARAMETER TimerIndex is not valid.
+ @retval EFI_UNSUPPORTEDT The processor does not have any readable timers.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Actual;
+ UINT64 Standard;
+ UINT32 Ratio;
+
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerValue = AsmReadTsc ();
+
+ if (TimerPeriod != NULL) {
+ Status = GetActualFrequency (&Actual);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetCpuBusRatio (&Ratio);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Since actual frequency might not be accurate, convert it into standand
+ // frequency: 100, 133, 166, 200, ...
+ //
+ Actual2StandardFrequency (Actual, Ratio, &Standard);
+
+ *TimerPeriod = DivU64x32 (1000000000, (UINT32) Standard);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
+
+ This function modifies the attributes for the memory region specified by BaseAddress and
+ Length from their current attributes to the attributes specified by Attributes.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval EFI_SUCCESS The attributes were set for the memory region.
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ Attributes specified an illegal combination of attributes that
+ cannot be set together.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ RETURN_STATUS Status;
+ EFI_STATUS MpStatus;
+ MTRR_MEMORY_CACHE_TYPE CacheType;
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+
+ //
+ // If this function is called because GCD SetMemorySpaceAttributes () is called
+ // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory
+ // map with MTRR values. So there is no need to modify MTRRs, just return immediately
+ // to avoid unnecessary computing.
+ //
+ if (mIsFlushingGCD) {
+ return EFI_SUCCESS;
+ }
+
+ switch (Attributes) {
+ case EFI_MEMORY_UC:
+ CacheType = CacheUncacheable;
+ break;
+
+ case EFI_MEMORY_WC:
+ CacheType = CacheWriteCombining;
+ break;
+
+ case EFI_MEMORY_WT:
+ CacheType = CacheWriteThrough;
+ break;
+
+ case EFI_MEMORY_WP:
+ CacheType = CacheWriteProtected;
+ break;
+
+ case EFI_MEMORY_WB:
+ CacheType = CacheWriteBack;
+ break;
+
+ case EFI_MEMORY_UCE:
+ case EFI_MEMORY_RP:
+ case EFI_MEMORY_XP:
+ case EFI_MEMORY_RUNTIME:
+ return EFI_UNSUPPORTED;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // call MTRR libary function
+ //
+ Status = MtrrSetMemoryAttribute(
+ BaseAddress,
+ Length,
+ CacheType
+ );
+
+ if (!RETURN_ERROR (Status)) {
+ //
+ // Sync saved MTRR settings
+ //
+ MtrrGetAllMtrrs (mMtrrTable);
+ //
+ // Synchronize the update with all APs
+ //
+ MpStatus = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &MpService
+ );
+ if (!EFI_ERROR (MpStatus)) {
+ MpStatus = MpService->StartupAllAPs (
+ MpService,
+ LoadMtrrData,
+ TRUE,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ if (MpStatus == EFI_NOT_STARTED) {
+ //
+ // If no enabled APs exit in the system, return success
+ //
+ MpStatus = EFI_SUCCESS;
+ }
+ ASSERT_EFI_ERROR (MpStatus);
+ }
+ }
+ return (EFI_STATUS) Status;
+}
+
+/**
+ Entrypoint of CPU DXE module.
+
+ This function is the entrypoint of CPU DXE module. It initializes system and installs
+ CPU Architecture Protocol.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entrypoint always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+
+ InitializeFloatingPointUnits ();
+
+ //
+ // Initialize GDT and IDT
+ //
+ InitializeDescriptorTables ();
+
+ //
+ // Install CPU Architectural Protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mHandle,
+ &gEfiCpuArchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mCpuArchProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Refresh GCD memory space map according to MTRR value.
+ //
+ RefreshGcdMemoryAttributes ();
+
+ //
+ // Report memory space from 0xFEE00000 to 0xFEEFFFFF as memory mapped space for MSI (Message Signaled Interrupt).
+ // First, add memory space for MSI
+ //
+ BaseAddress = CPU_MSI_MEMORY_BASE;
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BaseAddress,
+ CPU_MSI_MEMORY_SIZE,
+ EFI_MEMORY_UC
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Second, allocate this new added memory space.
+ //
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 0,
+ CPU_MSI_MEMORY_SIZE,
+ &BaseAddress,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // If the default local APIC base address has been changed, we need to add/allocate
+ // memory space for the 4K size of the local APIC memory range.
+ //
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) GetLocalApicBaseAddress();
+ if (BaseAddress != CPU_MSI_MEMORY_BASE) {
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BaseAddress,
+ SIZE_4KB,
+ EFI_MEMORY_UC
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 0,
+ SIZE_4KB,
+ &BaseAddress,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ // Program Local APIC for virtual wire mode. Enable Spurious
+ // Vector, program the LINT0 vector entry as ExtInt, and
+ // program the LINT1 vector entry as NMI
+ //
+ ProgramVirtualWireMode ();
+
+ //
+ // Allocates ACPI NVS memory for MTRR data.
+ //
+ InitializeMtrrData ();
+ MtrrGetAllMtrrs (mMtrrTable);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns the CPU core to processor bus frequency ratio.
+
+ This function returns the CPU core to processor bus frequency ratio.
+
+ @param Ratio Pointer to the CPU core to processor bus frequency ratio.
+
+ @retval EFI_SUCCESS The ratio is returned successfully
+ @retval EFI_UNSUPPORTED The ratio cannot be measured
+ @retval EFI_INVALID_PARAMETER The input parameter is not valid
+
+**/
+EFI_STATUS
+GetCpuBusRatio (
+ OUT UINT32 *Ratio
+ )
+{
+ UINT32 RegEax;
+ UINT32 BasicFamilyId;
+ UINT32 FamilyId;
+ UINT32 ModelId;
+ UINT32 ExtendedModelId;
+
+ if (Ratio == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
+
+ //
+ // The Extended Family ID needs to be examined only when the Family ID is 0FH.
+ //
+ BasicFamilyId = BitFieldRead32 (RegEax, 8, 11);
+ FamilyId = BasicFamilyId;
+ if (BasicFamilyId == 0x0F) {
+ FamilyId += BitFieldRead32 (RegEax, 20, 27);
+ }
+
+ //
+ // The Extended Model ID needs to be examined only when the Family ID is 06H or 0FH.
+ //
+ ModelId = BitFieldRead32 (RegEax, 4, 7);
+ if (BasicFamilyId == 0x06 || BasicFamilyId == 0x0f) {
+ ExtendedModelId = BitFieldRead32 (RegEax, 16, 19);
+ ModelId += ExtendedModelId << 4;
+ }
+
+ switch (FamilyId) {
+ case PENTIUM_FAMILY_ID:
+ switch (ModelId) {
+ case QUARK_MODEL_ID:
+ //
+ // Collect core to bus ratio
+ //
+ *Ratio = (UINTN) 0x01;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns the actual CPU core frequency in MHz.
+
+ This function returns the actual CPU core frequency in MHz.
+
+ @param Frequency Pointer to the CPU core frequency.
+
+ @retval EFI_SUCCESS The frequency is returned successfully.
+ @retval EFI_INVALID_PARAMETER Frequency is NULL.
+
+**/
+EFI_STATUS
+GetActualFrequency (
+ OUT UINT64 *Frequency
+ )
+{
+ UINT64 BeginValue;
+ UINT64 EndValue;
+
+ if (Frequency == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Read timestamp counter before and after delay of 100 microseconds
+ //
+ BeginValue = AsmReadTsc ();
+ MicroSecondDelay (100);
+ EndValue = AsmReadTsc ();
+
+ //
+ // Calculate the actual frequency
+ //
+ *Frequency = DivU64x32Remainder (EndValue - BeginValue, 100, NULL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Converts the actual frequency in MHz to the standard frequency in MHz.
+
+ This function converts the actual frequency in MHz to the standard frequency in MHz.
+
+ @param Actual Actual CPU core frequency.
+ @param Ratio CPU core to processor bus frequency ratio.
+ @param Standard Standard CPU core frequency.
+
+**/
+VOID
+Actual2StandardFrequency (
+ IN UINT64 Actual,
+ IN UINT32 Ratio,
+ OUT UINT64 *Standard
+ )
+{
+ UINT64 Inflated;
+ UINT64 Temp;
+
+ //
+ // Increase the Actual frequency a little, compute its
+ // corresponding FSB frequency, and then discard the small fractions of it, to
+ // get a clean, standard FSB frequency value.
+ //
+ // Increase Actual by 3%, since the error of actual frequency is within 1%.
+ //
+ Inflated = Actual + RShiftU64 (Actual, 5);
+
+ //
+ // The standard Fsb are: 100(300/3), 133(400/3), 166(500/3), 200(600/3), ...
+ // so if we are able to calculate the digit(3, 4, 5, 6, etc) at the hundred's
+ // position, the standard frequency can be calculated.
+ //
+ //
+ // So multiple the Inflated frequency by 3, divide it with Ratio, and divide
+ // it by 100, in order to get an integer (3, 4, 5, 6, ... respectively).
+ //
+ Temp = DivU64x32 (DivU64x32 (MultU64x32 (Inflated, 3), Ratio), 100);
+
+ //
+ // After getting the digit, convert it back to the Cpu frequency
+ //
+ *Standard = DivU64x32 (MultU64x32 (MultU64x32 (Temp, 100), Ratio), 3);
+}
+
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.h b/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.h
new file mode 100644
index 0000000..35b4257
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.h
@@ -0,0 +1,401 @@
+/** @file
+
+ Include file for CPU DXE Module
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Cpu.h
+
+**/
+
+#ifndef _CPU_DXE_H_
+#define _CPU_DXE_H_
+
+#include <PiDxe.h>
+
+#include "Exception.h"
+#include "ArchSpecificDef.h"
+
+#include <Protocol/MpService.h>
+#include <Guid/StatusCodeDataTypeId.h>
+#include <Protocol/Cpu.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/UefiLib.h>
+#include <Library/SocketLga775Lib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/UefiCpuLib.h>
+
+#include "MemoryAttribute.h"
+#include "MtrrSync.h"
+#include "Exception.h"
+
+#define INTERRUPT_VECTOR_NUMBER 256
+#define INTERRUPT_GATE_ATTRIBUTE 0x8e00
+
+#define APIC_REGISTER_LOCAL_ID_OFFSET 0x20
+#define APIC_REGISTER_APIC_VERSION_OFFSET 0x30
+#define APIC_REGISTER_SPURIOUS_VECTOR_OFFSET 0xF0
+#define APIC_REGISTER_ICR_LOW_OFFSET 0x300
+#define APIC_REGISTER_ICR_HIGH_OFFSET 0x310
+#define APIC_REGISTER_LINT0_VECTOR_OFFSET 0x350
+#define APIC_REGISTER_LINT1_VECTOR_OFFSET 0x360
+
+extern EFI_CPU_ARCH_PROTOCOL mCpuArchProtocol;
+extern UINT64 mValidMtrrAddressMask;
+extern UINT64 mValidMtrrBitsMask;
+
+/**
+ This function flushes CPU data cache.
+
+ This function implements FlushDataCache() service of CPU Architecture Protocol.
+ It flushes a range of the processor's data cache.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param Start Physical address to start flushing from.
+ @param Length Number of bytes to flush. Round up to chipset granularity.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS Cache is flushed.
+ @retval EFI_UNSUPPORTED Flush type is not supported.
+ @retval EFI_DEVICE_ERROR 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
+ );
+
+/**
+ This function enables interrupt processing by the processor.
+
+ This function implements EnableInterrupt() service of CPU Architecture Protocol.
+ This function enables interrupt processing by the processor. This function is
+ used to implement the Boot Services RaiseTPL() and RestoreTPL().
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are enabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ This function disables interrupt processing by the processor.
+
+ This function implements DisableInterrupt() service of CPU Architecture Protocol.
+ This function disables interrupt processing by the processor. This function is
+ used to implement the Boot Services RaiseTPL() and RestoreTPL().
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are disabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ This function retrieves the processor's current interrupt state.
+
+ This function implements GetInterruptState() service of CPU Architecture Protocol.
+ This function retrieves the processor's current interrupt state.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param State A pointer to the processor's current interrupt state.
+ Set to TRUE if interrupts are enabled and FALSE if interrupts are disabled.
+
+ @retval EFI_SUCCESS The processor's current interrupt state was returned in State.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetInterruptStateInstance (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+/**
+ This function generates an INIT on the processor.
+
+ This function implements Init() service of CPU Architecture Protocol.
+ This function generates an INIT on the processor.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InitType The type of processor INIT to perform.
+
+ @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
+ @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported by this processor.
+ @retval EFI_DEVICE_ERROR The processor INIT failed.
+
+**/
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+/**
+ This function Registers a function to be called from the processor interrupt handler.
+
+ This function implements RegisterInterruptHandler() service of CPU Architecture Protocol.
+ This function Registers a function to be called from the processor interrupt handler.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InterruptType Defines which interrupt or exception to hook.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ If this parameter is NULL, then the handler will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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.
+ @retval 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
+ );
+
+/**
+ This function returns a timer value from one of the processor's internal timers.
+
+ This function implements GetTimerValue() service of CPU Architecture Protocol.
+ This function returns a timer value from one of the processor's internal timers.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue.
+ This parameter must be between 0 and EFI_CPU_ARCH_PROTOCOL.NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each
+ increment of TimerValue. If TimerValue does not increment at a predictable
+ rate, then 0 is returned.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL.
+ @retval EFI_INVALID_PARAMETER TimerIndex is not valid.
+ @retval EFI_UNSUPPORTEDT The processor does not have any readable timers.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+/**
+ This function attempts to set the attributes for a memory range.
+
+ This function implements SetMemoryAttributes() service of CPU Architecture Protocol.
+ This function attempts to set the attributes for a memory range.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval EFI_SUCCESS The attributes were set for the memory region.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the
+ memory resource range specified by BaseAddress and Length.
+ @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+/**
+ Creates an IDT and a new GDT in RAM.
+
+ This function creates an IDT and a new GDT in RAM.
+
+**/
+VOID
+InitializeDescriptorTables (
+ VOID
+ );
+
+/**
+ Creates a new GDT in RAM and load it.
+
+ This function creates a new GDT in RAM and load it.
+
+**/
+VOID
+EFIAPI
+InitializeGdt (
+ VOID
+ );
+
+/**
+ Returns the actual CPU core frequency in MHz.
+
+ This function returns the actual CPU core frequency in MHz.
+
+ @param Frequency Pointer to the CPU core frequency.
+
+ @retval EFI_SUCCESS The frequency is returned successfully.
+ @retval EFI_INVALID_PARAMETER Frequency is NULL.
+
+**/
+EFI_STATUS
+GetActualFrequency (
+ OUT UINT64 *Frequency
+ );
+
+/**
+ Returns the CPU core to processor bus frequency ratio.
+
+ This function returns the CPU core to processor bus frequency ratio.
+
+ @param Ratio Pointer to the CPU core to processor bus frequency ratio.
+
+ @retval EFI_SUCCESS The ratio is returned successfully
+ @retval EFI_UNSUPPORTED The ratio cannot be measured
+ @retval EFI_INVALID_PARAMETER The input parameter is not valid
+
+**/
+EFI_STATUS
+GetCpuBusRatio (
+ OUT UINT32 *Ratio
+ );
+
+/**
+ Converts the actual frequency in MHz to the standard frequency in MHz.
+
+ This function converts the actual frequency in MHz to the standard frequency in MHz.
+
+ @param Actual Actual CPU core frequency.
+ @param Ratio CPU core to processor bus frequency ratio.
+ @param Standard Standard CPU core frequency.
+
+**/
+VOID
+Actual2StandardFrequency (
+ IN UINT64 Actual,
+ IN UINT32 Ratio,
+ OUT UINT64 *Standard
+ );
+
+/**
+ Retrieves the value of CS register.
+
+ This function retrieves the value of CS register.
+
+ @return The value of CS register.
+
+**/
+UINT16
+GetCodeSegment (
+ VOID
+ );
+
+/**
+ Refreshes the GCD Memory Space attributes according to MTRRs.
+
+ This function refreshes the GCD Memory Space attributes according to MTRRs.
+
+**/
+VOID
+RefreshGcdMemoryAttributes (
+ VOID
+ );
+
+/**
+ Label of base address of IDT vector 0.
+
+ This is just a label of base address of IDT vector 0.
+
+**/
+VOID
+EFIAPI
+AsmIdtVector00 (
+ VOID
+ );
+
+/**
+ Initialize the pointer to the external vector table.
+
+ The external vector table is an array of pointers to C based interrupt/exception
+ callback routines.
+
+ @param VectorTable The point to the vector table.
+**/
+VOID
+EFIAPI
+InitializeExternalVectorTablePtr(
+ EFI_CPU_INTERRUPT_HANDLER* VectorTable
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf b/IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf
new file mode 100644
index 0000000..d915b1e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf
@@ -0,0 +1,104 @@
+## @file
+# Component description file for CPU Arch DXE Driver.
+#
+# CPU DXE Driver that configures multi-processor environment, logs data to datahub
+# for processor subclass and cache subclass, and installs CPU Architecture Protocol and MP
+# Services Protocol
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuArchDxe
+ FILE_GUID = 62D171CB-78CD-4480-8678-C6A2A797A8DE
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeCpu
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+# Create Event Guid C Name: Event Type: EVENT_TYPE_PERIODIC_TIMER
+#
+# HOB Guid C Name: gEfiHtBistHobGuid Hob Type: GUID_EXTENSION
+#
+
+[Sources]
+ Cpu.c
+ Cpu.h
+ Exception.h
+ MemoryAttribute.c
+ MemoryAttribute.h
+ MtrrSync.c
+ MtrrSync.h
+
+[Sources.Ia32]
+ IA32/Exception.c
+ IA32/CpuAsm.asm
+ IA32/CpuAsm.S
+ IA32/ArchSpecificDef.h
+ IA32/ArchSpecific.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
+[LibraryClasses]
+ MtrrLib
+ TimerLib
+ DxeServicesTableLib
+ IoLib
+ PcdLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ ReportStatusCodeLib
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ UefiLib
+ LocalApicLib
+ UefiCpuLib
+
+[Protocols]
+ gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiCpuArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[Pcd]
+ gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress
+ gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress
+
+[Depex]
+ TRUE
+
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/Exception.h b/IA32FamilyCpuBasePkg/CpuArchDxe/Exception.h
new file mode 100644
index 0000000..efba6bc
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/Exception.h
@@ -0,0 +1,137 @@
+/** @file
+
+ Include file for exception handler
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Exception.h
+
+**/
+#ifndef _CPU_EXCEPTION_H_
+#define _CPU_EXCEPTION_H_
+
+#include <Protocol/DebugSupport.h>
+
+#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_TIMER 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
+
+//
+// Register Structure Definitions
+//
+typedef union {
+ EFI_SYSTEM_CONTEXT_IA32 SystemContextIa32;
+ EFI_SYSTEM_CONTEXT_X64 SystemContextX64;
+} SYSTEM_CONTEXT;
+
+//
+// Register Structure Definitions
+//
+typedef struct {
+ EFI_STATUS_CODE_DATA Header;
+ SYSTEM_CONTEXT SystemContext;
+} CPU_STATUS_CODE_TEMPLATE;
+
+typedef struct {
+ UINT32 ErrorMessage;
+ UINT8 Interrupt;
+} EFI_EXCEPTION_HANDLER;
+
+/**
+ The sample exception handler.
+
+ This function is called by primitive interrupt handler in assembly code, and
+ parameters of InterruptType and SystemContext are prepared by it beforehand.
+ This function outputs context of all registers when exception occurs. It then
+ reports status code for the exception.
+
+ @param InterruptType Exception type.
+ @param SystemContext System context data.
+
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Installs the Exception Handler.
+
+ This function installs the Exception Handler.
+
+ @param ExceptionBegin The begin number of exception
+
+**/
+VOID
+InitializeException (
+ IN UINT32 ExceptionBegin
+ );
+
+/**
+ Set Interrupt Descriptor Table Handler Address.
+
+ @param Index The Index of the interrupt descriptor table handle.
+
+**/
+VOID
+SetInterruptDescriptorTableHandlerAddress (
+ IN UINTN Index
+ );
+
+/**
+ Restore original Interrupt Descriptor Table Handler Address.
+
+ @param Index The Index of the interrupt descriptor table handle.
+
+**/
+VOID
+RestoreInterruptDescriptorTableHandlerAddress (
+ IN UINTN Index
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecific.c b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecific.c
new file mode 100644
index 0000000..bb21274
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecific.c
@@ -0,0 +1,177 @@
+/** @file
+
+ Memory Operation Functions for IA32 Architecture.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: ArchSpecific.c
+
+**/
+
+#include "Cpu.h"
+#include "MemoryAttribute.h"
+
+extern EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[];
+
+INTERRUPT_HANDLER_TEMPLATE_MAP mTemplateMap;
+INTERRUPT_GATE_DESCRIPTOR *mIdtTable = NULL;
+VOID *mInterruptHandler = NULL;
+INTERRUPT_GATE_DESCRIPTOR *mOrigIdtEntry = NULL;
+UINT16 mOrigIdtEntryCount = 0;
+
+UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
+UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;
+
+/**
+ Creates an IDT and a new GDT in RAM.
+
+ This function creates an IDT and a new GDT in RAM.
+
+**/
+VOID
+InitializeDescriptorTables (
+ VOID
+ )
+{
+ UINT16 CodeSegment;
+ INTERRUPT_GATE_DESCRIPTOR *IdtEntry;
+ UINTN Index;
+ INTERRUPT_GATE_DESCRIPTOR *IdtTable;
+ UINT8 *InterruptHandler;
+ IA32_DESCRIPTOR Idtr;
+
+ //
+ // Load Global Descriptor Table and update segment selectors
+ //
+ InitializeGdt ();
+
+ //
+ // Create Interrupt Descriptor Table
+ //
+ IdtTable = AllocateZeroPool (sizeof (INTERRUPT_GATE_DESCRIPTOR) * INTERRUPT_VECTOR_NUMBER);
+
+ GetTemplateAddressMap (&mTemplateMap);
+ InterruptHandler = AllocatePool (mTemplateMap.Size * INTERRUPT_VECTOR_NUMBER);
+
+ CodeSegment = AsmReadCs ();
+
+ //
+ // Get original IDT address and size and save original IDT entry.
+ //
+ AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
+ mOrigIdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (INTERRUPT_GATE_DESCRIPTOR));
+ ASSERT (mOrigIdtEntryCount <= INTERRUPT_VECTOR_NUMBER);
+ mOrigIdtEntry = AllocateCopyPool (Idtr.Limit + 1, (VOID *) Idtr.Base);
+ ASSERT (mOrigIdtEntry != NULL);
+
+ //
+ // Copy original IDT entry.
+ //
+ IdtEntry = IdtTable;
+ CopyMem (IdtEntry, (VOID *) Idtr.Base, Idtr.Limit + 1);
+
+ //
+ // Save IDT table pointer and Interrupt table pointer
+ //
+ mIdtTable = IdtTable;
+ mInterruptHandler = InterruptHandler;
+
+ for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++) {
+ //
+ // Update all IDT entries to use current CS value.
+ //
+ IdtEntry[Index].SegmentSelector = CodeSegment;
+ if (Index < mOrigIdtEntryCount) {
+ //
+ // Skip original IDT entry.
+ //
+ continue;
+ }
+ //
+ // Set the address of interrupt handler to the rest IDT entry.
+ //
+ SetInterruptDescriptorTableHandlerAddress (Index);
+ }
+
+ InitializeIdt (
+ &(mExternalVectorTable[0]),
+ (UINTN *) IdtTable,
+ (UINT16) (sizeof (INTERRUPT_GATE_DESCRIPTOR) * INTERRUPT_VECTOR_NUMBER)
+ );
+
+ //
+ // Initialize Exception Handlers
+ //
+ InitializeException (mOrigIdtEntryCount);
+}
+
+/**
+ Set Interrupt Descriptor Table Handler Address.
+
+ @param Index The Index of the interrupt descriptor table handle.
+
+**/
+VOID
+SetInterruptDescriptorTableHandlerAddress (
+ IN UINTN Index
+ )
+{
+ UINTN ExceptionHandle;
+
+ //
+ // Get the address of handler for entry
+ //
+ ExceptionHandle = (UINTN)mInterruptHandler + Index * mTemplateMap.Size;
+ CopyMem ((VOID *)ExceptionHandle, mTemplateMap.Start, mTemplateMap.Size);
+ *(UINT32 *) (ExceptionHandle + mTemplateMap.FixOffset) = Index;
+
+ mIdtTable[Index].OffsetLow = (UINT16) ExceptionHandle;
+ mIdtTable[Index].Attributes = INTERRUPT_GATE_ATTRIBUTE;
+ //
+ // 8e00;
+ //
+ mIdtTable[Index].OffsetHigh = (UINT16) (ExceptionHandle >> 16);
+}
+
+/**
+ Restore original Interrupt Descriptor Table Handler Address.
+
+ @param Index The Index of the interrupt descriptor table handle.
+
+**/
+VOID
+RestoreInterruptDescriptorTableHandlerAddress (
+ IN UINTN Index
+ )
+{
+ if (Index < mOrigIdtEntryCount) {
+ mIdtTable[Index].OffsetLow = mOrigIdtEntry[Index].OffsetLow;
+ mIdtTable[Index].OffsetHigh = mOrigIdtEntry[Index].OffsetHigh;
+ }
+}
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecificDef.h b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecificDef.h
new file mode 100644
index 0000000..e0f20fd
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecificDef.h
@@ -0,0 +1,99 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ ProcessorDef.h
+
+Abstract:
+
+ Definition for IA32 processor
+
+**/
+
+#ifndef _PROCESSOR_DEF_H_
+#define _PROCESSOR_DEF_H_
+
+#include <Protocol/Cpu.h>
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 OffsetLow;
+ UINT16 SegmentSelector;
+ UINT16 Attributes;
+ UINT16 OffsetHigh;
+} INTERRUPT_GATE_DESCRIPTOR;
+
+#pragma pack()
+
+typedef struct {
+ VOID *Start;
+ UINTN Size;
+ UINTN FixOffset;
+} INTERRUPT_HANDLER_TEMPLATE_MAP;
+
+/**
+ Return address map of interrupt handler template so that C code can generate
+ interrupt handlers, and dynamically do address fix.
+
+ @param AddressMap Pointer to a buffer where the address map is returned.
+**/
+VOID
+EFIAPI
+GetTemplateAddressMap (
+ OUT INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap
+ );
+
+/**
+ Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.
+ Table is initialized to intxx where xx is from 00 to number of entries or
+ 100h, whichever is smaller. After table has been initialized the LIDT
+ instruction is invoked.
+
+ TableStart is the pointer to the callback table and is not used by
+ InitializedIdt but by commonEntry. CommonEntry handles all interrupts,
+ does the context save and calls the callback entry, if non-NULL.
+ It is the responsibility of the callback routine to do hardware EOIs.
+
+ @param TableStart Pointer to interrupt callback table.
+ @param IdtTablePtr Pointer to IDT table.
+ @param IdtTableLimit IDT Table limit (number of interrupt entries * 8).
+**/
+VOID
+EFIAPI
+InitializeIdt (
+ IN EFI_CPU_INTERRUPT_HANDLER *TableStart,
+ IN UINTN *IdtTablePtr,
+ IN UINT16 IdtTableLimit
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.S b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.S
new file mode 100644
index 0000000..8dfdbdc
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.S
@@ -0,0 +1,574 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# CpuAsm.S
+#
+# Abstract:
+#
+# Assembly code that supports IA32 CPU architectural protocol
+#
+#------------------------------------------------------------------------------
+
+.data
+
+ExternalVectorTablePtr: .space 4
+CommonInterruptEntry: .long CommonEntry
+Idtr: .space 2
+Idtr1: .space 4
+
+.text
+
+#---------------------------------------;
+# _InitializeIdt ;
+#----------------------------------------------------------------------------;
+#
+# Protocol prototype
+# InitializeIdt (
+# IN EFI_CPU_INTERRUPT_HANDLER TableStart,
+# IN UINTN *IdtTablePtr,
+# IN UINT16 IdtLimit
+# )
+#
+# Routine Description:
+#
+# Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.
+# Table is initialized to intxx where xx is from 00 to number of entries or
+# 100h, whichever is smaller. After table has been initialized the LIDT
+# instruction is invoked.
+#
+# TableStart is the pointer to the callback table and is not used by
+# InitializedIdt but by commonEntry. CommonEntry handles all interrupts,
+# does the context save and calls the callback entry, if non-NULL.
+# It is the responsibility of the callback routine to do hardware EOIs.
+#
+# Arguments:
+#
+# TableStart - Pointer to interrupt callback table
+#
+# IdtTablePtr - Pointer to IDT table
+#
+# IdtLimit - IDT Table limit = number of interrupt entries * 8
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+# [ebp][8] = TableStart
+# [ebp][0c] = *IdtTablePtr
+# [ebp][10] = IdtLimit
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------;
+
+ASM_GLOBAL ASM_PFX(InitializeIdt)
+ASM_PFX(InitializeIdt):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushl %edi
+
+ movl 8(%ebp),%eax # Get ExternalVectorTable Address
+ movl %eax, ExternalVectorTablePtr
+
+ movw 0x10(%ebp),%ax # Get IDT Table limit
+ decw %ax
+ movw %ax, Idtr
+
+ movl 0xc(%ebp),%eax # Get Start of IDT
+ movl %eax, Idtr1
+
+ movl $Idtr, %edi
+ lidt %es:(%edi)
+
+ popl %edi
+ popl %ebp
+ ret
+
+#----------------------------------------------------------------------------;
+#
+# Protocol prototype
+# None
+#
+# Routine Description:
+#
+# These routines handle the individual interrupts. These routines always
+# gain control on any interrupt or exception. They save EAX and place
+# the interrupt number in EAX. CommonEntry is then jumped to.
+# instruction is invoked.
+#
+# CommonEntry handles all interrupts,does the context save and calls the
+# callback entry, if non-NULL. It is the responsibility of the callback
+# routine to do hardware EOIs. Callbacks are entered into the table
+# located at TableStart. Entries are modified by the InstallInterruptHandler
+# and UninstallInterruptHandler protocols.
+#
+# Arguments to CommonEntry:
+#
+# EAX - Interrupt or exception number
+#
+# TableStart - Pointer to interrupt callback table
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------;
+
+TemplateStart:
+ pushl %eax
+
+ #mov eax, 0nnh (nn stands for vector number, which will be fixed at runtime
+ .byte 0xb8
+VectorNumber:
+ .long 0x0
+
+ jmp *CommonInterruptEntry
+TemplateEnd:
+
+CommonEntry:
+
+#---------------------------------------;
+# _CommonEntry ;
+#----------------------------------------------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+# Entry from each interrupt with a push eax and eax=interrupt number
+
+#
+# +---------------------+
+# + EFlags +
+# +---------------------+
+# + CS +
+# +---------------------+
+# + EIP +
+# +---------------------+
+# + Error Code +
+# +---------------------+
+# + EAX / Vector Number +
+# +---------------------+
+# + EBP +
+# +---------------------+ <-- EBP
+#
+
+ cli
+ #
+ # All interrupt handlers are invoked through interrupt gates, so
+ # IF flag automatically cleared at the entry point
+ #
+ cmpl $32,%eax # Intel reserved vector for exceptions?
+ jae NoErrorCode
+ btl %eax, %cs:ASM_PFX(mErrorCodeFlag)
+ jc L1
+
+NoErrorCode:
+ #
+ # Push a dummy error code on the stack
+ # to maintain coherent stack map
+ #
+ pushl (%esp)
+ movl $0, 4(%esp)
+L1:
+ pushl %ebp
+ movl %esp,%ebp
+
+ #
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ # is 16-byte aligned
+ #
+ andl $0xfffffff0,%esp
+ subl $12,%esp
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pushl 0x4(%ebp)
+ pushl %ecx
+ pushl %edx
+ pushl %ebx
+ leal 24(%ebp),%ecx
+ pushl %ecx # ESP
+ pushl (%ebp)
+ pushl %esi
+ pushl %edi
+
+ movl %eax,4(%ebp) # save vector number
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ movl %ss,%eax
+ pushl %eax
+ movzwl 0x10(%ebp), %eax
+ pushl %eax
+ movl %ds,%eax
+ pushl %eax
+ movl %es,%eax
+ pushl %eax
+ movl %fs,%eax
+ pushl %eax
+ movl %gs,%eax
+ pushl %eax
+
+## UINT32 Eip;
+ pushl 12(%ebp)
+
+## UINT32 Gdtr[2], Idtr[2];
+ subl $8,%esp
+ sidt (%esp)
+ subl $8,%esp
+ sgdt (%esp)
+
+## UINT32 Ldtr, Tr;
+ xorl %eax,%eax
+ strl %eax
+ pushl %eax
+ sldtl %eax
+ pushl %eax
+
+## UINT32 EFlags;
+ pushl 20(%ebp)
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ movl %cr4, %eax
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ xorl %eax,%eax
+ pushl %eax
+ movl %cr0, %eax
+ pushl %eax
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movl %dr7, %eax
+ pushl %eax
+ movl %dr6, %eax
+ pushl %eax
+ movl %dr3, %eax
+ pushl %eax
+ movl %dr2, %eax
+ pushl %eax
+ movl %dr1, %eax
+ pushl %eax
+ movl %dr0, %eax
+ pushl %eax
+
+## UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+## UINT32 ExceptionData;
+ pushl 8(%ebp)
+
+## call into exception handler
+ movl 4(%ebp),%ebx
+ movl ExternalVectorTablePtr, %eax
+ movl (%eax,%ebx,4),%eax
+ orl %eax,%eax # NULL?
+ je nonNullValue #
+
+## Prepare parameter and call
+ movl %esp,%edx
+ pushl %edx
+ pushl %ebx
+ call *%eax
+ addl $8,%esp
+
+nonNullValue:
+ cli
+## UINT32 ExceptionData;
+ addl $4,%esp
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+## Skip restoration of DRx registers to support in-circuit emualators
+## or debuggers set breakpoint in interrupt/exception context
+ addl $24, %esp
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ popl %eax
+ movl %eax, %cr0
+ addl $4,%esp # not for Cr1
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, %cr3
+ popl %eax
+ movl %eax, %cr4
+
+## UINT32 EFlags;
+ popl 20(%ebp)
+
+## UINT32 Ldtr, Tr;
+## UINT32 Gdtr[2], Idtr[2];
+## Best not let anyone mess with these particular registers...
+ addl $24,%esp
+
+## UINT32 Eip;
+ pop 12(%ebp)
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+## NOTE - modified segment registers could hang the debugger... We
+## could attempt to insulate ourselves against this possibility,
+## but that poses risks as well.
+##
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popl 16(%ebp)
+ popl %ss
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ popl %edi
+ popl %esi
+ addl $4,%esp # not for ebp
+ addl $4,%esp # not for esp
+ popl %ebx
+ popl %edx
+ popl %ecx
+ popl %eax
+
+ movl %ebp,%esp
+ popl %ebp
+ addl $8,%esp
+ iretl
+
+
+#---------------------------------------;
+# _GetTemplateAddressMap ;
+#----------------------------------------------------------------------------;
+#
+# Protocol prototype
+# GetTemplateAddressMap (
+# INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap
+# );
+#
+# Routine Description:
+#
+# Return address map of interrupt handler template so that C code can generate
+# interrupt handlers, and dynamically do address fix.
+#
+# Arguments:
+#
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------;
+ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)
+ASM_PFX(GetTemplateAddressMap):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushal
+
+ movl 8(%ebp), %ebx
+ movl $TemplateStart, (%ebx)
+ movl $(TemplateEnd - TemplateStart), 4(%ebx)
+
+ # Note: if code in Template is updated, the value fills into the 3rd parameter
+ # also needs update
+ movl $(VectorNumber - TemplateStart), 8(%ebx)
+
+ popal
+ popl %ebp
+ ret
+
+
+
+#---------------------------------------;
+# _InitializeSelectors ;
+#----------------------------------------------------------------------------;
+#
+# Protocol prototype
+# InitializeSelectors (
+# )
+#
+# Routine Description:
+#
+# Creates an new GDT in RAM. The problem is that our former selectors
+# were ROM based and the EFI OS Loader does not manipulate the machine state
+# to change them (as it would for a 16-bit PC/AT startup code that had to
+# go from Real Mode to flat mode).
+#
+# Arguments:
+#
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------;
+
+.equ CODE_SELECTOR, 0x10
+.equ DATA_SELECTOR, 0x18
+
+ASM_GLOBAL ASM_PFX(InitializeGdt)
+ASM_PFX(InitializeGdt):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushal
+ movl $Gdtr, %edi
+
+ movw %cs,%ax # Get the selector data from our code image
+ .byte 0x66
+ movw %ax,%es
+ lgdt %es:(%edi)
+
+ .byte 0x67
+ .byte 0xea # Far Jump Offset:Selector to reload CS
+ .long SelectorRld
+ .word CODE_SELECTOR
+SelectorRld:
+ movw $DATA_SELECTOR, %ax # Update the Base for the new selectors, too
+ .byte 0x66
+ movw %ax,%ds
+ .byte 0x66
+ movw %ax,%es
+ .byte 0x66
+ movw %ax,%fs
+ .byte 0x66
+ movw %ax,%gs
+ .byte 0x66
+ movw %ax,%ss
+
+ popal
+ popl %ebp
+ ret
+
+#-----------------------------------------------------------------------------;
+# data
+#-----------------------------------------------------------------------------;
+
+ .p2align 4
+
+Gdtr: .word GDT_END - GDT_BASE - 1
+ .long GDT_BASE
+
+#-----------------------------------------------------------------------------;
+# global descriptor table (GDT)
+#-----------------------------------------------------------------------------;
+
+ .p2align 4
+
+GDT_BASE:
+# null descriptor
+# .equ NULL_SEL, $-GDT_BASE # Selector [0]
+ .word 0 # limit 15:0
+ .word 0 # base 15:0
+ .byte 0 # base 23:16
+ .byte 0 # type
+ .byte 0 # limit 19:16, flags
+ .byte 0 # base 31:24
+
+# linear data segment descriptor
+# .equ LINEAR_SEL, $-GDT_BASE # Selector [0x8]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# linear code segment descriptor
+# .equ LINEAR_CODE_SEL, $-GDT_BASE # Selector [0x10]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system data segment descriptor
+# .equ SYS_DATA_SEL, $-GDT_BASE # Selector [0x18]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system code segment descriptor
+# .equ SYS_CODE_SEL, $-GDT_BASE
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE3_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE4_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE5_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+GDT_END:
+
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.asm b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.asm
new file mode 100644
index 0000000..bce50c6
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.asm
@@ -0,0 +1,588 @@
+ page ,132
+ title CPU ARCHITECTURAL DXE PROTOCOL ASSEMBLY HOOKS
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; CpuAsm.asm
+;
+; Abstract:
+;
+; Assembly code that supports IA32 CPU architectural protocol
+;
+;------------------------------------------------------------------------------
+
+.686p
+.model flat
+
+.data
+ExternalVectorTablePtr DD ? ; Table of call backs
+CommonInterruptEntry DD CommonEntry ; Address of CommonEntry
+Idtr DW ? ; FWORD for IDT register
+Idtr1 DD ? ; MUST BE IMMEDIATELY AFTER Idtr
+
+EXTRN _mErrorCodeFlag:DWORD ; Error code flags for exceptions
+
+.stack
+.code
+.MMX
+.XMM
+
+UINT8 TYPEDEF BYTE
+UINT16 TYPEDEF WORD
+UINT32 TYPEDEF DWORD
+UINT64 TYPEDEF QWORD
+UINTN TYPEDEF UINT32
+
+;---------------------------------------;
+; _InitializeIdt ;
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; InitializeIdt (
+; IN EFI_CPU_INTERRUPT_HANDLER TableStart,
+; IN UINTN *IdtTablePtr,
+; IN UINT16 IdtLimit
+; )
+;
+; Routine Description:
+;
+; Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.
+; Table is initialized to intxx where xx is from 00 to number of entries or
+; 100h, whichever is smaller. After table has been initialized the LIDT
+; instruction is invoked.
+;
+; TableStart is the pointer to the callback table and is not used by
+; InitializedIdt but by commonEntry. CommonEntry handles all interrupts,
+; does the context save and calls the callback entry, if non-NULL.
+; It is the responsibility of the callback routine to do hardware EOIs.
+;
+; Arguments:
+;
+; TableStart - Pointer to interrupt callback table
+;
+; IdtTablePtr - Pointer to IDT table
+;
+; IdtLimit - IDT Table limit = number of interrupt entries * 8
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Input: [ebp][0] = Original ebp
+; [ebp][4] = Return address
+; [ebp][8] = TableStart
+; [ebp][0c] = *IdtTablePtr
+; [ebp][10] = IdtLimit
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+
+_InitializeIdt proc near public
+ push ebp ; C prolog
+ mov ebp, esp
+ push edi
+
+ mov eax, [ebp+8] ; Get ExternalVectorTable Address
+ mov ExternalVectorTablePtr, eax
+
+ mov ax, [ebp+10h] ; Get IDT Table limit
+ dec ax
+ mov Idtr, ax
+
+ mov eax, [ebp+0ch] ; Get Start of IDT
+ mov Idtr1, eax
+
+ mov edi, OFFSET Idtr ; Load IDT register
+ lidt FWORD PTR es:[edi]
+
+ pop edi
+ pop ebp
+ ret
+_InitializeIdt endp
+
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; None
+;
+; Routine Description:
+;
+; These routines handle the individual interrupts. These routines always
+; gain control on any interrupt or exception. They save EAX and place
+; the interrupt number in EAX. CommonEntry is then jumped to.
+; instruction is invoked.
+;
+; CommonEntry handles all interrupts,does the context save and calls the
+; callback entry, if non-NULL. It is the responsibility of the callback
+; routine to do hardware EOIs. Callbacks are entered into the table
+; located at TableStart. Entries are modified by the InstallInterruptHandler
+; and UninstallInterruptHandler protocols.
+;
+; Arguments to CommonEntry:
+;
+; EAX - Interrupt or exception number
+;
+; TableStart - Pointer to interrupt callback table
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+
+TemplateStart:
+ push eax
+
+ ;mov eax, 0nnh (nn stands for vector number, which will be fixed at runtime
+ DB 0b8h
+VectorNumber:
+ DD 00h
+
+ jmp dword ptr [CommonInterruptEntry];
+TemplateEnd:
+
+CommonEntry:
+
+;---------------------------------------;
+; _CommonEntry ;
+;----------------------------------------------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+; Entry from each interrupt with a push eax and eax=interrupt number
+
+;
+; +---------------------+
+; + EFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + EIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + EAX / Vector Number +
+; +---------------------+
+; + EBP +
+; +---------------------+ <-- EBP
+;
+
+ cli
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+ cmp eax, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt cs:_mErrorCodeFlag, eax
+ jc @F
+
+NoErrorCode:
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push [esp]
+ mov dword ptr [esp + 4], 0
+@@:
+ push ebp
+ mov ebp, esp
+
+ ;
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ ; is 16-byte aligned
+ ;
+ and esp, 0fffffff0h
+ sub esp, 12
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ push dword ptr [ebp + 4] ; EAX
+ push ecx
+ push edx
+ push ebx
+ lea ecx, [ebp + 24]
+ push ecx ; ESP
+ push dword ptr [ebp] ; EBP
+ push esi
+ push edi
+
+ mov [ebp + 4], eax ; save vector number
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ mov eax, ss
+ push eax
+ movzx eax, word ptr [ebp + 16]
+ push eax
+ mov eax, ds
+ push eax
+ mov eax, es
+ push eax
+ mov eax, fs
+ push eax
+ mov eax, gs
+ push eax
+
+;; UINT32 Eip;
+ push dword ptr [ebp + 12]
+
+;; UINT32 Gdtr[2], Idtr[2];
+ sub esp, 8
+ sidt fword ptr [esp]
+ sub esp, 8
+ sgdt fword ptr [esp]
+
+;; UINT32 Ldtr, Tr;
+ xor eax, eax
+ str ax
+ push eax
+ sldt ax
+ push eax
+
+;; UINT32 EFlags;
+ push dword ptr [ebp + 20]
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ mov eax, cr4
+ push eax
+ mov eax, cr3
+ push eax
+ mov eax, cr2
+ push eax
+ xor eax, eax
+ push eax
+ mov eax, cr0
+ push eax
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov eax, dr7
+ push eax
+ mov eax, dr6
+ push eax
+ mov eax, dr3
+ push eax
+ mov eax, dr2
+ push eax
+ mov eax, dr1
+ push eax
+ mov eax, dr0
+ push eax
+
+;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push dword ptr [ebp + 8]
+
+;; call into exception handler
+ mov ebx, [ebp + 4]
+ mov eax, ExternalVectorTablePtr
+ mov eax, [eax + ebx * 4]
+ or eax, eax ; NULL?
+ je nonNullValue;
+
+;; Prepare parameter and call
+ mov edx, esp
+ push edx
+ push ebx
+ call eax
+ add esp, 8
+
+nonNullValue:
+ cli
+;; UINT32 ExceptionData;
+ add esp, 4
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add esp, 4 * 6
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop eax
+ mov cr0, eax
+ add esp, 4 ; not for Cr1
+ pop eax
+ mov cr2, eax
+ pop eax
+ mov cr3, eax
+ pop eax
+ mov cr4, eax
+
+;; UINT32 EFlags;
+ pop dword ptr [ebp + 20]
+
+;; UINT32 Ldtr, Tr;
+;; UINT32 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add esp, 24
+
+;; UINT32 Eip;
+ pop dword ptr [ebp + 12]
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+;; NOTE - modified segment registers could hang the debugger... We
+;; could attempt to insulate ourselves against this possibility,
+;; but that poses risks as well.
+;;
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ pop dword ptr [ebp + 16]
+ pop ss
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pop edi
+ pop esi
+ add esp, 4 ; not for ebp
+ add esp, 4 ; not for esp
+ pop ebx
+ pop edx
+ pop ecx
+ pop eax
+
+ mov esp, ebp
+ pop ebp
+ add esp, 8
+ iretd
+
+
+;---------------------------------------;
+; _GetTemplateAddressMap ;
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; GetTemplateAddressMap (
+; INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap
+; );
+;
+; Routine Description:
+;
+; Return address map of interrupt handler template so that C code can generate
+; interrupt handlers, and dynamically do address fix.
+;
+; Arguments:
+;
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Input: [ebp][0] = Original ebp
+; [ebp][4] = Return address
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+_GetTemplateAddressMap proc near public
+ push ebp ; C prolog
+ mov ebp, esp
+ pushad
+
+ mov ebx, dword ptr [ebp+08h]
+ mov dword ptr [ebx], TemplateStart
+ mov dword ptr [ebx+4h], TemplateEnd - TemplateStart
+
+ ; if code in Template is updated, the value fills into the 3rd parameter
+ ; also needs update
+ mov dword ptr [ebx+8h], VectorNumber - TemplateStart
+
+ popad
+ pop ebp
+ ret
+_GetTemplateAddressMap endp
+
+
+
+;---------------------------------------;
+; _InitializeSelectors ;
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; InitializeSelectors (
+; )
+;
+; Routine Description:
+;
+; Creates an new GDT in RAM. The problem is that our former selectors
+; were ROM based and the EFI OS Loader does not manipulate the machine state
+; to change them (as it would for a 16-bit PC/AT startup code that had to
+; go from Real Mode to flat mode).
+;
+; Arguments:
+;
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Input: [ebp][0] = Original ebp
+; [ebp][4] = Return address
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+
+CODE_SELECTOR EQU 10h
+DATA_SELECTOR EQU 18h
+
+_InitializeGdt proc near public
+ push ebp ; C prolog
+ mov ebp, esp
+ pushad
+ mov edi, OFFSET Gdtr ; Load GDT register
+
+ mov ax,cs ; Get the selector data from our code image
+ mov es,ax
+ lgdt FWORD PTR es:[edi] ; and update the GDTR
+
+ db 067h
+ db 0eah ; Far Jump Offset:Selector to reload CS
+ dd OFFSET SelectorRld; Offset is ensuing instruction boundary
+ dw CODE_SELECTOR ; Selector is our code selector, 10h
+SelectorRld::
+ mov ax, DATA_SELECTOR ; Update the Base for the new selectors, too
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ popad
+ pop ebp
+ ret
+_InitializeGdt endp
+
+;-----------------------------------------------------------------------------;
+; data
+;-----------------------------------------------------------------------------;
+
+;.data
+ align 16
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd OFFSET GDT_BASE ; (GDT base gets set above)
+
+;-----------------------------------------------------------------------------;
+; global descriptor table (GDT)
+;-----------------------------------------------------------------------------;
+
+ align 16
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; 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 09Ah ; present, ring 0, data, expand-up, 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 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ 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
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+
+ end
+
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/Exception.c b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/Exception.c
new file mode 100644
index 0000000..1c1f12d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/Exception.c
@@ -0,0 +1,329 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Exception.c
+
+Abstract:
+
+ IA-32 Exception Handler.
+
+**/
+
+#include "Cpu.h"
+#include "Exception.h"
+
+//
+// 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_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_IA32),
+ { 0 }
+ },
+ {
+ {0}
+ }
+};
+
+/**
+ Reports StatusCode for Exception
+
+ This function reports status code for exception.
+
+ @param InterruptType Interrupt type
+ @param SystemContext EFI_SYSTEM_CONTEXT
+
+**/
+VOID
+ReportData (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 ErrorMessage;
+ UINT32 Index;
+
+ CopyMem (
+ &mStatusCodeData.SystemContext.SystemContextIa32,
+ SystemContext.SystemContextIa32,
+ sizeof (EFI_SYSTEM_CONTEXT_IA32)
+ );
+
+ ErrorMessage = EFI_SOFTWARE_DXE_BS_DRIVER;
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ if (mExceptionTable[Index].Interrupt == InterruptType) {
+ ErrorMessage |= mExceptionTable[Index].ErrorMessage;
+ break;
+ }
+ }
+
+ REPORT_STATUS_CODE_EX (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ EFI_SOFTWARE_UNSPECIFIED | ErrorMessage,
+ 0,
+ NULL,
+ NULL,
+ (UINT8 *)&mStatusCodeData + sizeof (EFI_STATUS_CODE_DATA),
+ sizeof (EFI_SYSTEM_CONTEXT_IA32)
+ );
+}
+
+/**
+ Common exception handler.
+
+ @param InterruptType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! IA32 Exception Type - %08x !!!!\n",
+ InterruptType
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->Cs,
+ SystemContext.SystemContextIa32->Eflags
+ ));
+ if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %08x\n",
+ SystemContext.SystemContextIa32->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
+ SystemContext.SystemContextIa32->Eax,
+ SystemContext.SystemContextIa32->Ecx,
+ SystemContext.SystemContextIa32->Edx,
+ SystemContext.SystemContextIa32->Ebx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
+ SystemContext.SystemContextIa32->Esp,
+ SystemContext.SystemContextIa32->Ebp,
+ SystemContext.SystemContextIa32->Esi,
+ SystemContext.SystemContextIa32->Edi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
+ SystemContext.SystemContextIa32->Ds,
+ SystemContext.SystemContextIa32->Es,
+ SystemContext.SystemContextIa32->Fs,
+ SystemContext.SystemContextIa32->Gs,
+ SystemContext.SystemContextIa32->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDTR - %08x %08x, IDTR - %08x %08x\n",
+ SystemContext.SystemContextIa32->Gdtr[0],
+ SystemContext.SystemContextIa32->Gdtr[1],
+ SystemContext.SystemContextIa32->Idtr[0],
+ SystemContext.SystemContextIa32->Idtr[1]
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "LDTR - %08x, TR - %08x\n",
+ SystemContext.SystemContextIa32->Ldtr,
+ SystemContext.SystemContextIa32->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
+ SystemContext.SystemContextIa32->Cr0,
+ SystemContext.SystemContextIa32->Cr2,
+ SystemContext.SystemContextIa32->Cr3,
+ SystemContext.SystemContextIa32->Cr4
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
+ SystemContext.SystemContextIa32->Dr0,
+ SystemContext.SystemContextIa32->Dr1,
+ SystemContext.SystemContextIa32->Dr2,
+ SystemContext.SystemContextIa32->Dr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR6 - %08x, DR7 - %08x\n",
+ SystemContext.SystemContextIa32->Dr6,
+ SystemContext.SystemContextIa32->Dr7
+ ));
+
+ //
+ // Report Status Code
+ //
+ ReportData (InterruptType, SystemContext);
+
+ //
+ // Enter a dead loop.
+ //
+ CpuDeadLoop ();
+
+ return ;
+}
+
+/**
+ Installs the Exception Handler.
+
+ This function installs the Exception Handler.
+
+ @param ExceptionBegin The begin number of exception
+
+**/
+VOID
+InitializeException (
+ IN UINT32 ExceptionBegin
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ BOOLEAN OldInterruptState;
+
+ //
+ // Disable interrupt
+ //
+ OldInterruptState = SaveAndDisableInterrupts ();
+
+ for (Index = ExceptionBegin; Index < mExceptionNumber; Index++) {
+ //
+ // Register sample excception handler
+ //
+ Status = mCpuArchProtocol.RegisterInterruptHandler (
+ &mCpuArchProtocol,
+ mExceptionTable[Index].Interrupt,
+ CommonExceptionHandler
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // Restore interrupt state.
+ //
+ SetInterruptState (OldInterruptState);
+}
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.c b/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.c
new file mode 100644
index 0000000..cb1ebb1
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.c
@@ -0,0 +1,463 @@
+/** @file
+
+ Code for memory attribute setting
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MemoryAttribute.c
+
+**/
+
+#include "Cpu.h"
+
+FIXED_MTRR mFixedMtrrTable[] = {
+ {
+ MTRR_LIB_IA32_MTRR_FIX64K_00000,
+ 0,
+ 0x10000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_80000,
+ 0x80000,
+ 0x4000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_A0000,
+ 0xA0000,
+ 0x4000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C0000,
+ 0xC0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C8000,
+ 0xC8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D0000,
+ 0xD0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D8000,
+ 0xD8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E0000,
+ 0xE0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E8000,
+ 0xE8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F0000,
+ 0xF0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F8000,
+ 0xF8000,
+ 0x1000
+ },
+};
+
+/**
+ Gets GCD Mem Space type from MTRR Type.
+
+ This function gets GCD Mem Space type from MTRR Type
+
+ @param MtrrAttributes MTRR memory type
+
+ @return GCD Mem Space type
+
+**/
+UINT64
+GetMemorySpaceAttributeFromMtrrType (
+ IN UINT8 MtrrAttributes
+ )
+{
+ switch (MtrrAttributes) {
+ case MTRR_CACHE_UNCACHEABLE:
+ return EFI_MEMORY_UC;
+ case MTRR_CACHE_WRITE_COMBINING:
+ return EFI_MEMORY_WC;
+ case MTRR_CACHE_WRITE_THROUGH:
+ return EFI_MEMORY_WT;
+ case MTRR_CACHE_WRITE_PROTECTED:
+ return EFI_MEMORY_WP;
+ case MTRR_CACHE_WRITE_BACK:
+ return EFI_MEMORY_WB;
+ default:
+ return 0;
+ }
+}
+
+/**
+ Initializes the valid bits mask and valid address mask for MTRRs.
+
+ This function initializes the valid bits mask and valid address mask for MTRRs.
+
+**/
+VOID
+InitializeMtrrMask (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+
+ PhysicalAddressBits = (UINT8) RegEax;
+
+ mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
+ mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;
+ } else {
+ mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;
+ mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
+ }
+}
+
+/**
+ Searches memory descriptors covered by given memory range.
+
+ This function searches into the Gcd Memory Space for descriptors (from StartIndex
+ to EndIndex) that contains the memory range specified by BaseAddress
+ and Length.
+
+ @param MemorySpaceMap Gcd Memory Space Map as array.
+ @param NumberOfDescriptors Number of descriptors in map.
+ @param BaseAddress BaseAddress for the requested range.
+ @param Length Length for the requested range.
+ @param StartIndex Start index into the Gcd Memory Space Map.
+ @param EndIndex End index into the Gcd Memory Space Map.
+
+ @retval EFI_SUCCESS Search successfully.
+ @retval EFI_NOT_FOUND The requested descriptors does 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;
+}
+
+/**
+ Sets the attributes for a specified range in Gcd Memory Space Map.
+
+ This function sets the attributes for a specified range in Gcd Memory Space Map.
+
+ @param MemorySpaceMap Gcd Memory Space Map as array
+ @param NumberOfDescriptors Number of descriptors in map
+ @param BaseAddress BaseAddress for the range
+ @param Length Length for the range
+ @param Attributes Attributes to set
+
+ @retval EFI_SUCCESS Memory attributes 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;
+
+ //
+ // Get all memory descriptors covered by the memory range
+ //
+ Status = SearchGcdMemorySpaces (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ &StartIndex,
+ &EndIndex
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Go through all related descriptors and set attributes accordingly
+ //
+ for (Index = StartIndex; Index <= EndIndex; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+ //
+ // Calculate the start and end address of the overlapping range
+ //
+ 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;
+ }
+ //
+ // Set memory attributes according to MTRR attribute and the original attribute of descriptor
+ //
+ gDS->SetMemorySpaceAttributes (
+ RegionStart,
+ RegionLength,
+ (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Refreshes the GCD Memory Space attributes according to MTRRs.
+
+ This function refreshes the GCD Memory Space attributes according to MTRRs.
+
+**/
+VOID
+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;
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ MTRR_FIXED_SETTINGS MtrrFixedSettings;
+ UINTN FirmwareVariableMtrrCount;
+ UINT8 DefaultMemoryType;
+
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
+
+ mIsFlushingGCD = TRUE;
+ MemorySpaceMap = NULL;
+
+ //
+ // Initialize the valid bits mask and valid address mask for MTRRs
+ //
+ InitializeMtrrMask ();
+
+ //
+ // Get the memory attribute of variable MTRRs
+ //
+ MtrrGetMemoryAttributeInVariableMtrr (
+ mValidMtrrBitsMask,
+ mValidMtrrAddressMask,
+ VariableMtrr
+ );
+
+ //
+ // Get the memory space map from GCD
+ //
+ Status = gDS->GetMemorySpaceMap (
+ &NumberOfDescriptors,
+ &MemorySpaceMap
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DefaultMemoryType = (UINT8) MtrrGetDefaultMemoryType ();
+ DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);
+
+ //
+ // 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 with WB attribute
+ //
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
+ if (VariableMtrr[Index].Valid &&
+ VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ VariableMtrr[Index].BaseAddress,
+ VariableMtrr[Index].Length,
+ EFI_MEMORY_WB
+ );
+ }
+ }
+ //
+ // Go for variable MTRRs with the attribute except for WB and UC attributes
+ //
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
+ if (VariableMtrr[Index].Valid &&
+ VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK &&
+ VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE) {
+ Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ VariableMtrr[Index].BaseAddress,
+ VariableMtrr[Index].Length,
+ Attributes
+ );
+ }
+ }
+ //
+ // Go for variable MTRRs with UC attribute
+ //
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
+ if (VariableMtrr[Index].Valid &&
+ VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ VariableMtrr[Index].BaseAddress,
+ VariableMtrr[Index].Length,
+ EFI_MEMORY_UC
+ );
+ }
+ }
+
+ //
+ // Go for fixed MTRRs
+ //
+ Attributes = 0;
+ BaseAddress = 0;
+ Length = 0;
+ MtrrGetFixedMtrr (&MtrrFixedSettings);
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ RegValue = MtrrFixedSettings.Mtrr[Index];
+ //
+ // Check for continuous fixed MTRR sections
+ //
+ for (SubIndex = 0; SubIndex < 8; SubIndex++) {
+ MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);
+ CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);
+ if (Length == 0) {
+ //
+ // A new MTRR attribute begins
+ //
+ Attributes = CurrentAttributes;
+ } else {
+ //
+ // If fixed MTRR attribute changed, then set memory attribute for previous atrribute
+ //
+ 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 fixed MTRR region
+ //
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+
+ //
+ // Free memory space map allocated by GCD service GetMemorySpaceMap ()
+ //
+ if (MemorySpaceMap != NULL) {
+ FreePool (MemorySpaceMap);
+ }
+
+ mIsFlushingGCD = FALSE;
+}
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.h b/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.h
new file mode 100644
index 0000000..7b338c1
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.h
@@ -0,0 +1,50 @@
+/** @file
+
+ Include file for memory attribute setting
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MemoryAttribute.h
+
+**/
+
+#ifndef _EFI_MEMORY_ATTRIB_H_
+#define _EFI_MEMORY_ATTRIB_H_
+
+#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | \
+ EFI_MEMORY_WC | \
+ EFI_MEMORY_WT | \
+ EFI_MEMORY_WB | \
+ EFI_MEMORY_UCE \
+ )
+
+extern BOOLEAN mIsFlushingGCD;
+
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.c b/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.c
new file mode 100644
index 0000000..7e9678e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.c
@@ -0,0 +1,113 @@
+/** @file
+
+ Code for MTRR synchronzation.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MtrrSync.c
+
+**/
+
+#include "Cpu.h"
+
+MTRR_SETTINGS *mMtrrTable;
+
+/**
+ Initialize memory region for MTRR data.
+
+ This function allocates ACPI NVS memory for MTRR data.
+ Each time MTRRs are written, this memory region will be updated accordingly.
+
+**/
+VOID
+InitializeMtrrData (
+ VOID
+ )
+{
+ //
+ // Allocate memory for fixed MTRRs, variable MTRRs and MTRR_DEF_TYPE
+ //
+ mMtrrTable = AllocateAcpiNvsMemoryBelow4G (sizeof (MTRR_SETTINGS));
+
+ PcdSet64 (PcdCpuMtrrTableAddress, (UINT64) (UINTN) mMtrrTable);
+}
+
+/**
+ Synchronzies up the MTRR values with BSP for calling processor.
+
+ This function synchronzies up the MTRR values with BSP for calling processor.
+
+ @param Buffer Mtrr table address.
+
+**/
+VOID
+EFIAPI
+LoadMtrrData (
+ VOID *Buffer
+ )
+{
+ MtrrSetAllMtrrs (mMtrrTable);
+}
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+ @param Size Size of memory to allocate.
+
+ @return Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+ IN UINTN Size
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ VOID* Buffer;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xffffffff;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &Address
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Buffer = (VOID *) (UINTN) Address;
+ ZeroMem (Buffer, Size);
+
+ return Buffer;
+}
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.h b/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.h
new file mode 100644
index 0000000..e6fb549
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.h
@@ -0,0 +1,85 @@
+/** @file
+
+ Include file for MTRR synchronzation.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MtrrSync.h
+
+**/
+
+#ifndef _EFI_MTRR_SYNC_H_
+#define _EFI_MTRR_SYNC_H_
+
+#include "Cpu.h"
+
+extern MTRR_SETTINGS *mMtrrTable;
+
+/**
+ Initialize memory region for MTRR data.
+
+ This function allocates ACPI NVS memory for MTRR data, and fills the region
+ with current MTRR data. Each time MTRRs are written, this memory region
+ will be updated accordingly.
+
+**/
+VOID
+InitializeMtrrData (
+ VOID
+ );
+
+/**
+ Synchronzies up the MTRR values with BSP for calling processor.
+
+ This function synchronzies up the MTRR values with BSP for calling processor.
+
+ @param Buffer Mtrr table address.
+
+**/
+VOID
+EFIAPI
+LoadMtrrData (
+ VOID *Buffer
+ );
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+ @param Size Size of memory to allocate.
+
+ @return Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+ IN UINTN Size
+ );
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Analysis.c b/IA32FamilyCpuBasePkg/CpuMpDxe/Analysis.c
new file mode 100644
index 0000000..8921e60
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Analysis.c
@@ -0,0 +1,197 @@
+/** @file
+ Code for Analysis phase.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Analysis.c
+
+**/
+
+#include "Cpu.h"
+#include "Feature.h"
+
+/**
+ Configures Processor Feature List for all processors.
+
+ This function configures Processor Feature List for all processors.
+
+**/
+VOID
+ConfigProcessorFeatureList (
+ VOID
+ )
+{
+ //
+ // Configure Feature List for Max CPUID Value Limit
+ //
+ if (FeaturePcdGet (PcdCpuMaxCpuIDValueLimitFlag)) {
+ MaxCpuidLimitConfigFeatureList ();
+ }
+ //
+ // Configure Feature List for execute disable bit
+ //
+ if (FeaturePcdGet (PcdCpuExecuteDisableBitFlag)) {
+ XdConfigFeatureList ();
+ }
+}
+
+/**
+ Produces Register Tables for all processors.
+
+ This function produces Register Tables for all processors.
+
+**/
+VOID
+ProduceRegisterTable (
+ VOID
+ )
+{
+
+ UINTN ProcessorNumber;
+ UINT8 Index;
+ CPU_FEATURE_ID FeatureID;
+ VOID *Attribute;
+
+ //
+ // Parse Processor Feature Lists and translate to Register Tables for all processors.
+ //
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+
+ //
+ // Traverse Processor Feature List for this logical processor.
+ //
+ Index = 1;
+ FeatureID = GetProcessorFeatureEntry (ProcessorNumber, Index, &Attribute);
+ Index++;
+ while (FeatureID != CpuFeatureMaximum) {
+
+ switch (FeatureID) {
+
+ case MaxCpuidValueLimit:
+ if (FeaturePcdGet (PcdCpuMaxCpuIDValueLimitFlag)) {
+ MaxCpuidLimitReg (ProcessorNumber, Attribute);
+ }
+ break;
+
+ case ExecuteDisableBit:
+ if (FeaturePcdGet (PcdCpuExecuteDisableBitFlag)) {
+ XdReg (ProcessorNumber, Attribute);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ FeatureID = GetProcessorFeatureEntry (ProcessorNumber, Index, &Attribute);
+ Index++;
+ }
+ }
+}
+
+/**
+ Produces Pre-SMM-Init Register Tables for all processors.
+
+ This function produces Pre-SMM-Init Register Tables for all processors.
+
+**/
+VOID
+ProducePreSmmInitRegisterTable (
+ VOID
+ )
+{
+ UINTN ProcessorNumber;
+ UINT32 ApicId;
+
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+ ApicId = mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData.InitialApicID;
+ mCpuConfigConextBuffer.PreSmmInitRegisterTable[ProcessorNumber].InitialApicId = ApicId;
+ }
+}
+
+/**
+ Produces register table according to output of Data Collection phase.
+
+ This function produces register table according to output of Data Collection phase.
+
+**/
+VOID
+AnalysisPhase (
+ VOID
+ )
+{
+ UINTN Index;
+ UINTN ProcessorNumber;
+ CPU_REGISTER_TABLE *RegisterTable;
+ CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
+ UINT8 CallbackSignalValue;
+
+ //
+ // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back.
+ //
+ CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_PROCESSOR_FEATURE_LIST_CONFIG_SIGNAL);
+ //
+ // Checks whether the callback function requests to bypass Processor Feature List configuration.
+ //
+ if (CallbackSignalValue != CPU_BYPASS_SIGNAL) {
+ //
+ // Configure Processor Feature List for all logical processors.
+ //
+ ConfigProcessorFeatureList ();
+ }
+
+ //
+ // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back.
+ //
+ CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_REGISTER_TABLE_TRANSLATION_SIGNAL);
+ //
+ // Checks whether the callback function requests to bypass Register Table translation.
+ //
+ if (CallbackSignalValue != CPU_BYPASS_SIGNAL) {
+ //
+ // Produce register tables for all logical processors.
+ //
+ ProduceRegisterTable ();
+ }
+
+ //
+ // Debug information
+ //
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+
+ RegisterTable = &mCpuConfigConextBuffer.RegisterTable[ProcessorNumber];
+ for (Index = 0; Index < RegisterTable->TableLength; Index++) {
+ RegisterTableEntry = &RegisterTable->RegisterTableEntry[Index];
+ DEBUG ((EFI_D_INFO, "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n", ProcessorNumber, RegisterTableEntry->Index, RegisterTableEntry->ValidBitStart, RegisterTableEntry->ValidBitLength, RegisterTableEntry->Value));
+ }
+ }
+ DEBUG ((EFI_D_INFO, "Capability: %8x\r\n", PcdGet32 (PcdCpuProcessorFeatureCapability)));
+ DEBUG ((EFI_D_INFO, "Configuration: %8x\r\n", PcdGet32 (PcdCpuProcessorFeatureUserConfiguration)));
+ DEBUG ((EFI_D_INFO, "Setting: %8x\r\n", PcdGet32 (PcdCpuProcessorFeatureSetting)));
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Cpu.h b/IA32FamilyCpuBasePkg/CpuMpDxe/Cpu.h
new file mode 100644
index 0000000..ad36c9d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Cpu.h
@@ -0,0 +1,298 @@
+/** @file
+
+ Include file for CPU DXE Module
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Cpu.h
+
+**/
+
+#ifndef _CPU_DXE_H_
+#define _CPU_DXE_H_
+
+#include "MpCommon.h"
+
+#define PLATFORM_DESKTOP 0
+#define PLATFORM_MOBILE 1
+#define PLATFORM_SERVER 2
+
+#define EFI_CPUID_CORE_TOPOLOGY 0x0B
+
+//
+// The definitions below follow the naming rules.
+// Definitions beginning with "B_" are bits within registers
+// Definitions beginning with "N_" are the bit position
+// Definitions with "_CPUID_" are CPUID bit fields
+// Definitions with "_MSR_" are MSR bit fields
+// Definitions with "N_*_START" are the bit start position
+// Definitions with "N_*_STOP" are the bit stop position
+// Definitions with "B_*_MASK" are the bit mask for the register values
+//
+
+//
+// Bit definitions for CPUID EAX = 1
+//
+// ECX
+#define N_CPUID_MONITOR_MWAIT_SUPPORT 3
+#define N_CPUID_VMX_SUPPORT 5
+#define N_CPUID_SMX_SUPPORT 6
+#define N_CPUID_EIST_SUPPORT 7
+#define N_CPUID_TM2_SUPPORT 8
+#define N_CPUID_DCA_SUPPORT 18
+#define N_CPUID_X2APIC_SUPPORT 21
+#define N_CPUID_AESNI_SUPPORT 25
+// EDX
+#define N_CPUID_MCE_SUPPORT 7
+#define N_CPUID_MCA_SUPPORT 14
+#define N_CPUID_TM_SUPPORT 29
+#define N_CPUID_PBE_SUPPORT 31
+
+//
+// Bit definitions for CPUID EAX = 80000001h
+//
+// EDX
+#define N_CPUID_XD_BIT_AVAILABLE 20
+
+//
+// Bit definitions for MSR_IA32_APIC_BASE (ECX = 1Bh)
+//
+#define N_MSR_BSP_FLAG 8
+#define B_MSR_ENABLE_X2APIC_MODE BIT10
+#define N_MSR_ENABLE_X2APIC_MODE 10
+#define N_MSR_APIC_GLOBAL_ENABLE 11
+
+//
+// Bit definitions for MSR_IA32_MISC_ENABLE (ECX = 1A0h)
+//
+#define N_MSR_LIMIT_CPUID_MAXVAL 22
+#define N_MSR_XD_BIT_DISABLE 34
+
+extern EFI_PHYSICAL_ADDRESS mStartupVector;
+
+extern BOOLEAN mRestoreSettingAfterInit;
+extern UINT8 mPlatformType;
+extern ACPI_CPU_DATA *mAcpiCpuData;
+
+/**
+ Collects basic processor data for calling processor.
+
+ This function collects basic processor data for calling processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+CollectBasicProcessorData (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Early MP Initialization.
+
+ This function does early MP initialization, including MTRR sync and first time microcode load.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+EarlyMpInit (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Collects data from all logical processors.
+
+ This function collects data from all logical processors
+
+**/
+VOID
+DataCollectionPhase (
+ VOID
+ );
+
+/**
+ Produces register table according to output of Data Collection phase.
+
+ This function produces register table according to output of Data Collection phase.
+
+**/
+VOID
+AnalysisPhase (
+ VOID
+ );
+
+/**
+ Programs processor registers according to register tables.
+
+ This function programs processor registers according to register tables.
+
+**/
+VOID
+SettingPhase (
+ VOID
+ );
+
+/**
+ Produces Pre-SMM-Init Register Tables for all processors.
+
+ This function produces Pre-SMM-Init Register Tables for all processors.
+
+**/
+VOID
+ProducePreSmmInitRegisterTable (
+ VOID
+ );
+
+/**
+ Wakes up APs for the first time to count their number and collect BIST data.
+
+ This function wakes up APs for the first time to count their number and collect BIST data.
+
+**/
+VOID
+WakeupAPAndCollectBist (
+ VOID
+ );
+
+/**
+ Configures all logical processors with three-phase architecture.
+
+ This function configures all logical processors with three-phase architecture.
+
+**/
+VOID
+ProcessorConfigurationuration (
+ VOID
+ );
+
+/**
+ Select least-feature processor as BSP.
+
+ This function selects least-feature processor as BSP.
+
+**/
+VOID
+SelectLfpAsBsp (
+ VOID
+ );
+
+/**
+ Add SMBIOS Processor Type and Cache Type tables for the CPU.
+**/
+VOID
+AddCpuSmbiosTables (
+ VOID
+ );
+
+/**
+ Prepare ACPI NVS memory below 4G memory for use of S3 resume.
+
+ This function allocates ACPI NVS memory below 4G memory for use of S3 resume,
+ and saves data into the memory region.
+
+ @param Context The Context save the info.
+
+**/
+VOID
+SaveCpuS3Data (
+ VOID *Context
+ );
+
+/**
+ Programs registers for the calling processor.
+
+ This function programs registers for the calling processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+SetProcessorRegister (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Programs registers before SMM initialization for the calling processor.
+
+ This function programs registers before SMM initialization for the calling processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+SetPreSmmInitProcessorRegister (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Label of start of AP machine check handler.
+
+ This is just a label of start of AP machine check handler.
+
+**/
+VOID
+EFIAPI
+ApMachineCheckHandler (
+ VOID
+ );
+
+/**
+ Label of end of AP machine check handler.
+
+ This is just a label of end of AP machine check handler.
+
+**/
+VOID
+EFIAPI
+ApMachineCheckHandlerEnd (
+ VOID
+ );
+
+/**
+ This function gets Package ID/Core ID/Thread ID of the processor.
+
+ The algorithm below assumes the target system has symmetry across physical package boundaries
+ with respect to the number of logical processors per package, number of cores per package.
+
+ @param InitialApicId Initial APIC ID for determing processor topology.
+ @param Location Pointer to EFI_CPU_PHYSICAL_LOCATION structure.
+ @param ThreadIdBits Number of bits occupied by Thread ID portion.
+ @param CoreIdBits Number of bits occupied by Core ID portion.
+
+**/
+VOID
+ExtractProcessorLocation (
+ IN UINT32 InitialApicId,
+ OUT EFI_CPU_PHYSICAL_LOCATION *Location,
+ OUT UINTN *ThreadIdBits,
+ OUT UINTN *CoreIdBits
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf b/IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf
new file mode 100644
index 0000000..934f86c
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf
@@ -0,0 +1,179 @@
+## @file
+# Component description file for CPU MP DXE Driver.
+#
+# CPU DXE Driver that configures multi-processor environment, logs data to datahub
+# for processor subclass and cache subclass, and installs CPU Architecture Protocol and MP
+# Services Protocol
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuMpDxe
+ FILE_GUID = 40BEAB40-CECE-4909-B133-20A413AE19E9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MultiProcessorInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+# Create Event Guid C Name: Event Type: EVENT_TYPE_PERIODIC_TIMER
+#
+# HOB Guid C Name: gEfiHtBistHobGuid Hob Type: GUID_EXTENSION
+#
+
+[Sources]
+ SMBIOS/ProcessorSubClass.c
+ SMBIOS/ProcessorData.c
+ SMBIOS/Processor.h
+ SMBIOS/CpuSmbios.c
+ SMBIOS/CacheSubClass.c
+ SMBIOS/Cache.h
+ Xd.h
+ Xd.c
+ Setting.c
+ SelectLfp.c
+ ProcessorConfig.c
+ MpService.h
+ MpService.c
+ MpCommon.h
+ MpCommon.c
+ LimitCpuIdValue.h
+ LimitCpuIdValue.c
+ Feature.h
+ DataCollection.c
+ Cpu.h
+ MpApic.c
+ MpApic.h
+ Analysis.c
+ Strings.uni
+
+[Sources.Ia32]
+ IA32/MpFuncs.asm
+ IA32/MpFuncs.S
+ IA32/CpuOnlyReset.h
+ IA32/CpuOnlyReset.c
+ IA32/CpuAsm.asm
+ IA32/CpuAsm.S
+ IA32/AsmInclude.inc
+ IA32/ArchSpecificDef.h
+ IA32/ArchSpecific.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
+[LibraryClasses]
+ TimerLib
+ DxeServicesTableLib
+ CpuConfigLib
+ CpuLib
+ IoLib
+ PcdLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ ReportStatusCodeLib
+ BaseMemoryLib
+ HiiLib
+ HobLib
+ UefiLib
+ DebugLib
+ BaseLib
+ SynchronizationLib
+ CpuOnlyResetLib
+ UefiCpuLib
+ MtrrLib
+ S3BootScriptLib
+ DebugAgentLib
+ LocalApicLib
+ PrintLib
+
+[Guids]
+ gEfiHtBistHobGuid # ALWAYS_CONSUMED
+ gEfiEventExitBootServicesGuid # ALWAYS_CONSUMED
+ gIdleLoopEventGuid # ALWAYS_CONSUMED
+
+[Protocols]
+ gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiCpuArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiGenericMemTestProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiSmmConfigurationProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiTimerArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiTcgProtocolGuid ## SOMETIMES_CONSUMES
+
+[FeaturePcd]
+ gEfiCpuTokenSpaceGuid.PcdCpuSelectLfpAsBspFlag
+ gEfiCpuTokenSpaceGuid.PcdCpuExecuteDisableBitFlag
+ gEfiCpuTokenSpaceGuid.PcdCpuMaxCpuIDValueLimitFlag
+
+[FixedPcd]
+ gEfiCpuTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+ gEfiCpuTokenSpaceGuid.PcdCpuApLoopMode
+
+[Pcd]
+ gEfiCpuTokenSpaceGuid.PcdPlatformType
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketCount
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuFrequencyLists
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxFsbFrequency
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxCoreFrequency
+ gEfiCpuTokenSpaceGuid.PcdCpuApStackSize
+ gEfiCpuTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSetting
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapability
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfiguration
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSettingEx1
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapabilityEx1
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfigurationEx1
+ gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer
+ gEfiCpuTokenSpaceGuid.PcdCpuCallbackSignal
+ gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset
+ gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress
+ gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress
+ gEfiCpuTokenSpaceGuid.PcdCpuS3DataAddress
+ gEfiCpuTokenSpaceGuid.PcdCpuSocketId
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize
+
+[Depex]
+ gEfiSmbiosProtocolGuid AND gEfiTimerArchProtocolGuid
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/DataCollection.c b/IA32FamilyCpuBasePkg/CpuMpDxe/DataCollection.c
new file mode 100644
index 0000000..61b48e6
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/DataCollection.c
@@ -0,0 +1,765 @@
+/** @file
+ Code for Data Collection phase.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: DataCollection.c
+
+**/
+
+#include "Cpu.h"
+#include "Feature.h"
+
+BOOLEAN HtCapable = FALSE;
+BOOLEAN CmpCapable = FALSE;
+
+/**
+ Collects Local APIC data of the processor.
+
+ This function collects Local APIC base, verion, and APIC ID of the processor.
+
+ @param ProcessorNumber Handle number of specified logical processor
+
+**/
+VOID
+CollectApicData (
+ UINTN ProcessorNumber
+ )
+{
+ CPU_MISC_DATA *CpuMiscData;
+ UINT32 LocalApicBaseAddress;
+
+ CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;
+
+ LocalApicBaseAddress = (UINT32) GetLocalApicBaseAddress();
+ CpuMiscData->ApicBase = LocalApicBaseAddress;
+ //
+ // Read bits 0..7 of Local APIC Version Register for Local APIC version.
+ //
+ CpuMiscData->ApicVersion = GetApicVersion () & 0xff;
+ //
+ // Read bits 24..31 of Local APIC ID Register for Local APIC ID
+ //
+ CpuMiscData->ApicID = GetApicId ();
+ CpuMiscData->InitialApicID = GetInitialApicId ();
+}
+
+/**
+ Collects all CPUID leafs the processor.
+
+ This function collects all CPUID leafs the processor.
+
+ @param ProcessorNumber Handle number of specified logical processor
+
+**/
+VOID
+CollectCpuidLeafs (
+ UINTN ProcessorNumber
+ )
+{
+ CPU_COLLECTED_DATA *CpuCollectedData;
+ EFI_CPUID_REGISTER *CpuidRegisters;
+ UINT32 Index;
+
+ CpuCollectedData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber];
+ //
+ // Collect basic CPUID information.
+ //
+ CpuidRegisters = CpuCollectedData->CpuidData.CpuIdLeaf;
+ for (Index = 0; Index < GetNumberOfCpuidLeafs (ProcessorNumber, BasicCpuidLeaf); Index++) {
+ AsmCpuid (
+ Index,
+ &CpuidRegisters->RegEax,
+ &CpuidRegisters->RegEbx,
+ &CpuidRegisters->RegEcx,
+ &CpuidRegisters->RegEdx
+ );
+ CpuidRegisters++;
+ }
+
+ //
+ // Collect extended function CPUID information.
+ //
+ for (Index = 0; Index < GetNumberOfCpuidLeafs (ProcessorNumber, ExtendedCpuidLeaf); Index++) {
+ AsmCpuid (
+ Index + 0x80000000,
+ &CpuidRegisters->RegEax,
+ &CpuidRegisters->RegEbx,
+ &CpuidRegisters->RegEcx,
+ &CpuidRegisters->RegEdx
+ );
+ CpuidRegisters++;
+ }
+
+ //
+ // Collect additional Cache & TLB information, if exists.
+ //
+ for (Index = 1; Index < GetNumberOfCpuidLeafs (ProcessorNumber, CacheAndTlbCpuidLeafs); Index++) {
+ AsmCpuid (
+ 2,
+ &CpuidRegisters->RegEax,
+ &CpuidRegisters->RegEbx,
+ &CpuidRegisters->RegEcx,
+ &CpuidRegisters->RegEdx
+ );
+ CpuidRegisters++;
+ }
+
+ //
+ // Collect Deterministic Cache Parameters Leaf.
+ //
+ for (Index = 0; Index < GetNumberOfCpuidLeafs (ProcessorNumber, DeterministicCacheParametersCpuidLeafs); Index++) {
+ AsmCpuidEx (
+ 4,
+ Index,
+ &CpuidRegisters->RegEax,
+ &CpuidRegisters->RegEbx,
+ &CpuidRegisters->RegEcx,
+ &CpuidRegisters->RegEdx
+ );
+ CpuidRegisters++;
+ }
+
+ //
+ // Collect Extended Topology Enumeration Leaf.
+ //
+ for (Index = 0; Index < GetNumberOfCpuidLeafs (ProcessorNumber, ExtendedTopologyEnumerationCpuidLeafs); Index++) {
+ AsmCpuidEx (
+ EFI_CPUID_CORE_TOPOLOGY,
+ Index,
+ &CpuidRegisters->RegEax,
+ &CpuidRegisters->RegEbx,
+ &CpuidRegisters->RegEcx,
+ &CpuidRegisters->RegEdx
+ );
+ CpuidRegisters++;
+ }
+}
+
+/**
+ Collects physical location of the processor.
+
+ This function gets Package ID/Core ID/Thread ID of the processor.
+
+ The algorithm below assumes the target system has symmetry across physical package boundaries
+ with respect to the number of logical processors per package, number of cores per package.
+
+ @param InitialApicId Initial APIC ID for determing processor topology.
+ @param Location Pointer to EFI_CPU_PHYSICAL_LOCATION structure.
+ @param ThreadIdBits Number of bits occupied by Thread ID portion.
+ @param CoreIdBits Number of bits occupied by Core ID portion.
+
+**/
+VOID
+ExtractProcessorLocation (
+ IN UINT32 InitialApicId,
+ OUT EFI_CPU_PHYSICAL_LOCATION *Location,
+ OUT UINTN *ThreadIdBits,
+ OUT UINTN *CoreIdBits
+ )
+{
+ BOOLEAN TopologyLeafSupported;
+ UINTN ThreadBits;
+ UINTN CoreBits;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+ UINT32 MaxCpuIdIndex;
+ UINT32 SubIndex;
+ UINTN LevelType;
+ UINT32 MaxLogicProcessorsPerPackage;
+ UINT32 MaxCoresPerPackage;
+
+ //
+ // Check if the processor is capable of supporting more than one logical processor.
+ //
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT28) == 0) {
+ Location->Thread = 0;
+ Location->Core = 0;
+ Location->Package = 0;
+ *ThreadIdBits = 0;
+ *CoreIdBits = 0;
+ return;
+ }
+
+ ThreadBits = 0;
+ CoreBits = 0;
+
+ //
+ // Assume three-level mapping of APIC ID: Package:Core:SMT.
+ //
+
+ TopologyLeafSupported = FALSE;
+ //
+ // Get the max index of basic CPUID
+ //
+ AsmCpuid (EFI_CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);
+
+ //
+ // If the extended topology enumeration leaf is available, it
+ // is the preferred mechanism for enumerating topology.
+ //
+ if (MaxCpuIdIndex >= EFI_CPUID_EXTENDED_TOPOLOGY) {
+ AsmCpuidEx (EFI_CPUID_EXTENDED_TOPOLOGY, 0, &RegEax, &RegEbx, &RegEcx, NULL);
+ //
+ // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for
+ // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not
+ // supported on that processor.
+ //
+ if (RegEbx != 0) {
+ TopologyLeafSupported = TRUE;
+
+ //
+ // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract
+ // the SMT sub-field of x2APIC ID.
+ //
+ LevelType = (RegEcx >> 8) & 0xff;
+ ASSERT (LevelType == EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT);
+ ThreadBits = RegEax & 0x1f;
+
+ //
+ // Software must not assume any "level type" encoding
+ // value to be related to any sub-leaf index, except sub-leaf 0.
+ //
+ SubIndex = 1;
+ do {
+ AsmCpuidEx (EFI_CPUID_EXTENDED_TOPOLOGY, SubIndex, &RegEax, NULL, &RegEcx, NULL);
+ LevelType = (RegEcx >> 8) & 0xff;
+ if (LevelType == EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {
+ CoreBits = (RegEax & 0x1f) - ThreadBits;
+ break;
+ }
+ SubIndex++;
+ } while (LevelType != EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
+ }
+ }
+
+ if (!TopologyLeafSupported) {
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+ MaxLogicProcessorsPerPackage = (RegEbx >> 16) & 0xff;
+ if (MaxCpuIdIndex >= EFI_CPUID_CACHE_PARAMS) {
+ AsmCpuidEx (EFI_CPUID_CACHE_PARAMS, 0, &RegEax, NULL, NULL, NULL);
+ MaxCoresPerPackage = (RegEax >> 26) + 1;
+ } else {
+ //
+ // Must be a single-core processor.
+ //
+ MaxCoresPerPackage = 1;
+ }
+
+ ThreadBits = (UINTN) (HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);
+ CoreBits = (UINTN) (HighBitSet32 (MaxCoresPerPackage - 1) + 1);
+ }
+
+ Location->Thread = InitialApicId & ~((-1) << ThreadBits);
+ Location->Core = (InitialApicId >> ThreadBits) & ~((-1) << CoreBits);
+ Location->Package = (InitialApicId >> (ThreadBits+ CoreBits));
+ *ThreadIdBits = ThreadBits;
+ *CoreIdBits = CoreBits;
+}
+
+/**
+ Collects physical location of the processor.
+
+ This function collects physical location of the processor.
+
+ @param ProcessorNumber Handle number of specified logical processor
+
+**/
+VOID
+CollectProcessorLocation (
+ UINTN ProcessorNumber
+ )
+{
+ CPU_COLLECTED_DATA *CpuCollectedData;
+ UINT32 InitialApicID;
+ UINTN ThreadIdBits;
+ UINTN CoreIdBits;
+
+ CpuCollectedData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber];
+ InitialApicID = CpuCollectedData->CpuMiscData.InitialApicID;
+
+ ExtractProcessorLocation (
+ InitialApicID,
+ &CpuCollectedData->ProcessorLocation,
+ &ThreadIdBits,
+ &CoreIdBits
+ );
+
+ CpuCollectedData->PackageIdBitOffset = (UINT8)(ThreadIdBits+ CoreIdBits);
+
+ //
+ // Check CMP and HT capabilities
+ //
+ if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {
+ if (CoreIdBits > 0) {
+ CmpCapable = TRUE;
+ }
+ if (ThreadIdBits > 0) {
+ HtCapable = TRUE;
+ }
+ }
+}
+
+/**
+ Collects intended FSB frequency and core to bus ratio.
+
+ This function collects intended FSB frequency and core to bus ratio.
+
+ @param ProcessorNumber Handle number of specified logical processor
+
+**/
+VOID
+CollectFrequencyData (
+ UINTN ProcessorNumber
+ )
+{
+ CPU_MISC_DATA *CpuMiscData;
+ UINT32 FamilyId;
+ UINT32 ModelId;
+ UINT32 SteppingId;
+ BOOLEAN OldInterruptState;
+ UINT64 BeginValue;
+ UINT64 EndValue;
+ UINT64 ActualFrequency;
+ UINT64 ActualFsb;
+
+ CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;
+ CpuMiscData->FrequencyLocked = FALSE;
+ CpuMiscData->MaxCoreToBusRatio = (UINTN) 0x01;
+
+ GetProcessorVersionInfo (ProcessorNumber, &FamilyId, &ModelId, &SteppingId, NULL);
+
+ switch (FamilyId) {
+ case PENTIUM_FAMILY_ID:
+ switch (ModelId) {
+ case QUARK_MODEL_ID:
+ //
+ // Support for Pentium processor family
+ //
+
+ //
+ // Collect intended FSB frequency
+ //
+ CpuMiscData->IntendedFsbFrequency = 400;
+
+ //
+ // Check whether frequency is locked
+ //
+ CpuMiscData->FrequencyLocked = TRUE;
+
+ //
+ // Collect core to bus ratio
+ //
+ CpuMiscData->MaxCoreToBusRatio = (UINTN) 0x01;
+ CpuMiscData->MinCoreToBusRatio = (UINTN) 0x01;
+
+ //
+ // Collect VID
+ //
+ CpuMiscData->MaxVid = (UINTN) 0x03;
+ CpuMiscData->MinVid = (UINTN) 0x03;
+
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // Calculate actual FSB frequency
+ // First calculate actual frequency by sampling some time and counts TSC
+ // Use spinlock mechanism because timer library cannot handle concurrent requests.
+ //
+ AcquireSpinLock (&mMPSystemData.APSerializeLock);
+ OldInterruptState = SaveAndDisableInterrupts ();
+ BeginValue = AsmReadTsc ();
+ MicroSecondDelay (1000);
+ EndValue = AsmReadTsc ();
+ SetInterruptState (OldInterruptState);
+ ReleaseSpinLock (&mMPSystemData.APSerializeLock);
+ //
+ // Calculate raw actual FSB frequency
+ //
+ ActualFrequency = DivU64x32 (EndValue - BeginValue, 1000);
+ ActualFsb = DivU64x32 (ActualFrequency, (UINT32) CpuMiscData->MaxCoreToBusRatio);
+ //
+ // Round the raw actual FSB frequency to standardized value
+ //
+ ActualFsb = ActualFsb + RShiftU64 (ActualFsb, 5);
+ ActualFsb = DivU64x32 (MultU64x32 (ActualFsb, 3), 100);
+ ActualFsb = DivU64x32 (MultU64x32 (ActualFsb, 100), 3);
+
+ CpuMiscData->ActualFsbFrequency = (UINTN) ActualFsb;
+
+ //
+ // Default number of P-states is 1
+ //
+ CpuMiscData->NumberOfPStates = 1;
+}
+
+/**
+ Collects capabilities of various features of the processor.
+
+ This function collects capabilities of various features of the processor.
+
+ @param ProcessorNumber Handle number of specified logical processor
+
+**/
+VOID
+CollectFeatureCapability (
+ UINTN ProcessorNumber
+ )
+{
+ //
+ // Collect capability for Max CPUID Value Limit
+ //
+ if (FeaturePcdGet (PcdCpuMaxCpuIDValueLimitFlag)) {
+ MaxCpuidLimitDetect (ProcessorNumber);
+ }
+ //
+ // Collect capability for execute disable bit
+ //
+ if (FeaturePcdGet (PcdCpuExecuteDisableBitFlag)) {
+ XdDetect (ProcessorNumber);
+ }
+}
+
+/**
+ Collects basic processor data for calling processor.
+
+ This function collects basic processor data for calling processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+CollectBasicProcessorData (
+ IN UINTN ProcessorNumber
+ )
+{
+ CPU_MISC_DATA *CpuMiscData;
+
+ CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;
+
+ if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {
+ //
+ // BIST for the BSP will be updated in CollectBistDataFromHob().
+ //
+ CpuMiscData->HealthData = 0;
+ } else {
+ CpuMiscData->HealthData = mExchangeInfo->BistBuffer[ProcessorNumber].Bist;
+ }
+
+ //
+ // A loop to check APIC ID and processor number
+ //
+ CollectApicData (ProcessorNumber);
+
+ //
+ // Get package number, core number and thread number.
+ //
+ CollectProcessorLocation (ProcessorNumber);
+}
+
+/**
+ Collects processor data for calling processor.
+
+ This function collects processor data for calling processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+CollectProcessorData (
+ IN UINTN ProcessorNumber
+ )
+{
+ CPU_MISC_DATA *CpuMiscData;
+
+ CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;
+
+ //
+ // Collect all leafs for CPUID after second time microcode load.
+ //
+ CollectCpuidLeafs (ProcessorNumber);
+
+ //
+ // Get intended FSB frequency and core to bus ratio
+ //
+ CollectFrequencyData (ProcessorNumber);
+
+ //
+ // Collect capabilities for various features.
+ //
+ CollectFeatureCapability (ProcessorNumber);
+}
+
+/**
+ Checks the number of CPUID leafs need by a processor.
+
+ This function check the number of CPUID leafs need by a processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+CountNumberOfCpuidLeafs (
+ IN UINTN ProcessorNumber
+ )
+{
+ UINT32 MaxCpuidIndex;
+ UINT32 MaxExtendedCpuidIndex;
+ UINT32 NumberOfCacheAndTlbRecords;
+ UINT32 NumberOfDeterministicCacheParametersLeafs;
+ UINT32 NumberOfExtendedTopologyEnumerationLeafs;
+ UINT32 RegValue;
+ CPU_COLLECTED_DATA *CpuCollectedData;
+
+ CpuCollectedData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber];
+
+ //
+ // Get the max index of basic CPUID
+ //
+ AsmCpuid (0, &MaxCpuidIndex, NULL, NULL, NULL);
+ //
+ // Get the max index of extended CPUID
+ //
+ AsmCpuid (0x80000000, &MaxExtendedCpuidIndex, NULL, NULL, NULL);
+ //
+ // Get the number of cache and TLB CPUID leafs
+ //
+ AsmCpuid (2, &NumberOfCacheAndTlbRecords, NULL, NULL, NULL);
+ NumberOfCacheAndTlbRecords = NumberOfCacheAndTlbRecords & 0xff;
+
+ //
+ // Get the number of deterministic cache parameter CPUID leafs
+ //
+ NumberOfDeterministicCacheParametersLeafs = 0;
+ do {
+ AsmCpuidEx (4, NumberOfDeterministicCacheParametersLeafs++, &RegValue, NULL, NULL, NULL);
+ } while ((RegValue & 0x0f) != 0);
+
+ //
+ // Get the number of Extended Topology Enumeration CPUID leafs
+ //
+ NumberOfExtendedTopologyEnumerationLeafs = 0;
+ if (MaxCpuidIndex >= EFI_CPUID_CORE_TOPOLOGY) {
+ do {
+ AsmCpuidEx (EFI_CPUID_CORE_TOPOLOGY, NumberOfExtendedTopologyEnumerationLeafs++, NULL, &RegValue, NULL, NULL);
+ } while ((RegValue & 0x0FFFF) != 0);
+ }
+
+ //
+ // Save collected data in Processor Configuration Context Buffer
+ //
+ CpuCollectedData->CpuidData.NumberOfBasicCpuidLeafs = MaxCpuidIndex + 1;
+ CpuCollectedData->CpuidData.NumberOfExtendedCpuidLeafs = (MaxExtendedCpuidIndex - 0x80000000) + 1;
+ CpuCollectedData->CpuidData.NumberOfCacheAndTlbCpuidLeafs = NumberOfCacheAndTlbRecords;
+ CpuCollectedData->CpuidData.NumberOfDeterministicCacheParametersCpuidLeafs = NumberOfDeterministicCacheParametersLeafs;
+ CpuCollectedData->CpuidData.NumberOfExtendedTopologyEnumerationLeafs = NumberOfExtendedTopologyEnumerationLeafs;
+}
+
+/**
+ Checks the number of CPUID leafs of all logical processors, and allocate memory for them.
+
+ This function checks the number of CPUID leafs of all logical processors, and allocates memory for them.
+
+**/
+VOID
+AllocateMemoryForCpuidLeafs (
+ VOID
+ )
+{
+ CPU_COLLECTED_DATA *CpuCollectedData;
+ UINTN ProcessorNumber;
+ UINTN NumberOfLeafs;
+
+ //
+ // Wakeup all APs for CPUID checking.
+ //
+ DispatchAPAndWait (
+ TRUE,
+ 0,
+ CountNumberOfCpuidLeafs
+ );
+ //
+ // Check number of CPUID leafs for BSP.
+ // Try to accomplish in first wakeup, and MTRR.
+ //
+ CountNumberOfCpuidLeafs (mCpuConfigConextBuffer.BspNumber);
+
+ //
+ // Allocate memory for CPUID leafs of all processors
+ //
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+
+ CpuCollectedData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber];
+
+ //
+ // Get the number of basic CPUID leafs.
+ //
+ NumberOfLeafs = CpuCollectedData->CpuidData.NumberOfBasicCpuidLeafs;
+ //
+ // Get the number of extended CPUID leafs.
+ //
+ NumberOfLeafs += CpuCollectedData->CpuidData.NumberOfExtendedCpuidLeafs;
+ //
+ // Get the number of cache and TLB CPUID leafs.
+ //
+ NumberOfLeafs += CpuCollectedData->CpuidData.NumberOfCacheAndTlbCpuidLeafs - 1;
+ //
+ // Get the number of deterministic cache parameters CPUID leafs.
+ //
+ NumberOfLeafs += CpuCollectedData->CpuidData.NumberOfDeterministicCacheParametersCpuidLeafs;
+ //
+ // Get the number of Extended Topology Enumeration CPUID leafs
+ //
+ NumberOfLeafs += CpuCollectedData->CpuidData.NumberOfExtendedTopologyEnumerationLeafs;
+
+ CpuCollectedData->CpuidData.CpuIdLeaf = AllocateZeroPool (sizeof (EFI_CPUID_REGISTER) * NumberOfLeafs);
+ }
+}
+
+/**
+ Collects BIST data from HOB.
+
+ This function collects BIST data from HOB built by SEC_PLATFORM_PPI.
+
+**/
+VOID
+CollectBistDataFromHob (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UINT32 *DataInHob;
+ UINTN NumberOfData;
+ UINTN ProcessorNumber;
+ UINT32 InitialLocalApicId;
+ CPU_MISC_DATA *CpuMiscData;
+
+ GuidHob = GetFirstGuidHob (&gEfiHtBistHobGuid);
+ if (GuidHob == NULL) {
+ return;
+ }
+
+ DataInHob = GET_GUID_HOB_DATA (GuidHob);
+ NumberOfData = GET_GUID_HOB_DATA_SIZE (GuidHob) / sizeof (UINT32);
+
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+ InitialLocalApicId = GetInitialLocalApicId (ProcessorNumber);
+ if (InitialLocalApicId < NumberOfData) {
+ CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;
+ CpuMiscData->HealthData = DataInHob[InitialLocalApicId];
+ //
+ // Initialize CPU health status for MP Services Protocol according to BIST data.
+ //
+ mMPSystemData.CpuHealthy[ProcessorNumber] = (BOOLEAN) (CpuMiscData->HealthData == 0);
+ if (!mMPSystemData.CpuHealthy[ProcessorNumber]) {
+ //
+ // Report Status Code that self test is failed
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+ (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
+ );
+ }
+ }
+ }
+}
+
+/**
+ Collects data from all logical processors.
+
+ This function collects data from all logical processors.
+
+**/
+VOID
+DataCollectionPhase (
+ VOID
+ )
+{
+ UINT8 CallbackSignalValue;
+
+ //
+ // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back.
+ //
+ CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_DATA_COLLECTION_SIGNAL);
+ //
+ // Check whether the callback function requests to bypass Setting phase.
+ //
+ if (CallbackSignalValue == CPU_BYPASS_SIGNAL) {
+ return;
+ }
+
+ //
+ // Check the number of CPUID leafs of all logical processors, and allocate memory for them.
+ //
+ AllocateMemoryForCpuidLeafs ();
+
+ //
+ // Wakeup all APs for data collection.
+ //
+ DispatchAPAndWait (
+ TRUE,
+ 0,
+ CollectProcessorData
+ );
+
+ //
+ // Collect data for BSP.
+ //
+ CollectProcessorData (mCpuConfigConextBuffer.BspNumber);
+
+ CollectBistDataFromHob ();
+
+ //
+ // Set PCD data for HT and CMP information
+ //
+ if (CmpCapable) {
+ PcdSet32 (PcdCpuProcessorFeatureCapability, PcdGet32 (PcdCpuProcessorFeatureCapability) | PCD_CPU_CMP_BIT);
+ if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_CMP_BIT) != 0) {
+ PcdSet32 (PcdCpuProcessorFeatureSetting, PcdGet32 (PcdCpuProcessorFeatureSetting) | PCD_CPU_CMP_BIT);
+ }
+ }
+ if (HtCapable) {
+ PcdSet32 (PcdCpuProcessorFeatureCapability, PcdGet32 (PcdCpuProcessorFeatureCapability) | PCD_CPU_HT_BIT);
+ if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_HT_BIT) != 0) {
+ PcdSet32 (PcdCpuProcessorFeatureSetting, PcdGet32 (PcdCpuProcessorFeatureSetting) | PCD_CPU_HT_BIT);
+ }
+ }
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Feature.h b/IA32FamilyCpuBasePkg/CpuMpDxe/Feature.h
new file mode 100644
index 0000000..60720b9
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Feature.h
@@ -0,0 +1,43 @@
+/** @file
+
+ Header file for processor features
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Feature.h
+
+**/
+
+#ifndef _CPU_FEATURE_H_
+#define _CPU_FEATURE_H_
+
+#include "LimitCpuIdValue.h"
+#include "Xd.h"
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecific.c b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecific.c
new file mode 100644
index 0000000..cf0aacd
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecific.c
@@ -0,0 +1,143 @@
+/** @file
+
+ Memory Operation Functions for IA32 Architecture.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: ArchSpecific.c
+
+**/
+
+#include "Cpu.h"
+#include "MpService.h"
+
+MP_CPU_EXCHANGE_INFO *mExchangeInfo;
+
+/**
+ Prepares Startup Vector for APs.
+
+ This function prepares Startup Vector for APs.
+
+**/
+VOID
+PrepareAPStartupVector (
+ VOID
+ )
+{
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ //
+ // Get the address map of startup code for AP,
+ // including code size, and offset of long jump instructions to redirect.
+ //
+ AsmGetAddressMap (&AddressMap);
+
+ //
+ // Allocate a 4K-aligned region under 1M for startup vector for AP.
+ // The region contains AP startup code and exchange data between BSP and AP.
+ //
+ AllocateStartupVector (AddressMap.Size + sizeof (MP_CPU_EXCHANGE_INFO));
+
+ //
+ // Copy AP startup code to startup vector, and then redirect the long jump
+ // instructions for mode switching.
+ //
+ CopyMem ((VOID *) (UINTN) mStartupVector, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
+ RedirectFarJump (&AddressMap, mStartupVector);
+
+ //
+ // Get the start address of exchange data between BSP and AP.
+ //
+ mExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mStartupVector + AddressMap.Size);
+
+ ZeroMem ((VOID *) mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));
+
+ PrepareGdtIdtForAP (
+ (IA32_DESCRIPTOR *) (UINTN) &mExchangeInfo->GdtrProfile,
+ (IA32_DESCRIPTOR *) (UINTN) &mExchangeInfo->IdtrProfile
+ );
+
+ //
+ // Assign ApLoopMode during POST phase
+ // Set ApLoopMode to ApInHltLoop if ApLoopMode is ApInMwaitLoop
+ // because ApInMwaitLoop could be supported only after C-State enabled.
+ //
+ if (PcdGet8 (PcdCpuApLoopMode) != ApInMwaitLoop) {
+ mExchangeInfo->ApLoopMode = (AP_LOOP_MODE) (PcdGet8 (PcdCpuApLoopMode));
+ } else {
+ mExchangeInfo->ApLoopMode = ApInHltLoop;
+ }
+
+ mExchangeInfo->ApFunction = ApProcEntry;
+ mExchangeInfo->BufferStart = (UINT32) mStartupVector;
+ mExchangeInfo->InitFlag = 1;
+}
+
+/**
+ Sets specified IDT entry with given function pointer.
+
+ This function sets specified IDT entry with given function pointer.
+
+ @param FunctionPointer Function pointer for IDT entry.
+ @param IdtEntry The IDT entry to update.
+
+ @return The original IDT entry value.
+
+**/
+UINTN
+SetIdtEntry (
+ IN UINTN FunctionPointer,
+ OUT INTERRUPT_GATE_DESCRIPTOR *IdtEntry
+)
+{
+ UINTN OriginalEntry;
+
+ OriginalEntry = ((UINT32) IdtEntry->OffsetHigh << 16) + IdtEntry->OffsetLow;
+
+ IdtEntry->OffsetLow = (UINT16) FunctionPointer;
+ IdtEntry->OffsetHigh = (UINT16) (FunctionPointer >> 16);
+
+ return OriginalEntry;
+}
+
+ /**
+ Fixup jump instructions in the AP startup code.
+
+ @param AddressMap Pointer to MP_ASSEMBLY_ADDRESS_MAP.
+ @param TargetBuffer Target address of the startup vector.
+**/
+VOID
+RedirectFarJump (
+ IN MP_ASSEMBLY_ADDRESS_MAP *AddressMap,
+ IN EFI_PHYSICAL_ADDRESS TargetBuffer
+ )
+{
+ *(UINT32 *)(UINTN)(mStartupVector + AddressMap->FlatJumpOffset + 3) = (UINT32)(TargetBuffer + AddressMap->PModeEntryOffset);
+}
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecificDef.h b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecificDef.h
new file mode 100644
index 0000000..1669231
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecificDef.h
@@ -0,0 +1,84 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ ProcessorDef.h
+
+Abstract:
+
+ Definition for IA32 processor
+
+**/
+
+#ifndef _PROCESSOR_DEF_H_
+#define _PROCESSOR_DEF_H_
+
+#include <FrameworkDxe.h>
+#include <Protocol/Cpu.h>
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 OffsetLow;
+ UINT16 SegmentSelector;
+ UINT16 Attributes;
+ UINT16 OffsetHigh;
+} INTERRUPT_GATE_DESCRIPTOR;
+
+#pragma pack()
+
+typedef struct {
+ VOID *Start;
+ UINTN Size;
+ UINTN FixOffset;
+} INTERRUPT_HANDLER_TEMPLATE_MAP;
+
+typedef struct {
+ UINT8 *RendezvousFunnelAddress;
+ UINTN PModeEntryOffset;
+ UINTN FlatJumpOffset;
+ UINTN Size;
+} MP_ASSEMBLY_ADDRESS_MAP;
+
+/**
+ Get starting address and size of the rendezvous entry for APs.
+ Information for fixing a jump instruction in the code is also returned.
+
+ @param AddressMap Output buffer for address map information.
+**/
+VOID
+EFIAPI
+AsmGetAddressMap (
+ OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/AsmInclude.inc b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/AsmInclude.inc
new file mode 100644
index 0000000..b384273
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/AsmInclude.inc
@@ -0,0 +1,59 @@
+;******************************************************************************
+;*
+;* Copyright (c) 2013 Intel Corporation.
+;*
+;* Redistribution and use in source and binary forms, with or without
+;* modification, are permitted provided that the following conditions
+;* are met:
+;*
+;* * Redistributions of source code must retain the above copyright
+;* notice, this list of conditions and the following disclaimer.
+;* * Redistributions in binary form must reproduce the above copyright
+;* notice, this list of conditions and the following disclaimer in
+;* the documentation and/or other materials provided with the
+;* distribution.
+;* * Neither the name of Intel Corporation nor the names of its
+;* contributors may be used to endorse or promote products derived
+;* from this software without specific prior written permission.
+;*
+;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+;* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+;* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+;* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+;* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+;* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+;* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+;* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+;* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+;* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+;* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;*
+;******************************************************************************
+
+VacantFlag Equ 00h
+NotVacantFlag Equ 0ffh
+StartupApSignal Equ 6E750000h
+MonitorFilterSize Equ 10h
+ApInHltLoop Equ 1
+ApInMwaitLoop Equ 2
+ApInRunLoop Equ 3
+
+LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
+StackStart equ (LockLocation + 4h)
+StackSize equ (LockLocation + 8h)
+RendezvousProc equ (LockLocation + 0Ch)
+GdtrProfile equ (LockLocation + 10h)
+IdtrProfile equ (LockLocation + 16h)
+BufferStart equ (LockLocation + 1Ch)
+Cr3Location equ (LockLocation + 20h)
+InitFlag equ (LockLocation + 24h)
+ApCountLocation equ (LockLocation + 28h)
+ApLoopModeLocation equ (LockLocation + 2Ch)
+BistBuffer equ (LockLocation + 30h)
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+;-------------------------------------------------------------------------------
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.S b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.S
new file mode 100644
index 0000000..0d39d31
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.S
@@ -0,0 +1,56 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# CpuAsm.S
+#
+# Abstract:
+#
+# Assembly code that supports IA32 CPU architectural protocol
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(ApMachineCheckHandler)
+ASM_PFX(ApMachineCheckHandler):
+ #
+ # Clear MCIP flag of IA32_MCG_STATUS register
+ #
+ movl $0x17a,%ecx
+ rdmsr
+ btrl $2,%eax
+ wrmsr
+
+ iret
+
+ASM_GLOBAL ASM_PFX(ApMachineCheckHandlerEnd)
+
+ASM_PFX(ApMachineCheckHandlerEnd):
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.asm b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.asm
new file mode 100644
index 0000000..badbc23
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.asm
@@ -0,0 +1,69 @@
+ page ,132
+ title CPU ARCHITECTURAL DXE PROTOCOL ASSEMBLY HOOKS
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; CpuAsm.asm
+;
+; Abstract:
+;
+; Assembly code that supports IA32 CPU architectural protocol
+;
+;------------------------------------------------------------------------------
+
+.686p
+.model flat
+
+.stack
+.code
+.MMX
+.XMM
+
+ApMachineCheckHandler PROC C PUBLIC
+ ;
+ ; Clear MCIP flag of IA32_MCG_STATUS register
+ ;
+ mov ecx, 17ah
+ rdmsr
+ btr eax, 2
+ wrmsr
+
+ iretd
+
+ApMachineCheckHandler ENDP
+
+EXTERNDEF C ApMachineCheckHandlerEnd:BYTE
+
+ApMachineCheckHandlerEnd LABEL BYTE
+
+ end
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.c b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.c
new file mode 100644
index 0000000..f938baa
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.c
@@ -0,0 +1,52 @@
+/** @file
+
+ Code for cpu only reset.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: CpuOnlyReset.c
+
+**/
+
+#include "CpuOnlyReset.h"
+
+/**
+ Initiate CPU only reset.
+
+ This function will save CPU context, call SetJump to mark the resume pointer
+ and program MCH to trigger CPU only reset.
+
+**/
+VOID
+InitiateCpuOnlyReset(
+ VOID
+ )
+{
+ return;
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.h b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.h
new file mode 100644
index 0000000..701d4ee
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.h
@@ -0,0 +1,184 @@
+/** @file
+
+ Header file for cpu only reset.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: CpuOnlyReset.h
+
+**/
+#ifndef _CPU_ONLY_RESET_H_
+#define _CPU_ONLY_RESET_H_
+
+#include "MpCommon.h"
+
+#define CPU_ONLY_RESET_INDICATOR SIGNATURE_32('C','R','S','T')
+#define CPU_ONLY_RESET_TEMP_STACK_SIZE 128
+#pragma pack(1)
+//
+// This structure describe the mininal information SEC phase need to deal with
+// CPU only reset.
+//
+typedef struct _CPU_ONLY_RESET_INFO_ {
+ UINT32 CpuOnlyResetIndicator; // a flag to indicate the reset is CPU only reset
+ UINT32 EntryPoint; // entry pointer SEC should jump to
+ UINT32 NewStack; // a temporary stack for the entry point
+ UINT32 Checksum; // the checksum to this data structure
+}CPU_ONLY_RESET_INFO;
+#pragma pack()
+
+#pragma pack(1)
+//
+// This data structure defined the trampolean information to resume to 64-bit
+// code from CPU only reset. And this data structure will works as stack, so please
+// take care the fields' sequence and alignment when modification
+// This structure is specific for 64-bit long mode
+//
+typedef struct _CPU_ONLY_RESET_TRAMPOLINE_INFO_ {
+ CPU_ONLY_RESET_INFO CpuOnlyResetInfo;
+ //
+ // ASSUMPTION:
+ // The gdt DXE drivers use, page table and CPU driver itself should
+ // be located bellow 4G memory. in feature, when this stuff allows to locate
+ // above 4G, the temporary page table, entry point and gdt
+ // need be implemented below 4G.
+ //
+ UINT16 TemporaryGdtLimit;
+ UINT32 TemporaryGdtBase;
+ // to make sure following field aligned with 4 bytes
+ UINT16 Reserved0;
+
+ UINT32 TemporaryCR3;
+ //
+ // prepare the parameter for calling InternalX86EnablePaging64 according to
+ // C calling convention to switch to long mode.
+ //
+ // InternalX86EnablePaging64 (
+ // IN UINT16 Cs,
+ // IN UINT64 EntryPoint,
+ // IN UINT64 Context1, OPTIONAL
+ // IN UINT64 Context2, OPTIONAL
+ // IN UINT64 NewStack
+ // );
+ //
+ // 4 bytes reserve for return address after call into InternalX86EnablePaging64
+ //
+ UINT32 Reserved1;
+ UINT16 TemporaryCS;
+ UINT16 Reserved2; // for alignment reason
+ UINT64 CpuOnlyResetEntryPoint;
+ UINT64 Context1;
+ UINT64 Context2;
+ UINT64 NewStack;
+ UINT8 TemporaryStack[CPU_ONLY_RESET_TEMP_STACK_SIZE];
+} CPU_ONLY_RESET_TRAMPOLINE_INFO;
+
+#pragma pack()
+
+#define CPU_ONLY_RESET_TRAMPOLINE_INFO_SIZE sizeof(CPU_ONLY_RESET_TRAMPOLINE_INFO)
+
+//
+// When CPU only reset occurs, we need save CPU_ONLY_RESET_TRAMPOLINE_INFO
+// to a well-known address which should be availabe and under 4G memory.
+// here we defines it as zero
+//
+#define CPU_ONLY_RESET_TRAMPOLINE_INFO_BASE_ADDRESS 0x400
+
+//
+// the structure define is generic. it will be the same one no matter
+// for 32-bit mode or 64-bit mode
+//
+typedef struct _CPU_ONLY_RESET_CONTEXT_BUFFER_ {
+ //
+ // System register
+ //
+ IA32_DESCRIPTOR GdtDesc;
+ IA32_DESCRIPTOR IdtDesc;
+ UINT16 Ldtr;
+ UINT16 Es;
+ UINT16 Cs;
+ UINT16 Ss;
+ UINT16 Ds;
+ UINT16 Fs;
+ UINT16 Gs;
+ //
+ //
+ UINTN Cr0;
+ UINTN Cr3;
+ UINTN Cr4;
+ UINTN Tr;
+ //
+ // debug register
+ //
+ UINTN Dr0;
+ UINTN Dr1;
+ UINTN Dr2;
+ UINTN Dr3;
+ UINTN Dr6;
+ UINTN Dr7;
+ //
+ // General register
+ //
+ BASE_LIBRARY_JUMP_BUFFER JumpContext;
+ //
+ // When CPU only reset occurs, we need save CPU_ONLY_RESET_TRAMPOLINE_INFO
+ // to a well-known address which should be under 4G memory(say address 0)
+ // So this field will save the original content on that address and
+ // restore it after resume
+ //
+ UINT8 CpuOnlyResetTrampolineInfo[CPU_ONLY_RESET_TRAMPOLINE_INFO_SIZE];
+
+}CPU_ONLY_RESET_CONTEXT_BUFFER;
+
+/**
+ Initiate CPU only reset.
+
+ This function will save CPU context, call SetJump to mark the resume pointer
+ and program MCH to trigger CPU only reset.
+
+**/
+VOID
+InitiateCpuOnlyReset(
+ VOID
+ );
+/**
+ This function is written in Long mode instructions and build by 64-bit
+ assembler, BUT running in 32-bit protected mode
+ This function is the real entry point after CPU only reset. SEC will dire
+
+ @param Context1 The first context save the info.
+ @param Context2 The second context save the info.
+**/
+VOID
+EFIAPI
+CpuOnlyResetResumeEntryWrapper (
+ VOID *Context1,
+ VOID *Context2
+ );
+#endif // _CPU_ONLY_RESET_H_
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/Exception.c b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/Exception.c
new file mode 100644
index 0000000..e9d1a00
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/Exception.c
@@ -0,0 +1,327 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Exception.c
+
+Abstract:
+
+ IA-32 Exception Handler.
+
+**/
+
+#include "Cpu.h"
+#include "Exception.h"
+
+//
+// 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_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_IA32),
+ { 0 }
+ },
+ {
+ 0
+ }
+};
+
+/**
+ Reports StatusCode for Exception
+
+ This function reports status code for exception.
+
+ @param InterruptType Interrupt type
+ @param SystemContext EFI_SYSTEM_CONTEXT
+
+**/
+VOID
+ReportData (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 ErrorMessage;
+ UINT32 Index;
+
+ CopyMem (
+ &mStatusCodeData.SystemContext.SystemContextIa32,
+ SystemContext.SystemContextIa32,
+ sizeof (EFI_SYSTEM_CONTEXT_IA32)
+ );
+
+ ErrorMessage = EFI_SOFTWARE_DXE_BS_DRIVER;
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ if (mExceptionTable[Index].Interrupt == InterruptType) {
+ ErrorMessage |= mExceptionTable[Index].ErrorMessage;
+ break;
+ }
+ }
+
+ REPORT_STATUS_CODE_EX (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ EFI_SOFTWARE_UNSPECIFIED | ErrorMessage,
+ 0,
+ NULL,
+ NULL,
+ (UINT8 *)&mStatusCodeData + sizeof (EFI_STATUS_CODE_DATA),
+ sizeof (EFI_SYSTEM_CONTEXT_IA32)
+ );
+}
+
+/**
+ Common exception handler.
+
+ @param InterruptType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! IA32 Exception Type - %08x !!!!\n",
+ InterruptType
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->Cs,
+ SystemContext.SystemContextIa32->Eflags
+ ));
+ if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %08x\n",
+ SystemContext.SystemContextIa32->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
+ SystemContext.SystemContextIa32->Eax,
+ SystemContext.SystemContextIa32->Ecx,
+ SystemContext.SystemContextIa32->Edx,
+ SystemContext.SystemContextIa32->Ebx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
+ SystemContext.SystemContextIa32->Esp,
+ SystemContext.SystemContextIa32->Ebp,
+ SystemContext.SystemContextIa32->Esi,
+ SystemContext.SystemContextIa32->Edi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
+ SystemContext.SystemContextIa32->Ds,
+ SystemContext.SystemContextIa32->Es,
+ SystemContext.SystemContextIa32->Fs,
+ SystemContext.SystemContextIa32->Gs,
+ SystemContext.SystemContextIa32->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDTR - %08x %08x, IDTR - %08x %08x\n",
+ SystemContext.SystemContextIa32->Gdtr[0],
+ SystemContext.SystemContextIa32->Gdtr[1],
+ SystemContext.SystemContextIa32->Idtr[0],
+ SystemContext.SystemContextIa32->Idtr[1]
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "LDTR - %08x, TR - %08x\n",
+ SystemContext.SystemContextIa32->Ldtr,
+ SystemContext.SystemContextIa32->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
+ SystemContext.SystemContextIa32->Cr0,
+ SystemContext.SystemContextIa32->Cr2,
+ SystemContext.SystemContextIa32->Cr3,
+ SystemContext.SystemContextIa32->Cr4
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
+ SystemContext.SystemContextIa32->Dr0,
+ SystemContext.SystemContextIa32->Dr1,
+ SystemContext.SystemContextIa32->Dr2,
+ SystemContext.SystemContextIa32->Dr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR6 - %08x, DR7 - %08x\n",
+ SystemContext.SystemContextIa32->Dr6,
+ SystemContext.SystemContextIa32->Dr7
+ ));
+
+ //
+ // Report Status Code
+ //
+ ReportData (InterruptType, SystemContext);
+
+ //
+ // Enter a dead loop.
+ //
+ CpuDeadLoop ();
+
+ return ;
+}
+
+/**
+ Installs the Exception Handler.
+
+ This function installs the Exception Handler.
+
+**/
+VOID
+InitializeException (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ BOOLEAN OldInterruptState;
+
+ //
+ // Disable interrupt
+ //
+ OldInterruptState = SaveAndDisableInterrupts ();
+
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ //
+ // Register sample excception handler
+ //
+ Status = mCpuArchProtocol.RegisterInterruptHandler (
+ &mCpuArchProtocol,
+ mExceptionTable[Index].Interrupt,
+ CommonExceptionHandler
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // Restore interrupt state.
+ //
+ SetInterruptState (OldInterruptState);
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.S b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.S
new file mode 100644
index 0000000..ebf817b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.S
@@ -0,0 +1,449 @@
+#-------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+# Module Name:
+#
+# MPFuncs32.S
+#
+# Abstract:
+#
+# This is the assembly code for MP (Multiple-processor) support
+#
+#-------------------------------------------------------------------------------
+
+
+.equ VacantFlag, 0x0
+.equ NotVacantFlag, 0xff
+.equ StartupApSignal, 0x6E750000
+.equ MonitorFilterSize, 0x10
+.equ ApInHltLoop, 1
+.equ ApInMwaitLoop, 2
+.equ ApInRunLoop, 3
+
+
+.equ LockLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+.equ StackStart, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x04
+.equ StackSize, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x08
+.equ RendezvousProc, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x0C
+.equ GdtrProfile, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x10
+.equ IdtrProfile, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x16
+.equ BufferStart, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x1C
+.equ Cr3Location, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x20
+.equ InitFlag, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x24
+.equ ApCountLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x28
+.equ ApLoopModeLocation,RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x2C
+.equ BistBuffer, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x30
+
+#-------------------------------------------------------------------------------------
+.macro PAUSE32
+ .byte 0xF3
+ .byte 0x90
+.endm
+
+#-------------------------------------------------------------------------------------
+#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);
+
+ASM_GLOBAL ASM_PFX(RendezvousFunnelProc)
+ASM_PFX(RendezvousFunnelProc):
+RendezvousFunnelProcStart:
+
+
+# At this point CS = 0x(vv00) and ip= 0x0.
+
+ .byte 0x66,0x8b,0xe8 # mov ebp, eax
+
+ .byte 0x8c,0xc8 # mov ax, cs
+ .byte 0x8e,0xd8 # mov ds, ax
+ .byte 0x8e,0xc0 # mov es, ax
+ .byte 0x8e,0xd0 # mov ss, ax
+ .byte 0x33,0xc0 # xor ax, ax
+ .byte 0x8e,0xe0 # mov fs, ax
+ .byte 0x8e,0xe8 # mov gs, ax
+
+# Get APIC ID
+
+ .byte 0x66,0xB8
+ .long 0x00000000 # mov eax, 0
+ .byte 0x0F,0xA2 # cpuid
+ .byte 0x66,0x3d
+ .long 0x0000000B # cmp eax, 0b
+ .byte 0x73,0x0e # jnb X2Apic
+
+# Processor is not x2APIC capable, so get 8-bit APIC ID
+ .byte 0x66,0xB8 # mov eax, 1
+ .long 0x00000001 # cpuid
+ .byte 0x0F,0xA2
+ .byte 0x66,0xC1,0xEB,0x18 # shr ebx, 24
+ .byte 0xeb,0x0e # jmp CheckInitFlag
+
+# Processor is x2APIC capable, so get 32-bit x2APIC ID
+X2Apic:
+ .byte 0x66,0xB8
+ .long 0x0000000B # mov eax, 0b
+ .byte 0x66,0x31,0xc9 # xor ecx, ecx
+ .byte 0x0F,0xA2 # cpuid
+ .byte 0x66,0x89,0xd3 # mov ebx, edx
+
+CheckInitFlag:
+# If it is the first time AP wakes up, just record AP's BIST
+# Otherwise, switch to flat mode
+
+ .byte 0xBE
+ .word InitFlag # mov si, InitFlag
+ .byte 0x66,0x83,0x3C,0x0 # cmp dword ptr [si], 0
+ .byte 0x74
+ .byte flat32Start - . - 1 # jz flat32Start
+
+# Increase ApCount as processor number for index of BIST Info array
+
+ .byte 0x66,0xa1 # mov eax, [ApCountLocation]
+ .word ApCountLocation
+IncApCount:
+ .byte 0x66,0x67,0x8d,0x48,0x01 # lea ecx, [eax+1]
+ .byte 0xf0,0x66,0x0f,0xb1,0x0e # lock cmpxchg [ApCountLocation], ecx
+ .word ApCountLocation
+ .byte 0x75,0xf2 # jnz IncApCount
+ .byte 0x66, 0xff, 0xc0 # inc eax ; AP processor number starts from 1
+# Record BIST information
+#
+ .byte 0x66,0x67,0x8d,0x34,0xc5 # lea esi, [BistBuffer + eax*8]
+ .long BistBuffer
+
+ .byte 0x66,0x89,0x1c # mov dword ptr [si], ebx ; APIC ID
+ .byte 0x66,0x89,0x6C,0x04 # mov dword ptr [si + 4], ebp ; Store BIST value
+
+ cli
+ hlt
+ jmp .-2
+
+# Switch to flat mode.
+
+flat32Start:
+
+ .byte 0xBE
+ .word BufferStart # mov si, BufferStart
+ .byte 0x66,0x8B,0x0C # mov ecx,dword ptr [si] ; ECX is keeping the start address of wakeup buffer
+
+ .byte 0xFA # cli
+
+ .byte 0xBE
+ .word GdtrProfile # mov si, GdtrProfile
+ .byte 0x66 # db 66h
+ .byte 0x2E,0xF,0x1,0x14 # lgdt fword ptr cs:[si]
+
+ .byte 0xBE
+ .word IdtrProfile # mov si, IdtrProfile
+ .byte 0x66 # db 66h
+ .byte 0x2E,0xF,0x1,0x1C # lidt fword ptr cs:[si]
+
+ .byte 0x33,0xC0 # xor ax, ax
+ .byte 0x8E,0xD8 # mov ds, ax
+
+ .byte 0xF,0x20,0xC0 # mov eax, cr0 ; Get control register 0
+ .byte 0x66,0x83,0xC8,0x1 # or eax, 000000001h ; Set PE bit (bit #0)
+ .byte 0xF,0x22,0xC0 # mov cr0, eax
+
+
+#step-4:
+
+FLAT32_JUMP:
+
+ .byte 0x66,0x67,0xEA # far jump
+ .long 0x0
+ .word 0x10
+
+PMODE_ENTRY: # protected mode entry point
+
+ movw $0x8,%ax
+ .byte 0x66
+ movw %ax,%ds
+ .byte 0x66
+ movw %ax,%es
+ .byte 0x66
+ movw %ax,%fs
+ .byte 0x66
+ movw %ax,%gs
+ .byte 0x66
+ movw %ax,%ss # Flat mode setup.
+
+ movl %ecx,%esi
+
+ movl %esi,%edi
+ addl $InitFlag, %edi
+ cmpl $2, (%edi)
+ jz ProgramDynamicStack
+
+ProgramStaticStack:
+
+ #
+ # Get processor number for this AP
+ # Note that BSP may become an AP due to SwitchBsp()
+ #
+ xorl %ecx, %ecx
+ leal BistBuffer(%esi), %edi
+
+GetProcNumber:
+ cmpl %ebx, (%edi) # APIC ID match?
+ jz Found
+ addl $8, %edi
+ incl %ecx
+ cmpl ApCountLocation(%esi), %ecx
+ jbe GetProcNumber
+
+Found:
+ #
+ # ProgramStack
+ #
+
+ movl %esi, %edi
+ addl $StackSize, %edi
+ movl (%edi), %eax
+ incl %ecx
+ mull %ecx # EAX = StackSize * (CpuNumber + 1)
+ decl %ecx
+
+ movl %esi, %edi
+ addl $StackStart, %edi
+ movl (%edi), %ebx
+ addl %ebx, %eax # EAX = StackStart + StackSize * (CpuNumber + 1)
+
+ movl %eax, %esp
+ subl $MonitorFilterSize, %esp # Reserved Monitor data space
+ movl %ecx, %ebp # Save processor number in ebp
+ jmp ProgramStackDone
+
+ProgramDynamicStack:
+
+ movl %esi,%edi
+ addl $LockLocation, %edi
+ movb $NotVacantFlag, %al
+TestLock:
+ xchgb (%edi), %al
+ cmpb $NotVacantFlag, %al
+ jz TestLock
+
+ movl %esi,%edi
+ addl $StackSize, %edi
+ movl (%edi), %eax
+ movl %esi,%edi
+ addl $StackStart, %edi
+ addl (%edi), %eax
+ movl %eax,%esp
+ movl %eax, (%edi)
+
+Releaselock:
+ movb $VacantFlag, %al
+ movl %esi,%edi
+ addl $LockLocation, %edi
+ xchgb (%edi), %al
+
+ProgramStackDone:
+
+ #
+ # Call assembly function to initialize FPU.
+ #
+ lea ASM_PFX(InitializeFloatingPointUnits), %ebx
+ call *%ebx
+
+ #
+ # Call C Function
+ #
+ movl %esi,%edi
+ addl $RendezvousProc, %edi
+ addl $ApLoopModeLocation, %esi # esi = ApLoopMode address location
+
+ xorl %ebx, %ebx
+ movl %ebx, 0xC(%esp) # Clean ReadyToBoot Flag
+ movw %bp, %bx # bx = the lowest 16bit of CpuNumber
+ orl $StartupApSignal, %ebx # Construct AP run Singal
+
+WakeUpThisAp:
+ movl (%edi), %eax
+ testl %eax, %eax
+ jz CheckReadyToBoot
+
+ push %ebp
+ call *%eax
+ addl $4, %esp
+
+ #
+ # Check if BSP was switched
+ #
+ movl ASM_PFX(mBspSwitched), %eax
+ cmpb $0, (%eax)
+ jz CheckReadyToBoot
+
+ movb $0, (%eax) # clear BSP switch flag
+
+ movl ASM_PFX(mNewProcessorNumber), %eax
+ movl (%eax), %ebp # rbp = new processor number
+
+ movw %bp, %bx # bx = the lowest 16bit of CpuNumber
+
+ #
+ # Assign the dedicated AP stack for the new AP
+ #
+ movl ASM_PFX(mMonitorDataAddress), %eax
+ movl (%eax), %esp
+
+CheckReadyToBoot:
+ movl (%esi), %eax # eax = ApLoopMode for POST
+ cmpb $1, 0xC(%esp) # Check ReadyToBoot flag?
+ jnz CheckWakeUpManner
+
+ movl $ApInHltLoop, %eax
+ cmpl $1, 0xD(%esp) # Check if C-State enable?
+ jnz CheckWakeUpManner
+
+ movl ApInMwaitLoop, %eax # eax = ApLoopMode for Read To Boot
+
+CheckWakeUpManner:
+ cli
+ cmpl $ApInHltLoop, %eax
+ jz HltApLoop
+
+ cmpl $ApInMwaitLoop, %eax
+ jnz CheckRunSignal
+
+ApMwaitLoop:
+ movl %esp, %eax # Set Monitor Address
+ xorl %ecx, %ecx # ecx = 0
+ xorl %edx, %edx # edx = 0
+ .byte 0x0f,0x1,0xc8 # MONITOR
+
+ movl 4(%esp), %eax # Mwait Cx, Target C-State per eax[7:4]
+ .byte 0x0f,0x1,0xc9 # MWAIT
+
+CheckRunSignal:
+ cmpl %ebx, (%esp) # Check if run signal correct?
+ jz WakeUpThisAp # Jmp to execute AP task
+ PAUSE32
+ jmp CheckReadyToBoot # Unknown break, go checking run manner
+
+HltApLoop:
+ cli
+ hlt
+ jmp HltApLoop # Jump to halt loop
+
+RendezvousFunnelProcEnd:
+#-------------------------------------------------------------------------------------
+# AsmGetAddressMap (&AddressMap);
+#-------------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmGetAddressMap)
+ASM_PFX(AsmGetAddressMap):
+
+ pushal
+ movl %esp,%ebp
+
+ movl 0x24(%ebp), %ebx
+ movl $RendezvousFunnelProcStart, (%ebx)
+ movl $(PMODE_ENTRY - RendezvousFunnelProcStart), 0x4(%ebx)
+ movl $(FLAT32_JUMP - RendezvousFunnelProcStart), 0x8(%ebx)
+ movl $(RendezvousFunnelProcEnd - RendezvousFunnelProcStart), 0x0c(%ebx)
+
+ popal
+ ret
+
+#-------------------------------------------------------------------------------------
+#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);
+#-------------------------------------------------------------------------------------
+.equ CPU_SWITCH_STATE_IDLE, 0
+.equ CPU_SWITCH_STATE_STORED, 1
+.equ CPU_SWITCH_STATE_LOADED, 2
+
+ASM_GLOBAL ASM_PFX(AsmExchangeRole)
+ASM_PFX(AsmExchangeRole):
+ # 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.
+ pushal
+ movl %esp,%ebp
+
+ # esi contains MyInfo pointer
+ movl 0x24(%ebp), %esi
+
+ # edi contains OthersInfo pointer
+ movl 0x28(%ebp), %edi
+
+ #Store EFLAGS, GDTR and IDTR regiter to stack
+ pushfl
+ sgdt 8(%esi)
+ sidt 14(%esi)
+
+ # Store the its StackPointer
+ movl %esp, 4(%esi)
+
+ # update its switch state to STORED
+ movb $CPU_SWITCH_STATE_STORED, (%esi)
+
+WaitForOtherStored:
+ # wait until the other CPU finish storing its state
+ cmpb $CPU_SWITCH_STATE_STORED, (%edi)
+ jz OtherStored
+ pause
+ jmp WaitForOtherStored
+
+OtherStored:
+ # Since another CPU already stored its state, load them
+ # load GDTR value
+ lgdt 8(%edi)
+
+ # load IDTR value
+ lidt 14(%edi)
+
+ # load its future StackPointer
+ movl 4(%edi), %esp
+
+ # update the other CPU's switch state to LOADED
+ movb $CPU_SWITCH_STATE_LOADED, (%edi)
+
+WaitForOtherLoaded:
+ # wait until the other CPU finish loading new state,
+ # otherwise the data in stack may corrupt
+ cmpb $CPU_SWITCH_STATE_LOADED, (%esi)
+ jz OtherLoaded
+ pause
+ jmp WaitForOtherLoaded
+
+OtherLoaded:
+ # since the other CPU already get the data it want, leave this procedure
+ popfl
+
+ popal
+ ret
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.asm b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.asm
new file mode 100644
index 0000000..a38e928
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.asm
@@ -0,0 +1,440 @@
+;-------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+; Module Name:
+;
+; MPFuncs32.asm
+;
+; Abstract:
+;
+; This is the assembly code for MP (Multiple-processor) support
+;
+;-------------------------------------------------------------------------------
+
+.686p
+.model flat
+.code
+
+include AsmInclude.inc
+InitializeFloatingPointUnits PROTO C
+
+EXTERNDEF C mBspSwitched:BYTE
+EXTERNDEF C mNewProcessorNumber:DWORD
+EXTERNDEF C mMonitorDataAddress:DWORD
+
+;-------------------------------------------------------------------------------------
+FJMP32 MACRO Selector, Offset
+ DB 066h
+ DB 067h
+ DB 0EAh ; far jump
+ DD Offset ; 32-bit offset
+ DW Selector ; 16-bit selector
+ ENDM
+FCALL32 MACRO Selector, Offset
+ DB 09Ah
+ DD Offset ; 32-bit offset
+ DW Selector ; 16-bit selector
+ ENDM
+;-------------------------------------------------------------------------------------
+;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);
+
+RendezvousFunnelProc PROC near C 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 00000000h ; mov eax, 0
+ db 0Fh, 0A2h ; cpuid
+ db 66h, 3dh
+ dd 0000000Bh ; cmp eax, 0b
+ db 73h
+ db X2Apic - $ - 1 ; jnb X2Apic
+
+; Processor is not x2APIC capable, so get 8-bit APIC ID
+ db 66h, 0B8h
+ dd 00000001h ; mov eax, 1
+ db 0Fh, 0A2h ; cpuid
+ db 66h, 0C1h, 0EBh, 18h ; shr ebx, 24
+ db 0ebh
+ db CheckInitFlag - $ - 1 ; jmp CheckInitFlag
+
+; Processor is x2APIC capable, so get 32-bit x2APIC ID
+X2Apic::
+ db 66h, 0B8h
+ dd 0000000Bh ; mov eax, 0b
+ db 66h, 31h, 0c9h ; xor ecx, ecx
+ db 0Fh, 0A2h ; cpuid
+ db 66h, 89h, 0d3h ; mov ebx, edx
+
+CheckInitFlag::
+; EBX is keeping APIC ID
+; If it is the first time AP wakes up, just record AP's BIST
+; Otherwise, switch to flat mode
+
+ db 0BEh
+ dw InitFlag ; mov si, InitFlag
+ db 66h, 83h, 3Ch, 00h ; cmp dword ptr [si], 0
+ db 74h
+ db flat32Start - $ - 1 ; jz flat32Start
+
+; Increase ApCount as processor number for index of BIST Info array
+
+ db 66h, 0a1h ; mov eax, [ApCountLocation]
+ dw ApCountLocation
+IncApCount::
+ db 66h, 67h, 8dh, 48h, 01 ; lea ecx, [eax+1]
+ db 0f0h, 66h, 0fh, 0b1h, 0eh ; lock cmpxchg [ApCountLocation], ecx
+ dw ApCountLocation
+ db 75h
+ db IncApCount - $ - 1 ; jnz IncApCount
+
+ db 66h, 0ffh, 0c0h ; inc eax ; AP processor number starts from 1
+
+; Record BIST information
+;
+ db 66h, 67h, 8dh, 34h, 0c5h ; lea esi, [BistBuffer + eax*8]
+ dd BistBuffer
+
+ db 66h, 89h, 1ch ; mov dword ptr [si], ebx ; APIC ID
+ db 66h, 89h, 6Ch, 04h ; mov dword ptr [si + 4], ebp ; Store BIST value
+
+ cli
+ hlt
+ jmp $-2
+
+; Switch to flat mode.
+
+flat32Start::
+
+ db 0BEh
+ dw BufferStart ; mov si, BufferStart
+ db 66h, 8Bh, 0Ch ; mov ecx,dword ptr [si] ; ECX is keeping the start address of wakeup buffer
+
+ db 0FAh ; cli
+ db 0BEh
+ dw GdtrProfile ; mov si, GdtrProfile
+ db 66h ; db 66h
+ db 2Eh,0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
+
+ db 0BEh
+ dw IdtrProfile ; mov si, IdtrProfile
+ db 66h ; db 66h
+ db 2Eh,0Fh, 01h, 1Ch ; lidt 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, 01h ; or eax, 000000001h ; Set PE bit (bit #0)
+ db 0Fh, 22h, 0C0h ; mov cr0, eax
+
+
+;step-4:
+
+FLAT32_JUMP::
+ FJMP32 010h,0h ; Far jmp using code segment descriptor
+
+PMODE_ENTRY:: ; protected mode entry point
+
+ mov ax, 8h
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax ; Flat mode setup.
+
+ mov esi, ecx
+
+ mov edi, esi
+ add edi, InitFlag
+ cmp dword ptr [edi], 2 ; Check whether in S3 boot path
+ jz ProgramDynamicStack
+
+ProgramStaticStack::
+
+ ;
+ ; Get processor number for this AP
+ ; Note that BSP may become an AP due to SwitchBsp()
+ ;
+
+ xor ecx, ecx
+ lea edi, [esi + BistBuffer]
+
+GetProcNumber::
+ cmp [edi], ebx ; APIC ID match?
+ jz Found
+ add edi, 8
+ inc ecx
+ cmp ecx, dword ptr [esi + ApCountLocation]
+ jbe GetProcNumber
+
+Found::
+ ;
+ ; ProgramStack
+ ;
+
+ mov edi, esi
+ add edi, StackSize
+ mov eax, dword ptr [edi]
+ inc ecx
+ mul ecx ; EAX = StackSize * (CpuNumber + 1)
+ dec ecx
+
+ mov edi, esi
+ add edi, StackStart
+ mov ebx, dword ptr [edi]
+ add eax, ebx ; EAX = StackStart + StackSize * (CpuNumber + 1)
+
+ mov esp, eax
+ sub esp, MonitorFilterSize ; Reserved Monitor data space
+ mov ebp, ecx ; Save processor number in ebp
+ jmp ProgramStackDone
+
+ProgramDynamicStack::
+
+ mov edi, esi
+ add edi, LockLocation
+ mov al, NotVacantFlag
+TestLock::
+ xchg byte ptr [edi], al
+ cmp al, NotVacantFlag
+ jz TestLock
+
+ mov edi, esi
+ add edi, StackSize
+ mov eax, dword ptr [edi]
+ mov edi, esi
+ add edi, StackStart
+ add eax, dword ptr [edi]
+ mov esp, eax
+ mov dword ptr [edi], eax
+
+Releaselock::
+ mov al, VacantFlag
+ mov edi, esi
+ add edi, LockLocation
+ xchg byte ptr [edi], al
+
+ProgramStackDone::
+
+ ;
+ ; Call assembly function to initialize FPU.
+ ;
+ mov ebx, InitializeFloatingPointUnits
+ call ebx
+
+ ;
+ ; Call C Function
+ ;
+ mov edi, esi
+ add edi, RendezvousProc
+ add esi, ApLoopModeLocation ; esi = ApLoopMode address location
+
+ xor ebx, ebx
+ mov dword ptr [esp + 0Ch], ebx ; Clean ReadyToBoot Flag
+ mov bx, bp ; bx = the lowest 16bit of CpuNumber
+ or ebx, StartupApSignal ; Construct AP run Singal
+
+WakeUpThisAp::
+ mov eax, dword ptr [edi]
+ test eax, eax
+ jz CheckWakeUpManner
+
+ push ebp ; Push processor number
+ call eax ; Call C function
+ add esp, 4
+
+ ;
+ ; Check if BSP was switched
+ ;
+ mov eax, offset mBspSwitched
+ cmp byte ptr [eax], 0
+ jz CheckReadyToBoot
+
+ mov byte ptr [eax], 0 ;clear BSP switch flag
+
+ mov eax, offset mNewProcessorNumber
+ mov ebp, [eax] ; rbp = new processor number
+
+ mov bx, bp ; bx = the lowest 16bit of CpuNumber
+
+ ;
+ ; Assign the dedicated AP stack for the new AP
+ ;
+ mov eax, offset mMonitorDataAddress
+ mov esp, [eax]
+
+CheckReadyToBoot::
+ mov eax, dword ptr [esi] ; eax = ApLoopMode for POST
+ cmp byte ptr [esp + 0Ch], 1 ; Check ReadyToBoot flag?
+ jnz CheckWakeUpManner
+
+ mov eax, ApInHltLoop
+ cmp byte ptr [esp + 0Dh], 1 ; Check if C-State enable?
+ jnz CheckWakeUpManner
+
+ mov eax, ApInMwaitLoop ; eax = ApLoopMode for Read To Boot
+
+CheckWakeUpManner::
+ cli
+ cmp eax, ApInHltLoop
+ jz HltApLoop
+
+ cmp eax, ApInMwaitLoop
+ jnz CheckRunSignal
+
+ApMwaitLoop::
+ mov eax, esp ; Set Monitor Address
+ xor ecx, ecx ; ecx = 0
+ xor edx, edx ; edx = 0
+ DB 0fh, 1, 0c8h ; MONITOR
+
+ mov eax, dword ptr [esp + 4] ; Mwait Cx, Target C-State per eax[7:4]
+ DB 0fh, 1, 0c9h ; MWAIT
+
+CheckRunSignal::
+ cmp dword ptr [esp], ebx ; Check if run signal correct?
+ jz WakeUpThisAp ; Jmp to execute AP task
+ PAUSE32
+ jmp CheckReadyToBoot ; Unknown break, go checking run manner
+
+HltApLoop::
+ cli
+ hlt
+ jmp HltApLoop ; Jump to halt loop
+
+RendezvousFunnelProc ENDP
+RendezvousFunnelProcEnd::
+;-------------------------------------------------------------------------------------
+; AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+AsmGetAddressMap PROC near C PUBLIC
+
+ pushad
+ mov ebp,esp
+
+ mov ebx, dword ptr [ebp+24h]
+ mov dword ptr [ebx], RendezvousFunnelProcStart
+ mov dword ptr [ebx+4h], PMODE_ENTRY - RendezvousFunnelProcStart
+ mov dword ptr [ebx+8h], FLAT32_JUMP - RendezvousFunnelProcStart
+ mov dword ptr [ebx+0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+
+ popad
+ ret
+AsmGetAddressMap 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 near C 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.
+ pushad
+ mov ebp,esp
+
+ ; esi contains MyInfo pointer
+ mov esi, dword ptr [ebp+24h]
+
+ ; edi contains OthersInfo pointer
+ mov edi, dword ptr [ebp+28h]
+
+ ;Store EFLAGS, GDTR and IDTR regiter to stack
+ pushfd
+ sgdt fword ptr [esi+8]
+ sidt fword ptr [esi+14]
+
+ ; Store the its StackPointer
+ mov dword ptr [esi+4],esp
+
+ ; update its switch state to STORED
+ mov byte ptr [esi], CPU_SWITCH_STATE_STORED
+
+WaitForOtherStored::
+ ; wait until the other CPU finish storing its state
+ cmp byte ptr [edi], CPU_SWITCH_STATE_STORED
+ jz OtherStored
+ pause
+ jmp WaitForOtherStored
+
+OtherStored::
+ ; Since another CPU already stored its state, load them
+ ; load GDTR value
+ lgdt fword ptr [edi+8]
+
+ ; load IDTR value
+ lidt fword ptr [edi+14]
+
+ ; load its future StackPointer
+ mov esp, dword ptr [edi+4]
+
+ ; update the other CPU's switch state to LOADED
+ mov byte ptr [edi], CPU_SWITCH_STATE_LOADED
+
+WaitForOtherLoaded::
+ ; wait until the other CPU finish loading new state,
+ ; otherwise the data in stack may corrupt
+ cmp byte ptr [esi], CPU_SWITCH_STATE_LOADED
+ jz OtherLoaded
+ pause
+ jmp WaitForOtherLoaded
+
+OtherLoaded::
+ ; since the other CPU already get the data it want, leave this procedure
+ popfd
+
+ popad
+ ret
+AsmExchangeRole ENDP
+END
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.c b/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.c
new file mode 100644
index 0000000..835b422
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.c
@@ -0,0 +1,149 @@
+/** @file
+
+ Code for Max CPUID Limit Feature
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: LimitCpuIdValue.c
+
+**/
+
+#include "LimitCpuIdValue.h"
+
+BOOLEAN EnableLimitCpuIdValue[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];
+
+/**
+ Detect capability of Max CPUID Limit feature for specified processor.
+
+ This function detects capability of Max CPUID Limit feature for specified processor.
+
+ @param ProcessorNumber The handle number of specified processor.
+
+**/
+VOID
+MaxCpuidLimitDetect (
+ UINTN ProcessorNumber
+ )
+{
+ EFI_CPUID_REGISTER *CpuidRegisters;
+ UINT8 MaxCpuid;
+
+ CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_SIGNATURE);
+ ASSERT (CpuidRegisters != NULL);
+
+ MaxCpuid = (UINT8) CpuidRegisters->RegEax;
+ if (MaxCpuid > 3) {
+ SetProcessorFeatureCapability (ProcessorNumber, MaxCpuidValueLimit, NULL);
+ }
+}
+
+/**
+ Configures Processor Feature Lists for Max CPUID Limit feature for all processors.
+
+ This function configures Processor Feature Lists for Max CPUID Limit feature for all processors.
+
+**/
+VOID
+MaxCpuidLimitConfigFeatureList (
+ VOID
+ )
+{
+ UINTN ProcessorNumber;
+ BOOLEAN UserConfigurationSet;
+
+ UserConfigurationSet = FALSE;
+ if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT) != 0) {
+ UserConfigurationSet = TRUE;
+ }
+
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+ //
+ // Check whether this logical processor supports Max CPUID Value Limit
+ //
+ if (GetProcessorFeatureCapability (ProcessorNumber, MaxCpuidValueLimit, NULL)) {
+ if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {
+ //
+ // Set the bit of Max CPUID Value Limit capability according to BSP capability.
+ //
+ PcdSet32 (PcdCpuProcessorFeatureCapability, PcdGet32 (PcdCpuProcessorFeatureCapability) | PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT);
+ //
+ // Set the bit of Max CPUID Value Limit setting according to BSP setting.
+ //
+ if (UserConfigurationSet) {
+ PcdSet32 (PcdCpuProcessorFeatureSetting, PcdGet32 (PcdCpuProcessorFeatureSetting) | PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT);
+ }
+ }
+
+ //
+ // If this logical processor supports Max CPUID Value Limit, then add feature into feature list for operation
+ // on corresponding register.
+ //
+ EnableLimitCpuIdValue[ProcessorNumber] = UserConfigurationSet;
+ AppendProcessorFeatureIntoList (ProcessorNumber, MaxCpuidValueLimit, &(EnableLimitCpuIdValue[ProcessorNumber]));
+ }
+ }
+}
+
+/**
+ Produces entry of Max CPUID Limit feature in Register Table for specified processor.
+
+ This function produces entry of Max CPUID Limit feature in Register Table for specified processor.
+
+ @param ProcessorNumber The handle number of specified processor.
+ @param Attribute Pointer to the attribute
+
+**/
+VOID
+MaxCpuidLimitReg (
+ UINTN ProcessorNumber,
+ VOID *Attribute
+ )
+{
+ BOOLEAN *Enable;
+ UINT64 Value;
+
+ //
+ // If Attribute is TRUE, then write 1 to MSR_IA32_MISC_ENABLE[22].
+ // Otherwise, write 0 to the bit.
+ //
+ Enable = (BOOLEAN *) Attribute;
+ Value = 0;
+ if (*Enable) {
+ Value = 1;
+ }
+
+ WriteRegisterTable (
+ ProcessorNumber,
+ Msr,
+ MSR_IA32_MISC_ENABLE,
+ N_MSR_LIMIT_CPUID_MAXVAL,
+ 1,
+ Value
+ );
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.h b/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.h
new file mode 100644
index 0000000..e948094
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.h
@@ -0,0 +1,82 @@
+/** @file
+
+ Include file for Max CPUID Limit Feature
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: LimitCpuIdValue.h
+
+**/
+
+#ifndef _CPU_LIMIT_CPUID_VALUE_H_
+#define _CPU_LIMIT_CPUID_VALUE_H_
+
+#include "Cpu.h"
+#include "MpService.h"
+
+/**
+ Detect capability of Max CPUID Limit feature for specified processor.
+
+ This function detects capability of Max CPUID Limit feature for specified processor.
+
+ @param ProcessorNumber The handle number of specified processor.
+
+**/
+VOID
+MaxCpuidLimitDetect (
+ UINTN ProcessorNumber
+ );
+
+/**
+ Configures Processor Feature Lists for Max CPUID Limit feature for all processors.
+
+ This function configures Processor Feature Lists for Max CPUID Limit feature for all processors.
+
+**/
+VOID
+MaxCpuidLimitConfigFeatureList (
+ VOID
+ );
+
+/**
+ Produces entry of Max CPUID Limit feature in Register Table for specified processor.
+
+ This function produces entry of Max CPUID Limit feature in Register Table for specified processor.
+
+ @param ProcessorNumber The handle number of specified processor.
+ @param Attribute Pointer to the attribute
+
+**/
+VOID
+MaxCpuidLimitReg (
+ UINTN ProcessorNumber,
+ VOID *Attribute
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.c b/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.c
new file mode 100644
index 0000000..a02c82d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.c
@@ -0,0 +1,162 @@
+/** @file
+
+ Code for APIC feature.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MpApic.c
+
+**/
+
+#include "MpApic.h"
+
+/**
+ Sort the APIC ID of all processors.
+
+ This function sorts the APIC ID of all processors so that processor number is assigned in the
+ ascending order of APIC ID which eases MP debugging. SMBIOS logic also depends on this assumption.
+
+**/
+VOID
+SortApicId (
+ VOID
+ )
+{
+ UINTN Index1;
+ UINTN Index2;
+ UINTN Index3;
+ UINT32 ApicId;
+ UINT32 Bist;
+
+ if (mExchangeInfo->ApCount != 0) {
+ mCpuConfigConextBuffer.NumberOfProcessors += mExchangeInfo->ApCount;
+
+ for (Index1 = 0; Index1 < mExchangeInfo->ApCount; Index1++) {
+ Index3 = Index1;
+ //
+ // Sort key is the hardware default APIC ID
+ //
+ ApicId = mExchangeInfo->BistBuffer[Index1].ApicId;
+ for (Index2 = Index1 + 1; Index2 <= mExchangeInfo->ApCount; Index2++) {
+ if (ApicId > mExchangeInfo->BistBuffer[Index2].ApicId) {
+ Index3 = Index2;
+ ApicId = mExchangeInfo->BistBuffer[Index2].ApicId;
+ }
+ }
+ if (Index3 != Index1) {
+ mExchangeInfo->BistBuffer[Index3].ApicId = mExchangeInfo->BistBuffer[Index1].ApicId;
+ mExchangeInfo->BistBuffer[Index1].ApicId = ApicId;
+ Bist = mExchangeInfo->BistBuffer[Index3].Bist;
+ mExchangeInfo->BistBuffer[Index3].Bist = mExchangeInfo->BistBuffer[Index1].Bist;
+ mExchangeInfo->BistBuffer[Index1].Bist = Bist;
+ }
+ }
+
+ //
+ // Get the processor number for the BSP
+ //
+ ApicId = GetInitialApicId ();
+ for (Index1 = 0; Index1 < mCpuConfigConextBuffer.NumberOfProcessors; Index1++) {
+ if (mExchangeInfo->BistBuffer[Index1].ApicId == ApicId) {
+ mCpuConfigConextBuffer.BspNumber = Index1;
+ break;
+ }
+ }
+ }
+}
+
+/**
+ Check if there is legacy APIC ID conflict among all processors.
+
+ @retval EFI_SUCCESS No coflict
+ @retval EFI_UNSUPPORTED There is legacy APIC ID conflict and can't be rsolved in xAPIC mode
+**/
+EFI_STATUS
+CheckApicId (
+ VOID
+ )
+{
+ UINTN Index1;
+ UINTN Index2;
+ BOOLEAN X2ApicCapable;
+
+ X2ApicCapable = FALSE;
+
+ //
+ // If xAPIC mode is configured, then check if there is any APIC ID conflict.
+ //
+ ASSERT (mCpuConfigConextBuffer.NumberOfProcessors <= FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber));
+
+ if (mCpuConfigConextBuffer.NumberOfProcessors > 255) {
+ DEBUG ((EFI_D_ERROR, "Number of processors > 255!\n"));
+ return EFI_UNSUPPORTED;
+ } else {
+ //
+ // Check if there is 8-bit legacy APIC ID conflict with hardware default socket IDs.
+ //
+ for (Index1 = 0; Index1 < mCpuConfigConextBuffer.NumberOfProcessors; Index1++) {
+ for (Index2 = Index1 + 1; Index2 < mCpuConfigConextBuffer.NumberOfProcessors; Index2++) {
+ if ((UINT8) mExchangeInfo->BistBuffer[Index1].ApicId == (UINT8) mExchangeInfo->BistBuffer[Index2].ApicId) {
+ break;
+ }
+ }
+ if (Index2 < mCpuConfigConextBuffer.NumberOfProcessors) {
+ DEBUG ((EFI_D_ERROR, "Legacy APIC ID conflict with hardware socket ID but x2APIC mode is not supported!\n"));
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Assign a package scope BSP responsible for package scope programming.
+
+ This functions assigns the processor with the least APIC ID within a processor package as
+ the package BSP.
+
+**/
+VOID
+AssignPackageBsp (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT32 PackageId;
+
+ mCpuConfigConextBuffer.CollectedDataBuffer[0].PackageBsp = TRUE;
+ PackageId = mCpuConfigConextBuffer.CollectedDataBuffer[0].ProcessorLocation.Package;
+ for (Index = 1; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {
+ if (PackageId != mCpuConfigConextBuffer.CollectedDataBuffer[Index].ProcessorLocation.Package) {
+ PackageId = mCpuConfigConextBuffer.CollectedDataBuffer[Index].ProcessorLocation.Package;
+ mCpuConfigConextBuffer.CollectedDataBuffer[Index].PackageBsp = TRUE;
+ }
+ }
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.h b/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.h
new file mode 100644
index 0000000..e4f05ca
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.h
@@ -0,0 +1,77 @@
+/** @file
+
+ Include file for APIC feature.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MpApic.h
+
+**/
+
+#ifndef _CPU_MP_APIC_H_
+#define _CPU_MP_APIC_H_
+
+#include "Cpu.h"
+
+/**
+ Sort the APIC ID of all processors.
+
+ This function sorts the APIC ID of all processors so that processor number is assigned in the
+ ascending order of APIC ID which eases MP debugging. SMBIOS logic also depends on this assumption.
+
+**/
+VOID
+SortApicId (
+ VOID
+ );
+
+/**
+ Check if there is legacy APIC ID conflict among all processors.
+
+ @retval EFI_SUCCESS No coflict or conflict was resoved by force x2APIC mode
+ @retval EFI_UNSUPPORTED There is legacy APIC ID conflict and can't be rsolved in xAPIC mode
+**/
+EFI_STATUS
+CheckApicId (
+ VOID
+ );
+
+/**
+ Assign a package scope BSP responsible for package scope programming.
+
+ This functions assigns the processor with the least APIC ID within a processor package as
+ the package BSP.
+
+**/
+VOID
+AssignPackageBsp (
+ VOID
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.c b/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.c
new file mode 100644
index 0000000..d13082f
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.c
@@ -0,0 +1,578 @@
+/** @file
+
+ Common functions for CPU DXE module.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MpCommon.c
+
+**/
+
+#include "MpService.h"
+#include "Cpu.h"
+#include "ArchSpecificDef.h"
+
+AP_PROCEDURE mApFunction = NULL;
+AP_PROCEDURE SimpleAPProcedure;
+UINT32 NumberToFinish;
+UINTN mApCount = 0;
+UINTN mStartupVectorSize;
+EFI_PHYSICAL_ADDRESS mApMachineCheckHandlerBase;
+UINT32 mApMachineCheckHandlerSize;
+
+/**
+ Allocates startup vector for APs.
+
+ This function allocates Startup vector for APs.
+
+ @param Size The size of startup vector.
+
+**/
+VOID
+AllocateStartupVector (
+ UINTN Size
+ )
+{
+ EFI_STATUS Status;
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;
+ EFI_PHYSICAL_ADDRESS StartAddress;
+
+ mStartupVectorSize = Size;
+
+ //
+ // In order to allocate startup vector for APs under 1M, try to locate
+ // Generic Memory Test Protocol to test memory before allocation.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiGenericMemTestProtocolGuid,
+ NULL,
+ (VOID **) &GenMemoryTest
+ );
+ if (EFI_ERROR (Status)) {
+ GenMemoryTest = NULL;
+ }
+
+ //
+ // Allocate wakeup buffer below 640K. Don't touch legacy region.
+ // Leave some room immediately below 640K in for CSM module.
+ // PcdEbdaReservedMemorySize has been required to be a multiple of 4KB.
+ //
+ StartAddress = 0xA0000 - PcdGet32 (PcdEbdaReservedMemorySize) - (EFI_SIZE_TO_PAGES (Size) * EFI_PAGE_SIZE);
+ for (mStartupVector = StartAddress; mStartupVector >= 0x2000; mStartupVector -= (EFI_SIZE_TO_PAGES (Size) * EFI_PAGE_SIZE)) {
+ //
+ // If Generic Memory Test Protocol has been located successfully, call CompatibleRangeTest() to test
+ // the range we are going to allocate. If the protocol has not been located, then the memory test would
+ // be skipped.
+ //
+ if (GenMemoryTest != NULL) {
+ Status = GenMemoryTest->CompatibleRangeTest (
+ GenMemoryTest,
+ mStartupVector,
+ EFI_SIZE_TO_PAGES (Size) * EFI_PAGE_SIZE
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ }
+
+ //
+ // If finally no CSM in the platform, this wakeup buffer is to be used in S3 boot path.
+ //
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (Size),
+ &mStartupVector
+ );
+
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ ASSERT_EFI_ERROR (Status);
+}
+
+ /**
+ Count the number of APs that have been switched
+ to E0000 or F0000 segments by ReAllocateMemoryForAP().
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+LegacyRegionAPCount (
+ IN UINTN ProcessorNumber
+ )
+{
+ AcquireSpinLock (&mMPSystemData.APSerializeLock);
+
+ mApCount++;
+
+ ReleaseSpinLock (&mMPSystemData.APSerializeLock);
+}
+
+
+/**
+ This AP function will place AP to the suitable state.
+
+ If C-State is enable, try to place AP to the Mwait-Loop with deepest C-State,
+ otherwize place AP to Hlt-Loop state.
+
+ @param Buffer Pointer to MP Services.
+**/
+VOID
+EFIAPI
+ChangeApLoopMode (
+ IN VOID *Buffer
+ )
+{
+ UINTN ProcessorNumber;
+ MONITOR_MWAIT_DATA *MonitorAddr;
+
+ WhoAmI (&mMpService, &ProcessorNumber);
+
+ //
+ // Set the ReadyToBootFlag for AP.
+ //
+ MonitorAddr = GetMonitorDataAddress (ProcessorNumber);
+ MonitorAddr->ReadyToBootFlag = TRUE;
+}
+
+/**
+ Protocol notification that will wake up and place AP to the suitable state
+ before booting to OS.
+
+ @param Event The triggered event.
+ @param Context Context for this event.
+**/
+VOID
+EFIAPI
+ChangeApLoopModeCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ while (ApRunning()) {
+ CpuPause ();
+ }
+
+ Status = mMpService.StartupAllAPs (
+ &mMpService,
+ ChangeApLoopMode,
+ FALSE,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Protocol notification that is fired when LegacyBios protocol is installed.
+
+ Re-allocate a wakeup buffer from E/F segment because the previous wakeup buffer
+ under 640K won't be preserved by the legacy OS.
+
+ @param Event The triggered event.
+ @param Context Context for this event.
+**/
+VOID
+EFIAPI
+ReAllocateMemoryForAP (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ VOID *LegacyRegion;
+ EFI_STATUS Status;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **)&LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ //
+ // Wait for all APs to finish their task before switching wakeup buffer
+ //
+ while (ApRunning()) {
+ CpuPause ();
+ }
+
+ //
+ // Allocate 4K aligned bytes from either 0xE0000 or 0xF0000.
+ // Note some CSM16 does not satisfy alignment request, so allocate a buffer of 2*4K
+ // and adjust the base address myself.
+ //
+ Status = LegacyBios->GetLegacyRegion (
+ LegacyBios,
+ 0x2000,
+ 0,
+ 0x1000,
+ &LegacyRegion
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((((UINTN)LegacyRegion) & 0xfff) != 0) {
+ LegacyRegion = (VOID *)(UINTN)((((UINTN)LegacyRegion) + 0xfff) & ~((UINTN)0xfff));
+ }
+
+ //
+ // Get the address map of startup code for AP,
+ // including code size, and offset of long jump instructions to redirect.
+ //
+ AsmGetAddressMap (&AddressMap);
+
+ //
+ // Update exchange info and copy AP startup code to new buffer in legacy region.
+ //
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mStartupVector + AddressMap.Size);
+ ExchangeInfo->BufferStart = (UINT32) (UINTN) LegacyRegion;
+ RedirectFarJump (&AddressMap, (EFI_PHYSICAL_ADDRESS) (UINTN) LegacyRegion);
+
+ //
+ // Switch all APs to use new wakeup buffer
+ //
+ Status = LegacyBios->CopyLegacyRegion (
+ LegacyBios,
+ mStartupVectorSize,
+ LegacyRegion,
+ (VOID *)(UINTN)mStartupVector
+ );
+
+ SendInitSipiSipiIpis (
+ TRUE,
+ 0,
+ LegacyRegionAPCount
+ );
+
+ //
+ // Wait until all APs finish
+ //
+ while (mApCount < mAcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ //
+ // Free original wakeup buffer
+ //
+ FreePages ((VOID *)(UINTN)mStartupVector, EFI_SIZE_TO_PAGES (mStartupVectorSize));
+
+ mStartupVector = (EFI_PHYSICAL_ADDRESS)(UINTN)LegacyRegion;
+ mAcpiCpuData->StartupVector = mStartupVector;
+ mExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mStartupVector + AddressMap.Size);
+}
+
+/**
+ Allocate aligned ACPI NVS memory below 4G.
+
+ This function allocates aligned ACPI NVS memory below 4G.
+
+ @param Size Size of memory region to allocate
+ @param Alignment Alignment in bytes
+
+ @return Base address of the allocated region
+
+**/
+VOID*
+AllocateAlignedAcpiNvsMemory (
+ IN UINTN Size,
+ IN UINTN Alignment
+ )
+{
+ UINTN PointerValue;
+ VOID *Pointer;
+
+ Pointer = AllocateAcpiNvsMemoryBelow4G (Size + Alignment - 1);
+
+ PointerValue = (UINTN) Pointer;
+ PointerValue = (PointerValue + Alignment - 1) / Alignment * Alignment;
+
+ Pointer = (VOID *) PointerValue;
+
+ return Pointer;
+}
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+ @param Size Size of memory to allocate.
+
+ @return Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+ IN UINTN Size
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ VOID* Buffer;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xffffffff;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &Address
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Buffer = (VOID *) (UINTN) Address;
+ ZeroMem (Buffer, Size);
+
+ return Buffer;
+}
+
+/**
+ Sends INIT-SIPI-SIPI to AP.
+
+ This function sends INIT-SIPI-SIPI to AP, and assign procedure specified by ApFunction.
+
+ @param Broadcast If TRUE, broadcase IPI to all APs; otherwise, send to specified AP.
+ @param ApicID The Local APIC ID of the specified AP. If Broadcast is TRUE, it is ignored.
+ @param ApFunction The procedure for AP to work on.
+
+**/
+VOID
+SendInitSipiSipiIpis (
+ IN BOOLEAN Broadcast,
+ IN UINT32 ApicID,
+ IN AP_PROCEDURE ApFunction
+ )
+{
+ mApFunction = ApFunction;
+
+ if (Broadcast) {
+ SendInitSipiSipiAllExcludingSelf ((UINT32) mStartupVector);
+ } else {
+ SendInitSipiSipi (ApicID, (UINT32) mStartupVector);
+ }
+}
+
+/**
+ A simple wrapper function dispatched to AP.
+
+ This function is a simple wrapper function dispatched to AP. It invokes task for AP, and count down
+ the number.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+SimpleApProcWrapper (
+ IN UINTN ProcessorNumber
+ )
+{
+ //
+ // Program virtual wire mode and Local APIC timer for AP, since it will be lost after AP wake up
+ //
+ ProgramVirtualWireMode ();
+ DisableLvtInterrupts ();
+ InitializeApicTimer (mLocalApicTimerDivisor, mLocalApicTimerInitialCount, FALSE, 0);
+
+ // Initialize Debug Agent to support source level debug on AP code.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL);
+
+ //
+ // If it is necessary to restore register setting after INIT signal,
+ // call SetProcessorRegister().
+ //
+ if (mRestoreSettingAfterInit) {
+ SetProcessorRegister (ProcessorNumber);
+ }
+
+ //
+ // Invoke task for AP.
+ //
+ SimpleAPProcedure (ProcessorNumber);
+
+ //
+ // Count down the number with lock mechanism.
+ //
+ InterlockedDecrement (&NumberToFinish);
+}
+
+/**
+ Dispatches task to AP.
+
+ This function dispatches task to AP. The BSP waits until specified APs have finished.
+
+ @param Broadcast If TRUE, send task to all APs; otherwise, send to specified AP.
+ @param ApicID The Local APIC ID of the specified AP. If Broadcast is TRUE, it is ignored.
+ @param Procedure The procedure for AP to work on.
+
+**/
+VOID
+DispatchAPAndWait (
+ IN BOOLEAN Broadcast,
+ IN UINT32 ApicID,
+ IN AP_PROCEDURE Procedure
+ )
+{
+ //
+ // Prepares the task for AP. It will invoked by SimpleApProcWrapper.
+ //
+ SimpleAPProcedure = Procedure;
+
+ //
+ // Checks whether the function is for broadcast.
+ //
+ if (Broadcast) {
+ //
+ // If in broadcast mode, the number to finish is the number of all APs
+ //
+ NumberToFinish = (UINT32) mCpuConfigConextBuffer.NumberOfProcessors - 1;
+ } else {
+ //
+ // If in non-broadcast mode, the number to finish is 1
+ //
+ NumberToFinish = 1;
+ }
+
+ //
+ // Wake up specified AP(s), and make them work on SimpleApProcWrapper, which
+ // will in turn invoke Procedure.
+ //
+ SendInitSipiSipiIpis (
+ Broadcast,
+ ApicID,
+ SimpleApProcWrapper
+ );
+
+ //
+ // BSP waits until specified AP(s) have finished.
+ //
+ while (NumberToFinish > 0) {
+ CpuPause ();
+ }
+}
+
+/**
+ Creates a copy of GDT and IDT for all APs.
+
+ This function creates a copy of GDT and IDT for all APs.
+
+ @param Gdtr Base and limit of GDT for AP
+ @param Idtr Base and limit of IDT for AP
+
+**/
+VOID
+PrepareGdtIdtForAP (
+ OUT IA32_DESCRIPTOR *Gdtr,
+ OUT IA32_DESCRIPTOR *Idtr
+ )
+{
+ SEGMENT_DESCRIPTOR *GdtForAP;
+ INTERRUPT_GATE_DESCRIPTOR *IdtForAP;
+ IA32_DESCRIPTOR GdtrForBSP;
+ IA32_DESCRIPTOR IdtrForBSP;
+ VOID *MachineCheckHandlerBuffer;
+
+ //
+ // Get the BSP's data of GDT and IDT
+ //
+ AsmReadGdtr ((IA32_DESCRIPTOR *) &GdtrForBSP);
+ AsmReadIdtr ((IA32_DESCRIPTOR *) &IdtrForBSP);
+
+ //
+ // Allocate ACPI NVS memory for GDT, IDT, and machine check handler.
+ // Combine allocation for ACPI NVS memory under 4G to save memory.
+ //
+ GdtForAP = AllocateAlignedAcpiNvsMemory (
+ (GdtrForBSP.Limit + 1) + (IdtrForBSP.Limit + 1) + (UINTN) ApMachineCheckHandlerEnd - (UINTN) ApMachineCheckHandler,
+ 8
+ );
+
+ //
+ // GDT base is 8-bype aligned, and its size is multiple of 8-bype, so IDT base here is
+ // also 8-bype aligned.
+ //
+ IdtForAP = (INTERRUPT_GATE_DESCRIPTOR *) ((UINTN) GdtForAP + GdtrForBSP.Limit + 1);
+ MachineCheckHandlerBuffer = (VOID *) ((UINTN) GdtForAP + (GdtrForBSP.Limit + 1) + (IdtrForBSP.Limit + 1));
+ //
+ // Make copy for APs' GDT & IDT
+ //
+ CopyMem (GdtForAP, (VOID *) GdtrForBSP.Base, GdtrForBSP.Limit + 1);
+ CopyMem (IdtForAP, (VOID *) IdtrForBSP.Base, IdtrForBSP.Limit + 1);
+
+ //
+ // Copy code for AP's machine check handler to ACPI NVS memory, and register in IDT
+ //
+ CopyMem (
+ MachineCheckHandlerBuffer,
+ (VOID *) (UINTN) ApMachineCheckHandler,
+ (UINTN) ApMachineCheckHandlerEnd - (UINTN) ApMachineCheckHandler
+ );
+ SetIdtEntry ((UINTN) MachineCheckHandlerBuffer, &IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK]);
+
+ //
+ // Set AP's profile for GDTR and IDTR
+ //
+ Gdtr->Base = (UINTN) GdtForAP;
+ Gdtr->Limit = GdtrForBSP.Limit;
+
+ Idtr->Base = (UINTN) IdtForAP;
+ Idtr->Limit = IdtrForBSP.Limit;
+
+ //
+ // Save the AP's machine check handler information
+ //
+ mApMachineCheckHandlerBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MachineCheckHandlerBuffer;
+ mApMachineCheckHandlerSize = (UINT32) ((UINTN) ApMachineCheckHandlerEnd - (UINTN) ApMachineCheckHandler);
+}
+
+/**
+ Get mointor data address for specified processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+ @return Pointer to monitor data.
+**/
+MONITOR_MWAIT_DATA *
+EFIAPI
+GetMonitorDataAddress (
+ IN UINTN ProcessorNumber
+ )
+{
+ return (MONITOR_MWAIT_DATA *) ((UINT8*) mExchangeInfo->StackStart + (ProcessorNumber + 1) * mExchangeInfo->StackSize - MONITOR_FILTER_SIZE);
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.h b/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.h
new file mode 100644
index 0000000..e873ca0
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.h
@@ -0,0 +1,367 @@
+/** @file
+
+ Include files of common functions for CPU DXE module.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MpCommon.h
+
+**/
+
+#ifndef _MP_COMMON_H_
+#define _MP_COMMON_H_
+
+#include "ArchSpecificDef.h"
+#include <AcpiCpuData.h>
+#include <IndustryStandard/SmBios.h>
+
+#include <Protocol/Smbios.h>
+#include <Protocol/MpService.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/GenericMemoryTest.h>
+#include <Protocol/Cpu.h>
+#include <Protocol/SmmConfiguration.h>
+#include <Protocol/Timer.h>
+#include <Protocol/TcgService.h>
+
+#include <Guid/StatusCodeDataTypeId.h>
+#include <Guid/HtBistHob.h>
+#include <Guid/EventGroup.h>
+#include <Guid/IdleLoopEvent.h>
+
+#include <Library/BaseLib.h>
+#include <Library/SynchronizationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HobLib.h>
+#include <Library/HiiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/CpuConfigLib.h>
+#include <Library/CpuLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Library/CpuOnlyResetLib.h>
+#include <Library/UefiCpuLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/SocketLga775Lib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/PrintLib.h>
+
+#define INTERRUPT_HANDLER_MACHINE_CHECK 0x12
+
+#define VACANT_FLAG 0x00
+#define NOT_VACANT_FLAG 0xff
+
+#define MICROSECOND 10
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 LimitLow;
+ UINT16 BaseLow;
+ UINT8 BaseMiddle;
+ UINT8 Attributes1;
+ UINT8 Attributes2;
+ UINT8 BaseHigh;
+} SEGMENT_DESCRIPTOR;
+
+#pragma pack()
+
+#define STARTUP_AP_SIGNAL 0x6E750000
+
+typedef enum {
+ ApInHltLoop = 1,
+ ApInMwaitLoop = 2,
+ ApInRunLoop = 3
+} AP_LOOP_MODE;
+
+typedef struct {
+ UINT32 StartupApSignal;
+ UINT32 MwaitTargetCstate;
+ AP_LOOP_MODE ApLoopMode;
+ BOOLEAN ReadyToBootFlag;
+ BOOLEAN CStateEnable;
+} MONITOR_MWAIT_DATA;
+
+//
+// The MONITOR_FILTER_SIZE be mulitple of 16 bytes,
+// to make sure AP's stack is 16-byte alignment on x64 arch.
+//
+#define MONITOR_FILTER_SIZE sizeof(MONITOR_MWAIT_DATA)
+
+typedef struct {
+ UINT32 ApicId;
+ UINT32 Bist;
+} BIST_INFO;
+
+//
+// MTRR table definitions
+//
+typedef struct {
+ UINT16 Index;
+ UINT64 Value;
+} EFI_MTRR_VALUES;
+
+typedef
+VOID
+(EFIAPI *AP_PROC_ENTRY) (
+ IN UINTN ProcessorNumber
+ );
+
+typedef
+VOID
+(*AP_PROCEDURE) (
+ IN UINTN ProcessorNumber
+ );
+
+//
+// Note that this structure is located immediately after the AP startup code
+// in the wakeup buffer. this structure is not always writeable if the wakeup
+// buffer is in the legacy region.
+//
+typedef struct {
+ UINTN Lock;
+ VOID *StackStart;
+ UINTN StackSize;
+ AP_PROC_ENTRY ApFunction;
+ IA32_DESCRIPTOR GdtrProfile;
+ IA32_DESCRIPTOR IdtrProfile;
+ UINT32 BufferStart;
+ UINT32 Cr3;
+ UINT32 InitFlag;
+ UINT32 ApCount;
+ AP_LOOP_MODE ApLoopMode;
+ BIST_INFO BistBuffer[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+} MP_CPU_EXCHANGE_INFO;
+
+extern MP_CPU_EXCHANGE_INFO *mExchangeInfo;
+extern AP_PROCEDURE mApFunction;
+extern CPU_CONFIG_CONTEXT_BUFFER mCpuConfigConextBuffer;
+extern EFI_PHYSICAL_ADDRESS mApMachineCheckHandlerBase;
+extern UINT32 mApMachineCheckHandlerSize;
+extern UINTN mLocalApicTimerDivisor;
+extern UINT32 mLocalApicTimerInitialCount;
+
+/**
+ Allocates startup vector for APs.
+
+ This function allocates Startup vector for APs.
+
+ @param Size The size of startup vector.
+
+**/
+VOID
+AllocateStartupVector (
+ UINTN Size
+ );
+
+/**
+ Creates a copy of GDT and IDT for all APs.
+
+ This function creates a copy of GDT and IDT for all APs.
+
+ @param Gdtr Base and limit of GDT for AP
+ @param Idtr Base and limit of IDT for AP
+
+**/
+VOID
+PrepareGdtIdtForAP (
+ OUT IA32_DESCRIPTOR *Gdtr,
+ OUT IA32_DESCRIPTOR *Idtr
+ );
+
+/**
+ Allocate aligned ACPI NVS memory below 4G.
+
+ This function allocates aligned ACPI NVS memory below 4G.
+
+ @param Size Size of memory region to allocate
+ @param Alignment Alignment in bytes
+
+ @return Base address of the allocated region
+
+**/
+VOID*
+AllocateAlignedAcpiNvsMemory (
+ IN UINTN Size,
+ IN UINTN Alignment
+ );
+
+/**
+ Prepares Startup Vector for APs.
+
+ This function prepares Startup Vector for APs.
+
+**/
+VOID
+PrepareAPStartupVector (
+ VOID
+ );
+
+/**
+ Sets specified IDT entry with given function pointer.
+
+ This function sets specified IDT entry with given function pointer.
+
+ @param FunctionPointer Function pointer for IDT entry.
+ @param IdtEntry The IDT entry to update.
+
+ @return The original IDT entry value.
+
+**/
+UINTN
+SetIdtEntry (
+ IN UINTN FunctionPointer,
+ OUT INTERRUPT_GATE_DESCRIPTOR *IdtEntry
+ );
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+ @param Size Size of memory to allocate.
+
+ @return Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+ IN UINTN Size
+ );
+
+/**
+ Sends INIT-SIPI-SIPI to specific AP, and make it work on procedure specified by ApFunction.
+
+ This function sends INIT-SIPI-SIPI to specific AP, and make it work on procedure specified by ApFunction.
+
+ @param Broadcast If TRUE, broadcase IPI to all APs; otherwise, send to specified AP.
+ @param ApicID The Local APIC ID of the specified AP.
+ @param ApFunction The procedure for all APs to work on.
+
+**/
+VOID
+SendInitSipiSipiIpis (
+ IN BOOLEAN Broadcast,
+ IN UINT32 ApicID,
+ IN AP_PROCEDURE ApFunction
+ );
+
+/**
+ Dispatches task to AP.
+
+ This function dispatches task to AP. The BSP waits until specified APs have finished.
+
+ @param Broadcast If TRUE, send task to all APs; otherwise, send to specified AP.
+ @param ApicID The Local APIC ID of the specified AP. If Broadcast is TRUE, it is ignored.
+ @param Procedure The procedure for AP to work on.
+
+**/
+VOID
+DispatchAPAndWait (
+ IN BOOLEAN Broadcast,
+ IN UINT32 ApicID,
+ IN AP_PROCEDURE Procedure
+ );
+
+/**
+ Installs MP Services Protocol and register related timer event.
+
+ This function installs MP Services Protocol and register related timer event.
+
+**/
+VOID
+InstallMpServicesProtocol (
+ VOID
+ );
+
+/**
+ Protocol notification that is fired when LegacyBios protocol is installed.
+
+ Re-allocate a wakeup buffer from E/F segment because the previous wakeup buffer
+ under 640K won't be preserved by the legacy OS.
+
+ @param Event The triggered event.
+ @param Context Context for this event.
+**/
+VOID
+EFIAPI
+ReAllocateMemoryForAP (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Fixup jump instructions in the AP startup code.
+
+ @param AddressMap Pointer to MP_ASSEMBLY_ADDRESS_MAP.
+ @param TargetBuffer Target address of the startup vector.
+**/
+VOID
+RedirectFarJump (
+ IN MP_ASSEMBLY_ADDRESS_MAP *AddressMap,
+ IN EFI_PHYSICAL_ADDRESS TargetBuffer
+ );
+
+/**
+ Protocol notification that will wake up and place AP to the suitable state
+ before booting to OS.
+
+ @param Event The triggered event.
+ @param Context Context for this event.
+**/
+VOID
+EFIAPI
+ChangeApLoopModeCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Get mointor data address for specified processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+ @return Pointer to monitor data.
+**/
+MONITOR_MWAIT_DATA *
+EFIAPI
+GetMonitorDataAddress (
+ IN UINTN ProcessorNumber
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.c b/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.c
new file mode 100644
index 0000000..d15a3cc
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.c
@@ -0,0 +1,1478 @@
+/** @file
+
+ Implementation of MP Services Protocol
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MpService.c
+
+**/
+
+#include "MpService.h"
+#include "Cpu.h"
+
+EFI_MP_SERVICES_PROTOCOL mMpService = {
+ GetNumberOfProcessors,
+ GetProcessorInfo,
+ StartupAllAPs,
+ StartupThisAP,
+ SwitchBSP,
+ EnableDisableAP,
+ WhoAmI
+};
+
+BOOLEAN mStopCheckAPsStatus = FALSE;
+BOOLEAN mBspSwitched = FALSE;
+UINTN mNewProcessorNumber = 0;
+MONITOR_MWAIT_DATA *mMonitorDataAddress = NULL;
+
+/**
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param NumberOfProcessors Pointer to the total number of logical processors in the system,
+ including the BSP and disabled APs.
+ @param 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_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ )
+{
+ UINTN Index;
+ CPU_DATA_BLOCK *CpuData;
+ UINT32 ThreadNumber;
+ UINTN CallerNumber;
+
+ //
+ // Check whether caller processor is BSP
+ //
+ WhoAmI (This, &CallerNumber);
+ if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check parameter NumberOfProcessors
+ //
+ if (NumberOfProcessors == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check parameter NumberOfEnabledProcessors
+ //
+ if (NumberOfEnabledProcessors == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *NumberOfProcessors = mCpuConfigConextBuffer.NumberOfProcessors;
+
+ //
+ // Count the number of enabled processors
+ //
+ *NumberOfEnabledProcessors = 0;
+ for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {
+
+ GetProcessorLocation (
+ Index,
+ NULL,
+ NULL,
+ &ThreadNumber
+ );
+
+ CpuData = &mMPSystemData.CpuData[Index];
+ if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_HT_BIT) != 0) {
+ if (CpuData->State != CpuStateDisabled) {
+ (*NumberOfEnabledProcessors)++;
+ }
+ } else {
+ if (CpuData->State != CpuStateDisabled && ThreadNumber == 0) {
+ (*NumberOfEnabledProcessors)++;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param ProcessorNumber The handle number of processor.
+ @param 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_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ UINTN CallerNumber;
+
+ //
+ // Check whether caller processor is BSP
+ //
+ WhoAmI (This, &CallerNumber);
+ if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {
+ 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 >= mCpuConfigConextBuffer.NumberOfProcessors) {
+ return EFI_NOT_FOUND;
+ }
+
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+
+ //
+ // Get Local APIC ID of specified processor
+ //
+ ProcessorInfoBuffer->ProcessorId = GET_CPU_MISC_DATA (ProcessorNumber, ApicID);
+
+ //
+ // Get physical location of specified processor
+ //
+ GetProcessorLocation (
+ ProcessorNumber,
+ &(ProcessorInfoBuffer->Location.Package),
+ &(ProcessorInfoBuffer->Location.Core),
+ &(ProcessorInfoBuffer->Location.Thread)
+ );
+
+ //
+ // Get Status Flag of specified processor
+ //
+ ProcessorInfoBuffer->StatusFlag = 0;
+
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;
+ if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_HT_BIT) == 0) {
+ if (ProcessorInfoBuffer->Location.Thread > 0) {
+ ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;
+ }
+ }
+
+ if (CpuData->State == CpuStateDisabled) {
+ ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;
+ }
+
+ if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;
+ }
+
+ if (mMPSystemData.CpuHealthy[ProcessorNumber]) {
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;
+ }
+
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param Procedure A pointer to the function to be run on enabled APs of the system.
+ @param SingleThread Indicates whether to execute the function simultaneously or one by one..
+ @param 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 TimeoutInMicroSeconds The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param ProcedureArgument Pointer to the optional parameter of the assigned function.
+ @param 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
+StartupAllAPs (
+ IN EFI_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 (This, &ProcessorNumber);
+ if (ProcessorNumber != mCpuConfigConextBuffer.BspNumber) {
+ 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 < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+
+ mMPSystemData.CpuList[ProcessorNumber] = FALSE;
+ if (ProcessorNumber != mCpuConfigConextBuffer.BspNumber) {
+ if (CpuData->State != CpuStateDisabled) {
+ if (CpuData->State != CpuStateIdle) {
+ mStopCheckAPsStatus = FALSE;
+ return EFI_NOT_READY;
+ } else {
+ //
+ // Mark this processor as responsible for current calling.
+ //
+ mMPSystemData.CpuList[ProcessorNumber] = TRUE;
+ }
+ }
+ }
+ }
+
+ 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 < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+ //
+ // Check whether this processor is responsible for current calling.
+ //
+ if (mMPSystemData.CpuList[ProcessorNumber]) {
+
+ mMPSystemData.StartCount++;
+
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateReady;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ if (!Blocking) {
+ WakeUpAp (
+ ProcessorNumber,
+ Procedure,
+ ProcedureArgument
+ );
+ }
+
+ if (SingleThread) {
+ Blocking = TRUE;
+ }
+ }
+ }
+
+ //
+ // If only BSP exists then return EFI_SUCCESS as no APs to start, else return EFI_NOT_STARTED.
+ //
+ if (mMPSystemData.StartCount == 0) {
+ mStopCheckAPsStatus = FALSE;
+ if (mCpuConfigConextBuffer.NumberOfProcessors == 1) {
+ return EFI_SUCCESS;
+ }
+ 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.CurrentTime);
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param Procedure A pointer to the function to be run on the designated AP.
+ @param ProcessorNumber The handle number of AP..
+ @param 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 TimeoutInMicroseconds The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param ProcedureArgument Pointer to the optional parameter of the assigned function.
+ @param 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
+StartupThisAP (
+ IN EFI_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 (This, &CallerNumber);
+ if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check whether processor with the handle specified by ProcessorNumber exists
+ //
+ if (ProcessorNumber >= mCpuConfigConextBuffer.NumberOfProcessors) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check whether specified processor is BSP
+ //
+ if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {
+ 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 == CpuStateDisabled) {
+ mStopCheckAPsStatus = FALSE;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check whether specified AP is busy
+ //
+ if (CpuData->State != CpuStateIdle) {
+ mStopCheckAPsStatus = FALSE;
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Wakeup specified AP for Procedure.
+ //
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateReady;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ WakeUpAp (
+ ProcessorNumber,
+ 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, &CpuData->CurrentTime);
+
+ //
+ // 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param ProcessorNumber The handle number of processor.
+ @param 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
+SwitchBSP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSP
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN OldInterruptState;
+ CPU_DATA_BLOCK *CpuData;
+ CPU_STATE CpuState;
+ UINTN CallerNumber;
+ UINT32 CurrentTimerCount;
+ UINTN DivideValue;
+ UINT8 Vector;
+ BOOLEAN PeriodicMode;
+ UINT64 CurrentTscValue;
+ UINT64 TimerPeriod;
+
+ //
+ // Check whether caller processor is BSP
+ //
+ WhoAmI (This, &CallerNumber);
+ if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check whether processor with the handle specified by ProcessorNumber exists
+ //
+ if (ProcessorNumber >= mCpuConfigConextBuffer.NumberOfProcessors) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check whether specified processor is BSP
+ //
+ if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+
+ //
+ // Check whether specified AP is disabled
+ //
+ if (CpuData->State == CpuStateDisabled) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check whether specified AP is busy
+ //
+ if (CpuData->State != CpuStateIdle) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Save current rate of DXE Timer
+ //
+ mTimer->GetTimerPeriod (mTimer, &TimerPeriod);
+
+ //
+ // Disable DXE Timer and drain pending interrupts
+ //
+ mTimer->SetTimerPeriod (mTimer, 0);
+
+ //
+ // Record the current local APIC timer setting of BSP
+ //
+ GetApicTimerState (&DivideValue, &PeriodicMode, &Vector);
+ CurrentTimerCount = GetApicTimerCurrentCount ();
+ DisableApicTimerInterrupt ();
+
+ //
+ // Record the current TSC value
+ //
+ CurrentTscValue = AsmReadTsc ();
+
+ //
+ // 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.
+ //
+ OldInterruptState = SaveAndDisableInterrupts ();
+ //
+ // Mask LINT0 & LINT1 for the old BSP
+ //
+ DisableLvtInterrupts ();
+ //
+ // Clear the BSP bit of MSR_IA32_APIC_BASE
+ //
+ AsmMsrBitFieldWrite64 (EFI_MSR_IA32_APIC_BASE, N_MSR_BSP_FLAG, N_MSR_BSP_FLAG, 0);
+
+ mMPSystemData.BSPInfo.State = CPU_SWITCH_STATE_IDLE;
+ mMPSystemData.APInfo.State = CPU_SWITCH_STATE_IDLE;
+
+ //
+ // Need to wakeUp AP (future BSP).
+ //
+ WakeUpAp (
+ ProcessorNumber,
+ FutureBSPProc,
+ NULL
+ );
+
+ 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)
+ //
+ AsmMsrBitFieldWrite64 (EFI_MSR_IA32_APIC_BASE, N_MSR_BSP_FLAG, N_MSR_BSP_FLAG, 1);
+ ProgramVirtualWireMode ();
+
+ //
+ // Restore local APIC timer setting to new BSP
+ //
+ InitializeApicTimer (DivideValue, CurrentTimerCount, PeriodicMode, Vector);
+
+ //
+ // Restore interrupt state.
+ //
+ SetInterruptState (OldInterruptState);
+
+ //
+ // Enable and restore rate of DXE Timer
+ //
+ mTimer->SetTimerPeriod (mTimer, TimerPeriod);
+
+ CpuData = &mMPSystemData.CpuData[mCpuConfigConextBuffer.BspNumber];
+ while (TRUE) {
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuState = CpuData->State;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ if (CpuState == CpuStateFinished) {
+ break;
+ }
+ }
+
+ Status = ChangeCpuState (mCpuConfigConextBuffer.BspNumber, EnableOldBSP, EFI_CPU_CAUSE_USER_SELECTION);
+ mCpuConfigConextBuffer.BspNumber = ProcessorNumber;
+
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param ProcessorNumber The handle number of processor.
+ @param NewAPState Indicates whether the newstate of the AP is enabled or disabled.
+ @param 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
+EnableDisableAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN NewAPState,
+ IN UINT32 *HealthFlag OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN CallerNumber;
+
+ //
+ // Check whether caller processor is BSP
+ //
+ WhoAmI (This, &CallerNumber);
+ if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check whether processor with the handle specified by ProcessorNumber exists
+ //
+ if (ProcessorNumber >= mCpuConfigConextBuffer.NumberOfProcessors) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check whether specified processor is BSP
+ //
+ if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = ChangeCpuState (ProcessorNumber, NewAPState, EFI_CPU_CAUSE_USER_SELECTION);
+
+ if (HealthFlag != NULL) {
+ mMPSystemData.CpuHealthy[ProcessorNumber] = (BOOLEAN) ((*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT) != 0);
+ }
+
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param 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
+ )
+{
+ UINTN Index;
+ UINT32 ApicID;
+
+ //
+ // Check parameter ProcessorNumber
+ //
+ if (ProcessorNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ApicID = GetApicId ();
+
+ for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {
+ if (ApicID == GET_CPU_MISC_DATA (Index, ApicID)) {
+ break;
+ }
+ }
+
+ *ProcessorNumber = Index;
+ return EFI_SUCCESS;
+}
+
+/**
+ 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 Event Event triggered.
+ @param 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 < mCpuConfigConextBuffer.NumberOfProcessors; 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 ;
+}
+
+/**
+ 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 < mCpuConfigConextBuffer.NumberOfProcessors; 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.
+ //
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuState = CpuData->State;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ if (CpuState == CpuStateFinished) {
+ mMPSystemData.FinishCount++;
+ mMPSystemData.CpuList[ProcessorNumber] = FALSE;
+
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateIdle;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ //
+ // 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 (
+ 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.CurrentTime, &mMPSystemData.TotalTime, mMPSystemData.ExpectedTime)) {
+ //
+ // If FailedCpuList is not NULL, record all failed APs in it.
+ //
+ if (mMPSystemData.FailedCpuList != NULL) {
+ *mMPSystemData.FailedCpuList = AllocatePool ((mMPSystemData.StartCount - mMPSystemData.FinishCount + 1) * sizeof(UINTN));
+ ASSERT (*mMPSystemData.FailedCpuList != NULL);
+ }
+ ListIndex = 0;
+
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; 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 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.
+ //
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuState = CpuData->State;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ //
+ // If the APs finishes for StartupThisAP(), return EFI_SUCCESS.
+ //
+ if (CpuState == CpuStateFinished) {
+
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateIdle;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ if (CpuData->Finished != NULL) {
+ *(CpuData->Finished) = TRUE;
+ }
+ return EFI_SUCCESS;
+ } else {
+ //
+ // If timeout expires for StartupThisAP(), report timeout.
+ //
+ if (CheckTimeout (&CpuData->CurrentTime, &CpuData->TotalTime, CpuData->ExpectedTime)) {
+
+ if (CpuData->Finished != NULL) {
+ *(CpuData->Finished) = FALSE;
+ }
+ //
+ // Reset failed AP to idle state
+ //
+ ResetProcessorToIdleState (ProcessorNumber);
+
+ return EFI_TIMEOUT;
+ }
+ }
+ return EFI_NOT_READY;
+}
+
+/**
+ Calculate timeout value and return the current performance counter value.
+
+ Calculate the number of performance counter ticks required for a timeout.
+ If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
+ as infinity.
+
+ @param TimeoutInMicroseconds Timeout value in microseconds.
+ @param CurrentTime Returns the current value of the performance counter.
+
+ @return Expected timestamp counter for timeout.
+ If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
+ as infinity.
+
+**/
+UINT64
+CalculateTimeout (
+ IN UINTN TimeoutInMicroseconds,
+ OUT UINT64 *CurrentTime
+ )
+{
+ //
+ // Read the current value of the performance counter
+ //
+ *CurrentTime = GetPerformanceCounter ();
+
+ //
+ // If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
+ // as infinity.
+ //
+ if (TimeoutInMicroseconds == 0) {
+ return 0;
+ }
+
+ //
+ // GetPerformanceCounterProperties () returns the timestamp counter's frequency
+ // in Hz. So multiply the return value with TimeoutInMicroseconds and then divide
+ // it by 1,000,000, to get the number of ticks for the timeout value.
+ //
+ return DivU64x32 (
+ MultU64x64 (
+ GetPerformanceCounterProperties (NULL, NULL),
+ TimeoutInMicroseconds
+ ),
+ 1000000
+ );
+}
+
+/**
+ Checks whether timeout expires.
+
+ Check whether the number of ellapsed performance counter ticks required for a timeout condition
+ has been reached. If Timeout is zero, which means infinity, return value is always FALSE.
+
+ @param PreviousTime On input, the value of the performance counter when it was last read.
+ On output, the current value of the performance counter
+ @param TotalTime The total amount of ellapsed time in performance counter ticks.
+ @param Timeout The number of performance counter ticks required to reach a timeout condition.
+
+ @retval TRUE A timeout condition has been reached.
+ @retval FALSE A timeout condition has not been reached.
+
+**/
+BOOLEAN
+CheckTimeout (
+ IN OUT UINT64 *PreviousTime,
+ IN UINT64 *TotalTime,
+ IN UINT64 Timeout
+ )
+{
+ UINT64 Start;
+ UINT64 End;
+ UINT64 CurrentTime;
+ INT64 Delta;
+ INT64 Cycle;
+
+ if (Timeout == 0) {
+ return FALSE;
+ }
+ GetPerformanceCounterProperties (&Start, &End);
+ Cycle = End - Start;
+ if (Cycle < 0) {
+ Cycle = -Cycle;
+ }
+ Cycle++;
+ CurrentTime = GetPerformanceCounter();
+ Delta = (INT64) (CurrentTime - *PreviousTime);
+ if (Start > End) {
+ Delta = -Delta;
+ }
+ if (Delta < 0) {
+ Delta += Cycle;
+ }
+ *TotalTime += Delta;
+ *PreviousTime = CurrentTime;
+ if (*TotalTime > Timeout) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Searches for the next waiting AP.
+
+ Search for the next AP that is put in waiting state by single-threaded StartupAllAPs().
+
+ @param 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 < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+
+ if (mMPSystemData.CpuList[ProcessorNumber]) {
+ *NextProcessorNumber = ProcessorNumber;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Worker function for SwitchBSP().
+
+ Worker function for SwitchBSP(), assigned to the AP which is intended to become BSP.
+
+ @param Buffer Not used.
+
+**/
+VOID
+EFIAPI
+FutureBSPProc (
+ IN VOID *Buffer
+ )
+{
+ AsmExchangeRole (&mMPSystemData.APInfo, &mMPSystemData.BSPInfo);
+ return ;
+}
+
+/**
+ Worker function of EnableDisableAP ()
+
+ Worker function of EnableDisableAP (). Changes state of specified processor.
+
+ @param ProcessorNumber Processor number of specified AP.
+ @param NewState Desired state of the specified AP.
+ @param Cause The cause to change AP's state.
+
+ @retval EFI_SUCCESS AP's state successfully changed.
+
+**/
+EFI_STATUS
+ChangeCpuState (
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN NewState,
+ IN EFI_CPU_STATE_CHANGE_CAUSE Cause
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA ErrorData;
+
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+
+ mMPSystemData.DisableCause[ProcessorNumber] = Cause;
+
+ if (!NewState) {
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateDisabled;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ ErrorData.Cause = Cause;
+ ErrorData.SoftwareDisabled = TRUE;
+
+ REPORT_STATUS_CODE_EX (
+ EFI_ERROR_MINOR | EFI_ERROR_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_EC_DISABLED,
+ (UINT32) ProcessorNumber,
+ NULL,
+ NULL,
+ (UINT8 *) &ErrorData + sizeof (EFI_STATUS_CODE_DATA),
+ sizeof (EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA) - sizeof (EFI_STATUS_CODE_DATA)
+ );
+ } else {
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateIdle;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+ }
+
+ return EFI_SUCCESS;
+}
+
+ /**
+ C function for AP execution.
+
+ The AP startup code jumps to this C function after switching to flat32 model.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+EFIAPI
+ApProcEntry (
+ IN UINTN ProcessorNumber
+ )
+{
+ if (mApFunction != NULL) {
+ (*mApFunction) (ProcessorNumber);
+ }
+}
+
+/**
+ Wrapper function for all procedures assigned to AP.
+
+ Wrapper function for all procedures assigned to AP via MP service protocol.
+ It controls states of AP and invokes assigned precedure.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+ApProcWrapper (
+ IN UINTN ProcessorNumber
+ )
+{
+ EFI_AP_PROCEDURE Procedure;
+ VOID *Parameter;
+ CPU_DATA_BLOCK *CpuData;
+ MONITOR_MWAIT_DATA *MonitorAddr;
+
+ //
+ // Program virtual wire mode and Local APIC timer for AP, since it will be lost after AP wake up
+ //
+ ProgramVirtualWireMode ();
+ DisableLvtInterrupts ();
+ InitializeApicTimer (mLocalApicTimerDivisor, mLocalApicTimerInitialCount, FALSE, 0);
+
+ //
+ // Initialize Debug Agent to support source level debug on AP code.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL);
+
+ //
+ // Call SetProcessorRegister() to restore register setting,
+ // for some registers are cleared by INIT signal.
+ //
+ SetProcessorRegister (ProcessorNumber);
+
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateBusy;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ //
+ // Now let us check it out.
+ //
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ Procedure = CpuData->Procedure;
+ Parameter = CpuData->Parameter;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ if (Procedure != NULL) {
+
+ Procedure (Parameter);
+
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->Procedure = NULL;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+ }
+
+ //
+ // Update signal once finishing AP task
+ //
+ MonitorAddr = GetMonitorDataAddress (ProcessorNumber);
+ MonitorAddr->StartupApSignal = 0;
+
+ //
+ // 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
+ //
+ if (Procedure == FutureBSPProc) {
+ mBspSwitched = TRUE;
+ WhoAmI (&mMpService, &mNewProcessorNumber);
+ CpuData = &mMPSystemData.CpuData[mNewProcessorNumber];
+ mMonitorDataAddress = GetMonitorDataAddress (mNewProcessorNumber);
+ //
+ // Copy the monitor data structure of the old AP into the AP stack of the new AP.
+ //
+ CopyMem (mMonitorDataAddress, MonitorAddr, sizeof (MONITOR_MWAIT_DATA));
+ }
+
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateFinished;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+}
+
+/**
+ Function to wake up a specified AP and assign procedure to it.
+
+ Function to wake up a specified AP and assign procedure to it.
+
+ @param ProcessorNumber Handle number of the specified processor.
+ @param Procedure Procedure to assign.
+ @param ProcArguments Argument for Procedure.
+
+**/
+VOID
+WakeUpAp (
+ IN UINTN ProcessorNumber,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *ProcArguments
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ MONITOR_MWAIT_DATA *MonitorAddr;
+
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->Parameter = ProcArguments;
+ CpuData->Procedure = Procedure;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+
+ //
+ // Check AP wakeup manner, update signal to wake up AP
+ //
+ MonitorAddr = GetMonitorDataAddress (ProcessorNumber);
+
+ //
+ // Check AP Loop mode
+ //
+ if (MonitorAddr->ApLoopMode == ApInHltLoop) {
+ //
+ // Save new the AP Loop mode
+ //
+ MonitorAddr->ApLoopMode = mExchangeInfo->ApLoopMode;
+ SendInitSipiSipiIpis (
+ FALSE,
+ GET_CPU_MISC_DATA (ProcessorNumber, ApicID),
+ ApProcWrapper
+ );
+
+ } else if (MonitorAddr->ApLoopMode == ApInMwaitLoop ||
+ MonitorAddr->ApLoopMode == ApInRunLoop) {
+ //
+ // Save new the AP Loop mode
+ //
+ MonitorAddr->ApLoopMode = mExchangeInfo->ApLoopMode;
+ mApFunction = ApProcWrapper;
+ //
+ // AP is in Mwait C1 state
+ //
+ MonitorAddr->MwaitTargetCstate = 0;
+ MonitorAddr->StartupApSignal = STARTUP_AP_SIGNAL | (UINT16) ProcessorNumber;
+
+ } else {
+
+ ASSERT (FALSE);
+ }
+
+}
+
+/**
+ Reset an AP to Idle state.
+
+ Any task being executed by the AP will be aborted and the AP
+ will be waiting for a new task in Wait-For-SIPI state.
+
+ @param ProcessorNumber The handle number of processor.
+**/
+VOID
+ResetProcessorToIdleState (
+ UINTN ProcessorNumber
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+
+ SendInitSipiSipiIpis (
+ FALSE,
+ GET_CPU_MISC_DATA (ProcessorNumber, ApicID),
+ NULL
+ );
+
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+
+ AcquireSpinLock (&CpuData->CpuDataLock);
+ CpuData->State = CpuStateIdle;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+}
+
+/**
+ 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 ProcessorNumber;
+
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+ CpuData = &mMPSystemData.CpuData[ProcessorNumber];
+ if (ProcessorNumber != mCpuConfigConextBuffer.BspNumber) {
+ if (CpuData->State != CpuStateIdle && CpuData->State != CpuStateDisabled) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.h b/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.h
new file mode 100644
index 0000000..6799dff
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.h
@@ -0,0 +1,554 @@
+/** @file
+
+ Include file for MP Services Protocol
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: MpService.h
+
+**/
+
+#ifndef _MP_SERVICE_H_
+#define _MP_SERVICE_H_
+
+#include "MpCommon.h"
+
+#define CPU_CHECK_AP_INTERVAL 0x10 // microseconds
+//
+// The MP data structure follows.
+//
+#define CPU_SWITCH_STATE_IDLE 0
+#define CPU_SWITCH_STATE_STORED 1
+#define CPU_SWITCH_STATE_LOADED 2
+
+extern EFI_MP_SERVICES_PROTOCOL mMpService;
+extern EFI_TIMER_ARCH_PROTOCOL *mTimer;
+
+typedef struct {
+ UINT8 State; // offset 0
+ UINTN StackPointer; // offset 4 / 8
+ IA32_DESCRIPTOR Gdtr; // offset 8 / 16
+ IA32_DESCRIPTOR Idtr; // offset 14 / 26
+} CPU_EXCHANGE_ROLE_INFO;
+
+typedef enum {
+ CpuStateIdle,
+ CpuStateReady,
+ CpuStateBusy,
+ CpuStateFinished,
+ CpuStateDisabled
+} CPU_STATE;
+
+//
+// Define Individual Processor Data block.
+//
+typedef struct {
+ EFI_AP_PROCEDURE volatile Procedure;
+ VOID* volatile Parameter;
+
+ EFI_EVENT WaitEvent;
+ BOOLEAN *Finished;
+ UINT64 ExpectedTime;
+ UINT64 CurrentTime;
+ UINT64 TotalTime;
+
+ SPIN_LOCK CpuDataLock;
+ CPU_STATE volatile State;
+
+} CPU_DATA_BLOCK;
+
+//
+// Define MP data block which consumes individual processor block.
+//
+typedef struct {
+ SPIN_LOCK APSerializeLock;
+
+ CPU_EXCHANGE_ROLE_INFO BSPInfo;
+ CPU_EXCHANGE_ROLE_INFO APInfo;
+
+ EFI_EVENT CheckAPsEvent;
+
+ UINTN FinishCount;
+ UINTN StartCount;
+
+ BOOLEAN CpuList[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];
+
+ EFI_AP_PROCEDURE Procedure;
+ VOID *ProcArguments;
+ BOOLEAN SingleThread;
+ EFI_EVENT WaitEvent;
+ UINTN **FailedCpuList;
+ UINT64 ExpectedTime;
+ UINT64 CurrentTime;
+ UINT64 TotalTime;
+
+ CPU_DATA_BLOCK CpuData[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];
+ EFI_CPU_STATE_CHANGE_CAUSE DisableCause[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];
+ BOOLEAN CpuHealthy[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];
+
+} MP_SYSTEM_DATA;
+
+typedef struct {
+ ACPI_CPU_DATA AcpiCpuData;
+ IA32_DESCRIPTOR GdtrProfile;
+ IA32_DESCRIPTOR IdtrProfile;
+} MP_CPU_SAVED_DATA;
+
+extern MP_SYSTEM_DATA mMPSystemData;
+
+/**
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param NumberOfCPUs Pointer to the total number of logical processors in the system,
+ including the BSP and disabled APs.
+ @param NumberOfEnabledCPUs 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_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfCPUs,
+ OUT UINTN *NumberOfEnabledCPUs
+ );
+
+/**
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param ProcessorNumber The handle number of processor.
+ @param 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_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ );
+
+/**
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param Procedure A pointer to the function to be run on enabled APs of the system.
+ @param SingleThread Indicates whether to execute the function simultaneously or one by one..
+ @param 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 TimeoutInMicroSeconds The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param ProcedureArgument Pointer to the optional parameter of the assigned function.
+ @param 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
+StartupAllAPs (
+ IN EFI_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 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param Procedure A pointer to the function to be run on the designated AP.
+ @param ProcessorNumber The handle number of AP..
+ @param 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 TimeoutInMicroseconds The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param ProcedureArgument Pointer to the optional parameter of the assigned function.
+ @param 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
+StartupThisAP (
+ IN EFI_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 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param ProcessorNumber The handle number of processor.
+ @param OldBSPState 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
+SwitchBSP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN OldBSPState
+ );
+
+/**
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param ProcessorNumber The handle number of processor.
+ @param NewAPState Indicates whether the newstate of the AP is enabled or disabled.
+ @param 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
+EnableDisableAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN NewAPState,
+ 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 This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param 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
+ );
+
+/**
+ This function is called by both the BSP and the AP which is to become the BSP to
+ Exchange execution context including stack between them. After return from this
+ function, the BSP becomes AP and the AP becomes the BSP.
+
+ @param MyInfo Pointer to buffer holding the exchanging information for the executing processor.
+ @param OthersInfo Pointer to buffer holding the exchanging information for the peer.
+**/
+VOID
+EFIAPI
+AsmExchangeRole (
+ IN CPU_EXCHANGE_ROLE_INFO *MyInfo,
+ IN CPU_EXCHANGE_ROLE_INFO *OthersInfo
+ );
+
+/**
+ Worker function for SwitchBSP().
+
+ Worker function for SwitchBSP(), assigned to the AP which is intended to become BSP.
+
+ @param Buffer Not used.
+
+**/
+VOID
+EFIAPI
+FutureBSPProc (
+ IN VOID *Buffer
+ );
+
+/**
+ Worker function of EnableDisableAP ()
+
+ Worker function of EnableDisableAP (). Changes state of specified processor.
+
+ @param CpuNumber Processor number of specified AP.
+ @param NewState Desired state of the specified AP.
+ @param Cause The cause to change AP's state.
+
+ @retval EFI_SUCCESS AP's state successfully changed.
+
+**/
+EFI_STATUS
+ChangeCpuState (
+ IN UINTN CpuNumber,
+ IN BOOLEAN NewState,
+ IN EFI_CPU_STATE_CHANGE_CAUSE Cause
+ );
+
+/**
+ 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 Event Event triggered.
+ @param Context Parameter passed with the event.
+
+**/
+VOID
+EFIAPI
+CheckAPsStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ 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
+ );
+
+/**
+ Checks status of specified AP.
+
+ This function checks whether specified AP has finished task assigned by StartupThisAP(),
+ and whether timeout expires.
+
+ @param 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
+ );
+
+/**
+ Calculate timeout value and return the current performance counter value.
+
+ Calculate the number of performance counter ticks required for a timeout.
+ If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
+ as infinity.
+
+ @param TimeoutInMicroseconds Timeout value in microseconds.
+ @param CurrentTime Returns the current value of the performance counter.
+
+ @return Expected timestamp counter for timeout.
+ If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
+ as infinity.
+
+**/
+UINT64
+CalculateTimeout (
+ IN UINTN TimeoutInMicroseconds,
+ OUT UINT64 *CurrentTime
+ );
+
+/**
+ Checks whether timeout expires.
+
+ Check whether the number of ellapsed performance counter ticks required for a timeout condition
+ has been reached. If Timeout is zero, which means infinity, return value is always FALSE.
+
+ @param PreviousTime On input, the value of the performance counter when it was last read.
+ On output, the current value of the performance counter
+ @param TotalTime The total amount of ellapsed time in performance counter ticks.
+ @param Timeout The number of performance counter ticks required to reach a timeout condition.
+
+ @retval TRUE A timeout condition has been reached.
+ @retval FALSE A timeout condition has not been reached.
+
+**/
+BOOLEAN
+CheckTimeout (
+ IN OUT UINT64 *PreviousTime,
+ IN UINT64 *TotalTime,
+ IN UINT64 Timeout
+ );
+
+/**
+ Searches for the next waiting AP.
+
+ Search for the next AP that is put in waiting state by single-threaded StartupAllAPs().
+
+ @param 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
+ );
+
+ /**
+ C function for AP execution.
+
+ The AP startup code jumps to this C function after switching to flat32 model.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+EFIAPI
+ApProcEntry (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Wrapper function for all procedures assigned to AP.
+
+ Wrapper function for all procedures assigned to AP via MP service protocol.
+ It controls states of AP and invokes assigned precedure.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+ApProcWrapper (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Function to wake up a specified AP and assign procedure to it.
+
+ Function to wake up a specified AP and assign procedure to it.
+
+ @param ProcessorNumber Handle number of the specified processor.
+ @param Procedure Procedure to assign.
+ @param Parameter Argument for Procedure.
+
+**/
+VOID
+WakeUpAp (
+ IN UINTN ProcessorNumber,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *Parameter
+ );
+
+/**
+ Reset an AP to Idle state.
+
+ Any task being executed by the AP will be aborted and the AP
+ will be waiting for a new task in Wait-For-SIPI state.
+
+ @param ProcessorNumber The handle number of processor.
+**/
+VOID
+ResetProcessorToIdleState (
+ UINTN ProcessorNumber
+ );
+
+/**
+ Check whether any AP is running for assigned task.
+
+ @retval TRUE Some APs are running.
+ @retval FALSE No AP is running.
+**/
+BOOLEAN
+ApRunning (
+ VOID
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/ProcessorConfig.c b/IA32FamilyCpuBasePkg/CpuMpDxe/ProcessorConfig.c
new file mode 100644
index 0000000..e84315a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/ProcessorConfig.c
@@ -0,0 +1,571 @@
+/** @file
+ Code for processor configuration.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: ProcessorConfig.c
+
+**/
+
+#include "MpService.h"
+#include "Cpu.h"
+#include "MpApic.h"
+
+MP_SYSTEM_DATA mMPSystemData;
+CPU_CONFIG_CONTEXT_BUFFER mCpuConfigConextBuffer;
+EFI_PHYSICAL_ADDRESS mStartupVector;
+UINT8 mPlatformType;
+ACPI_CPU_DATA *mAcpiCpuData;
+EFI_HANDLE mHandle = NULL;
+MTRR_SETTINGS *mMtrrSettings;
+EFI_EVENT mSmmConfigurationNotificationEvent;
+EFI_HANDLE mImageHandle;
+EFI_TIMER_ARCH_PROTOCOL *mTimer;
+UINTN mLocalApicTimerDivisor;
+UINT32 mLocalApicTimerInitialCount;
+
+/**
+ Prepares memory region for processor configuration.
+
+ This function prepares memory region for processor configuration.
+
+**/
+VOID
+PrepareMemoryForConfiguration (
+ VOID
+ )
+{
+ UINTN NumberOfProcessors;
+ UINTN Index;
+ MONITOR_MWAIT_DATA *MonitorData;
+
+ //
+ // Initialize Spin Locks for system
+ //
+ InitializeSpinLock (&mMPSystemData.APSerializeLock);
+ for (Index = 0; Index < PcdGet32(PcdCpuMaxLogicalProcessorNumber); Index++) {
+ InitializeSpinLock (&mMPSystemData.CpuData[Index].CpuDataLock);
+ }
+
+ //
+ // Claim memory for AP stack.
+ //
+ mExchangeInfo->StackStart = AllocateAcpiNvsMemoryBelow4G (PcdGet32(PcdCpuMaxLogicalProcessorNumber) * PcdGet32 (PcdCpuApStackSize));
+ mExchangeInfo->StackSize = PcdGet32 (PcdCpuApStackSize);
+
+ //
+ // Initialize the Monitor Data structure in APs' stack
+ //
+ for (Index = 0; Index < PcdGet32(PcdCpuMaxLogicalProcessorNumber); Index++) {
+ MonitorData = GetMonitorDataAddress (Index);
+ MonitorData->ApLoopMode = ApInHltLoop;
+ }
+
+ //
+ // Initialize data for CPU configuration context buffer
+ //
+ NumberOfProcessors = mCpuConfigConextBuffer.NumberOfProcessors;
+ mCpuConfigConextBuffer.CollectedDataBuffer = AllocateZeroPool (sizeof (CPU_COLLECTED_DATA) * NumberOfProcessors);
+ mCpuConfigConextBuffer.FeatureLinkListEntry = AllocateZeroPool (sizeof (LIST_ENTRY) * NumberOfProcessors);
+
+ //
+ // Initialize Processor Feature List for all logical processors.
+ //
+ for (Index = 0; Index < NumberOfProcessors; Index++) {
+ InitializeListHead (&mCpuConfigConextBuffer.FeatureLinkListEntry[Index]);
+ }
+
+ mCpuConfigConextBuffer.RegisterTable = AllocateAcpiNvsMemoryBelow4G (
+ (sizeof (CPU_REGISTER_TABLE) + sizeof (UINTN)) * NumberOfProcessors
+ );
+ mCpuConfigConextBuffer.PreSmmInitRegisterTable = AllocateAcpiNvsMemoryBelow4G (
+ (sizeof (CPU_REGISTER_TABLE) + sizeof (UINTN)) * NumberOfProcessors
+ );
+
+ mCpuConfigConextBuffer.SettingSequence = (UINTN *) (((UINTN) mCpuConfigConextBuffer.RegisterTable) + (sizeof (CPU_REGISTER_TABLE) * NumberOfProcessors));
+ for (Index = 0; Index < NumberOfProcessors; Index++) {
+ mCpuConfigConextBuffer.SettingSequence[Index] = Index;
+ }
+
+ //
+ // Set the value for PcdCpuConfigContextBuffer.
+ //
+ mCpuConfigLibConfigConextBuffer = &mCpuConfigConextBuffer;
+ PcdSet64 (PcdCpuConfigContextBuffer, (UINT64) (UINTN) mCpuConfigLibConfigConextBuffer);
+
+ //
+ // Read the platform type from PCD
+ //
+ mPlatformType = PcdGet8 (PcdPlatformType);
+}
+
+/**
+ Event notification that is fired every time a gEfiSmmConfigurationProtocol installs.
+
+ This function configures all logical processors with three-phase architecture.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+SmmConfigurationEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *Registration;
+ EFI_SMM_CONFIGURATION_PROTOCOL *SmmConfiguration;
+
+ //
+ // Make sure this notification is for this handler
+ //
+ Status = gBS->LocateProtocol (&gEfiSmmConfigurationProtocolGuid, NULL, (VOID **)&SmmConfiguration);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Wakeup APs. Collect data of all processors. BSP polls to
+ // wait for APs' completion.
+ //
+ DataCollectionPhase ();
+ //
+ // With collected data, BSP analyzes processors'configuration
+ // according to user's policy.
+ //
+ AnalysisPhase ();
+
+ //
+ // Wakeup APs. Program registers of all processors, according to
+ // the result of Analysis phase. BSP polls to wait for AP's completion.
+ //
+ SettingPhase ();
+
+ //
+ // Select least-feature procesosr as BSP
+ //
+ if (FeaturePcdGet (PcdCpuSelectLfpAsBspFlag)) {
+ SelectLfpAsBsp ();
+ }
+
+ //
+ // Add SMBIOS Processor Type and Cache Type tables for the CPU.
+ //
+ AddCpuSmbiosTables ();
+
+ //
+ // Save CPU S3 data
+ //
+ SaveCpuS3Data (mImageHandle);
+
+ Status = gBS->SetTimer (
+ mMPSystemData.CheckAPsEvent,
+ TimerPeriodic,
+ 10000 * MICROSECOND
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Setup notification on Legacy BIOS Protocol to reallocate AP wakeup
+ //
+ EfiCreateProtocolNotifyEvent (
+ &gEfiLegacyBiosProtocolGuid,
+ TPL_CALLBACK,
+ ReAllocateMemoryForAP,
+ NULL,
+ &Registration
+ );
+}
+
+/**
+ Early MP Initialization.
+
+ This function does early MP initialization, including MTRR sync and first time microcode load.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+EarlyMpInit (
+ IN UINTN ProcessorNumber
+ )
+{
+ MtrrSetAllMtrrs (mMtrrSettings);
+
+ CollectBasicProcessorData (ProcessorNumber);
+
+}
+
+/**
+ First phase MP initialization before SMM initialization.
+
+ @retval EFI_SUCCESS First phase MP initialization was done successfully.
+ @retval EFI_UNSUPPORTED There is legacy APIC ID conflict and can't be rsolved in xAPIC mode.
+
+**/
+EFI_STATUS
+ProcessorConfiguration (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Wakeup APs for the first time, BSP stalls for arbitrary
+ // time for APs' completion. BSP then collects the number
+ // and BIST information of APs.
+ //
+ WakeupAPAndCollectBist ();
+ //
+ // Sort APIC ID of all processors in asending order. Processor number
+ // is assigned in this order to ease MP debug. SMBIOS logic also depends on it.
+ //
+ SortApicId ();
+
+ //
+ // Prepare data in memory for processor configuration
+ //
+ PrepareMemoryForConfiguration ();
+
+ //
+ // Early MP initialization
+ //
+ mMtrrSettings = (MTRR_SETTINGS *)(UINTN)PcdGet64 (PcdCpuMtrrTableAddress);
+ MtrrGetAllMtrrs (mMtrrSettings);
+
+ DispatchAPAndWait (
+ TRUE,
+ 0,
+ EarlyMpInit
+ );
+
+ EarlyMpInit (mCpuConfigConextBuffer.BspNumber);
+
+ DEBUG_CODE (
+ //
+ // Verify that all processors have same APIC ID topology. New APIC IDs
+ // were constructed based on this assumption.
+ //
+ UINTN Index;
+ UINT8 PackageIdBitOffset;
+
+ PackageIdBitOffset = mCpuConfigConextBuffer.CollectedDataBuffer[0].PackageIdBitOffset;
+ for (Index = 1; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {
+ if (PackageIdBitOffset != mCpuConfigConextBuffer.CollectedDataBuffer[Index].PackageIdBitOffset) {
+ ASSERT (FALSE);
+ }
+ }
+ );
+
+ //
+ // Check if there is legacy APIC ID conflict among all processors.
+ //
+ Status = CheckApicId ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Assign Package BSP for package scope programming later.
+ //
+ AssignPackageBsp ();
+
+ //
+ // Produce pre-SMM-init register table.
+ //
+ ProducePreSmmInitRegisterTable ();
+
+ //
+ // Early MP initialization step 2
+ //
+ DispatchAPAndWait (
+ TRUE,
+ 0,
+ SetPreSmmInitProcessorRegister
+ );
+
+ SetPreSmmInitProcessorRegister (mCpuConfigConextBuffer.BspNumber);
+
+ //
+ // Locate Timer Arch Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &mTimer);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install MP Services Protocol
+ //
+ InstallMpServicesProtocol ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Installs MP Services Protocol and register related timer event.
+
+ This function installs MP Services Protocol and register related timer event.
+
+**/
+VOID
+InstallMpServicesProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Create timer event to check AP state for non-blocking execution.
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ CheckAPsStatus,
+ NULL,
+ &mMPSystemData.CheckAPsEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Now install the MP services protocol.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mHandle,
+ &gEfiMpServiceProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mMpService
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Callback function for idle events.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context The pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+IdleLoopEventCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ CpuSleep ();
+}
+
+/**
+ Entrypoint of CPU MP DXE module.
+
+ This function is the entrypoint of CPU MP DXE module.
+ It initializes Multi-processor configuration and installs MP Services Protocol.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entrypoint always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+MultiProcessorInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *Registration;
+ EFI_EVENT IdleLoopEvent;
+ EFI_EVENT ExitBootServiceEvent;
+ EFI_EVENT LegacyToBootEvent;
+
+ mImageHandle = ImageHandle;
+ //
+ // Configure processors with three-phase architecture
+ //
+ Status = ProcessorConfiguration ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install notification callback on SMM Configuration Protocol
+ //
+ mSmmConfigurationNotificationEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiSmmConfigurationProtocolGuid,
+ TPL_CALLBACK,
+ SmmConfigurationEventNotify,
+ NULL,
+ &Registration
+ );
+
+ //
+ // Create EXIT_BOOT_SERIVES Event to set AP to suitable status
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ChangeApLoopModeCallBack,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &ExitBootServiceEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create an event to be signalled when Legacy Boot occurs to set AP to suitable status
+ //
+ Status = EfiCreateEventLegacyBootEx(
+ TPL_NOTIFY,
+ ChangeApLoopModeCallBack,
+ NULL,
+ &LegacyToBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Setup a callback for idle events
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ IdleLoopEventCallback,
+ NULL,
+ &gIdleLoopEventGuid,
+ &IdleLoopEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wakes up APs for the first time to count their number and collect BIST data.
+
+ This function wakes up APs for the first time to count their number and collect BIST data.
+
+**/
+VOID
+WakeupAPAndCollectBist (
+ VOID
+ )
+{
+ //
+ // Save BSP's Local APIC Timer setting
+ //
+ GetApicTimerState (&mLocalApicTimerDivisor, NULL, NULL);
+ mLocalApicTimerInitialCount = GetApicTimerInitCount ();
+
+ //
+ // Prepare code and data for APs' startup vector
+ //
+ PrepareAPStartupVector ();
+
+ mCpuConfigConextBuffer.NumberOfProcessors = 1;
+ mCpuConfigConextBuffer.BspNumber = 0;
+ //
+ // Item 0 of BistBuffer is for BSP.
+ //
+ mExchangeInfo->BistBuffer[0].ApicId = GetInitialApicId ();
+
+ SendInitSipiSipiIpis (
+ TRUE,
+ 0,
+ NULL
+ );
+
+ //
+ // Wait for task to complete and then exit.
+ //
+ MicroSecondDelay (PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
+ mExchangeInfo->InitFlag = 0;
+}
+
+
+/**
+ Prepare ACPI NVS memory below 4G memory for use of S3 resume.
+
+ This function allocates ACPI NVS memory below 4G memory for use of S3 resume,
+ and saves data into the memory region.
+
+ @param Context The Context save the info.
+
+**/
+VOID
+SaveCpuS3Data (
+ VOID *Context
+ )
+{
+ MP_CPU_SAVED_DATA *MpCpuSavedData;
+
+ //
+ // Allocate ACPI NVS memory below 4G memory for use of S3 resume.
+ //
+ MpCpuSavedData = AllocateAcpiNvsMemoryBelow4G (sizeof (MP_CPU_SAVED_DATA));
+
+ //
+ // Set the value for CPU data
+ //
+ mAcpiCpuData = &(MpCpuSavedData->AcpiCpuData);
+ mAcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS) (UINTN) &(MpCpuSavedData->GdtrProfile);
+ mAcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS) (UINTN) &(MpCpuSavedData->IdtrProfile);
+ mAcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) mExchangeInfo->StackStart;
+ mAcpiCpuData->StackSize = PcdGet32 (PcdCpuApStackSize);
+ mAcpiCpuData->MtrrTable = (EFI_PHYSICAL_ADDRESS) (UINTN) PcdGet64 (PcdCpuMtrrTableAddress);
+ mAcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS) (UINTN) mCpuConfigConextBuffer.RegisterTable;
+
+ mAcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS) (UINTN) mCpuConfigConextBuffer.PreSmmInitRegisterTable;
+ mAcpiCpuData->ApMachineCheckHandlerBase = mApMachineCheckHandlerBase;
+ mAcpiCpuData->ApMachineCheckHandlerSize = mApMachineCheckHandlerSize;
+
+ //
+ // Check user's policy for HT enable.
+ //
+ mAcpiCpuData->APState = FALSE;
+ if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_HT_BIT) != 0) {
+ mAcpiCpuData->APState = TRUE;
+ }
+
+ //
+ // Copy GDTR and IDTR profiles
+ //
+ CopyMem ((VOID *) (UINTN) mAcpiCpuData->GdtrProfile, (VOID *) (UINTN) &mExchangeInfo->GdtrProfile, sizeof (IA32_DESCRIPTOR));
+ CopyMem ((VOID *) (UINTN) mAcpiCpuData->IdtrProfile, (VOID *) (UINTN) &mExchangeInfo->IdtrProfile, sizeof (IA32_DESCRIPTOR));
+
+ mAcpiCpuData->NumberOfCpus = (UINT32) mCpuConfigConextBuffer.NumberOfProcessors;
+
+ //
+ // Set the base address of CPU S3 data to PcdCpuS3DataAddress
+ //
+ PcdSet64 (PcdCpuS3DataAddress, (UINT64)(UINTN)mAcpiCpuData);
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Cache.h b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Cache.h
new file mode 100644
index 0000000..654d5cb
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Cache.h
@@ -0,0 +1,108 @@
+/** @file
+ Include file for record cache subclass data with Smbios protocol.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _CACHE_H_
+#define _CACHE_H_
+
+#include "MpCommon.h"
+
+//
+// Bit field definitions for return registers of CPUID EAX = 4
+//
+// EAX
+#define CPU_CACHE_TYPE_MASK 0x1F
+#define CPU_CACHE_LEVEL_MASK 0xE0
+#define CPU_CACHE_LEVEL_SHIFT 5
+// EBX
+#define CPU_CACHE_LINESIZE_MASK 0xFFF
+#define CPU_CACHE_PARTITIONS_MASK 0x3FF000
+#define CPU_CACHE_PARTITIONS_SHIFT 12
+#define CPU_CACHE_WAYS_MASK 0xFFC00000
+#define CPU_CACHE_WAYS_SHIFT 22
+
+#define CPU_CACHE_L1 1
+#define CPU_CACHE_L2 2
+#define CPU_CACHE_L3 3
+#define CPU_CACHE_L4 4
+#define CPU_CACHE_LMAX CPU_CACHE_L4
+
+typedef struct {
+ UINT8 CacheLevel;
+ UINT8 CacheDescriptor;
+ UINT16 CacheSizeinKB;
+ CACHE_ASSOCIATIVITY_DATA Associativity;
+ CACHE_TYPE_DATA SystemCacheType;
+} CPU_CACHE_CONVERTER;
+
+
+typedef struct {
+ UINT16 CacheSizeinKB;
+ CACHE_ASSOCIATIVITY_DATA Associativity;
+ CACHE_TYPE_DATA SystemCacheType;
+ //
+ // Can extend the structure here.
+ //
+} CPU_CACHE_DATA;
+
+//
+// It is defined for SMBIOS_TABLE_TYPE7.CacheConfiguration.
+//
+typedef struct {
+ UINT16 Level :3;
+ UINT16 Socketed :1;
+ UINT16 Reserved2 :1;
+ UINT16 Location :2;
+ UINT16 Enable :1;
+ UINT16 OperationalMode :2;
+ UINT16 Reserved1 :6;
+} CPU_CACHE_CONFIGURATION_DATA;
+
+/**
+ Add Cache Information to Type 7 SMBIOS Record.
+
+ @param[in] ProcessorNumber Processor number of specified processor.
+ @param[out] L1CacheHandle Pointer to the handle of the L1 Cache SMBIOS record.
+ @param[out] L2CacheHandle Pointer to the handle of the L2 Cache SMBIOS record.
+ @param[out] L3CacheHandle Pointer to the handle of the L3 Cache SMBIOS record.
+
+**/
+VOID
+AddSmbiosCacheTypeTable (
+ IN UINTN ProcessorNumber,
+ OUT EFI_SMBIOS_HANDLE *L1CacheHandle,
+ OUT EFI_SMBIOS_HANDLE *L2CacheHandle,
+ OUT EFI_SMBIOS_HANDLE *L3CacheHandle
+ );
+
+#endif
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CacheSubClass.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CacheSubClass.c
new file mode 100644
index 0000000..efd5ada
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CacheSubClass.c
@@ -0,0 +1,587 @@
+/** @file
+ Code to record cache subclass data with Smbios protocol.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Processor.h"
+#include "Cache.h"
+#include <Library/PrintLib.h>
+
+CPU_CACHE_CONVERTER mCacheConverter[] = {
+ {
+ 1,
+ 0x06,
+ 8,
+ CacheAssociativity4Way,
+ CacheTypeInstruction
+ },
+ {
+ 1,
+ 0x08,
+ 16,
+ CacheAssociativity4Way,
+ CacheTypeInstruction
+ },
+ {
+ 1,
+ 0x0A,
+ 8,
+ CacheAssociativity2Way,
+ CacheTypeData
+ },
+ {
+ 1,
+ 0x0C,
+ 16,
+ CacheAssociativity4Way,
+ CacheTypeData
+ },
+ {
+ 3,
+ 0x22,
+ 512,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 3,
+ 0x23,
+ 1024,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 3,
+ 0x25,
+ 2048,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 3,
+ 0x29,
+ 4096,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 1,
+ 0x2C,
+ 32,
+ CacheAssociativity8Way,
+ CacheTypeData
+ },
+ {
+ 1,
+ 0x30,
+ 32,
+ CacheAssociativity8Way,
+ CacheTypeInstruction
+ },
+ {
+ 2,
+ 0x39,
+ 128,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x3B,
+ 128,
+ CacheAssociativity2Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x3C,
+ 256,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x41,
+ 128,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x42,
+ 256,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x43,
+ 512,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x44,
+ 1024,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x45,
+ 2048,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x49,
+ 4096,
+ CacheAssociativity16Way,
+ CacheTypeUnified
+ },
+ {
+ 1,
+ 0x60,
+ 16,
+ CacheAssociativity8Way,
+ CacheTypeData
+ },
+ {
+ 1,
+ 0x66,
+ 8,
+ CacheAssociativity4Way,
+ CacheTypeData
+ },
+ {
+ 1,
+ 0x67,
+ 16,
+ CacheAssociativity4Way,
+ CacheTypeData
+ },
+ {
+ 1,
+ 0x68,
+ 32,
+ CacheAssociativity4Way,
+ CacheTypeData
+ },
+ {
+ 2,
+ 0x78,
+ 1024,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x79,
+ 128,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x7A,
+ 256,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x7B,
+ 512,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x7C,
+ 1024,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x7D,
+ 2048,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x7F,
+ 512,
+ CacheAssociativity2Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x82,
+ 256,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x83,
+ 512,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x84,
+ 1024,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x85,
+ 2048,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x86,
+ 512,
+ CacheAssociativity4Way,
+ CacheTypeUnified
+ },
+ {
+ 2,
+ 0x87,
+ 1024,
+ CacheAssociativity8Way,
+ CacheTypeUnified
+ }
+};
+
+/**
+ Get cache data from CPUID EAX = 2.
+
+ @param[in] ProcessorNumber Processor number of specified processor.
+ @param[out] CacheData Pointer to the cache data gotten from CPUID EAX = 2.
+
+**/
+VOID
+GetCacheDataFromCpuid2 (
+ IN UINTN ProcessorNumber,
+ OUT CPU_CACHE_DATA *CacheData
+ )
+{
+ UINT8 CacheLevel;
+ EFI_CPUID_REGISTER *CacheInformation;
+ UINTN CacheDescriptorNum;
+ UINT32 RegPointer[4];
+ UINT8 RegIndex;
+ UINT32 RegValue;
+ UINT8 ByteIndex;
+ UINT8 Descriptor;
+ UINTN DescriptorIndex;
+
+ DEBUG ((EFI_D_INFO, "Get cache data from CPUID EAX = 2\n"));
+
+ CacheDescriptorNum = (UINTN) (sizeof (mCacheConverter) / sizeof (mCacheConverter[0]));
+ CacheInformation = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_CACHE_INFO);
+ ASSERT (CacheInformation != NULL);
+
+ CopyMem (RegPointer, CacheInformation, sizeof (EFI_CPUID_REGISTER));
+ RegPointer[0] &= 0xFFFFFF00;
+
+ for (RegIndex = 0; RegIndex < 4; RegIndex++) {
+ RegValue = RegPointer[RegIndex];
+ //
+ // The most significant bit (bit 31) of each register indicates whether the register
+ // contains valid information (set to 0) or is reserved (set to 1).
+ //
+ if ((RegValue & BIT31) != 0) {
+ continue;
+ }
+
+ for (ByteIndex = 0; ByteIndex < 4; ByteIndex++) {
+ Descriptor = (UINT8) ((RegValue >> (ByteIndex * 8)) & 0xFF);
+ for (DescriptorIndex = 0; DescriptorIndex < CacheDescriptorNum; DescriptorIndex++) {
+ if (mCacheConverter[DescriptorIndex].CacheDescriptor == Descriptor) {
+ CacheLevel = mCacheConverter[DescriptorIndex].CacheLevel; // 1 based
+ ASSERT (CacheLevel >= 1 && CacheLevel <= CPU_CACHE_LMAX);
+ CacheData[CacheLevel - 1].CacheSizeinKB = (UINT16) (CacheData[CacheLevel - 1].CacheSizeinKB + mCacheConverter[DescriptorIndex].CacheSizeinKB);
+ CacheData[CacheLevel - 1].SystemCacheType = mCacheConverter[DescriptorIndex].SystemCacheType;
+ CacheData[CacheLevel - 1].Associativity = mCacheConverter[DescriptorIndex].Associativity;
+ }
+ }
+ }
+ }
+}
+
+/**
+ Get cache data from CPUID EAX = 4.
+
+ CPUID EAX = 4 is Deterministic Cache Parameters Leaf.
+
+ @param[in] ProcessorNumber Processor number of specified processor.
+ @param[out] CacheData Pointer to the cache data gotten from CPUID EAX = 4.
+
+**/
+VOID
+GetCacheDataFromCpuid4 (
+ IN UINTN ProcessorNumber,
+ OUT CPU_CACHE_DATA *CacheData
+ )
+{
+ EFI_CPUID_REGISTER *CpuidRegisters;
+ UINT8 Index;
+ UINT8 NumberOfDeterministicCacheParameters;
+ UINT32 Ways;
+ UINT32 Partitions;
+ UINT32 LineSize;
+ UINT32 Sets;
+ CACHE_TYPE_DATA SystemCacheType;
+ CACHE_ASSOCIATIVITY_DATA Associativity;
+ UINT8 CacheLevel;
+
+ DEBUG ((EFI_D_INFO, "Get cache data from CPUID EAX = 4\n"));
+
+ NumberOfDeterministicCacheParameters = (UINT8) GetNumberOfCpuidLeafs (ProcessorNumber, DeterministicCacheParametersCpuidLeafs);
+
+ for (Index = 0; Index < NumberOfDeterministicCacheParameters; Index++) {
+ CpuidRegisters = GetDeterministicCacheParametersCpuidLeaf (ProcessorNumber, Index);
+
+ if ((CpuidRegisters->RegEax & CPU_CACHE_TYPE_MASK) == 0) {
+ //break;
+ continue;
+ }
+
+ switch (CpuidRegisters->RegEax & CPU_CACHE_TYPE_MASK) {
+ case 1:
+ SystemCacheType = CacheTypeData;
+ break;
+ case 2:
+ SystemCacheType = CacheTypeInstruction;
+ break;
+ case 3:
+ SystemCacheType = CacheTypeUnified;
+ break;
+ default:
+ SystemCacheType = CacheTypeUnknown;
+ }
+
+ Ways = ((CpuidRegisters->RegEbx & CPU_CACHE_WAYS_MASK) >> CPU_CACHE_WAYS_SHIFT) + 1;
+ Partitions = ((CpuidRegisters->RegEbx & CPU_CACHE_PARTITIONS_MASK) >> CPU_CACHE_PARTITIONS_SHIFT) + 1;
+ LineSize = (CpuidRegisters->RegEbx & CPU_CACHE_LINESIZE_MASK) + 1;
+ Sets = CpuidRegisters->RegEcx + 1;
+
+ switch (Ways) {
+ case 2:
+ Associativity = CacheAssociativity2Way;
+ break;
+ case 4:
+ Associativity = CacheAssociativity4Way;
+ break;
+ case 8:
+ Associativity = CacheAssociativity8Way;
+ break;
+ case 12:
+ Associativity = CacheAssociativity12Way;
+ break;
+ case 16:
+ Associativity = CacheAssociativity16Way;
+ break;
+ case 24:
+ Associativity = CacheAssociativity24Way;
+ break;
+ case 32:
+ Associativity = CacheAssociativity32Way;
+ break;
+ case 48:
+ Associativity = CacheAssociativity48Way;
+ break;
+ case 64:
+ Associativity = CacheAssociativity64Way;
+ break;
+ default:
+ Associativity = CacheAssociativityFully;
+ break;
+ }
+
+ CacheLevel = (UINT8) ((CpuidRegisters->RegEax & CPU_CACHE_LEVEL_MASK) >> CPU_CACHE_LEVEL_SHIFT); // 1 based
+ ASSERT (CacheLevel >= 1 && CacheLevel <= CPU_CACHE_LMAX);
+ CacheData[CacheLevel - 1].CacheSizeinKB = (UINT16) (CacheData[CacheLevel - 1].CacheSizeinKB + (Ways * Partitions * LineSize * Sets) / 1024);
+ CacheData[CacheLevel - 1].SystemCacheType = SystemCacheType;
+ CacheData[CacheLevel - 1].Associativity = Associativity;
+ }
+
+}
+
+/**
+ Add Type 7 SMBIOS Record for Cache Information.
+
+ @param[in] ProcessorNumber Processor number of specified processor.
+ @param[out] L1CacheHandle Pointer to the handle of the L1 Cache SMBIOS record.
+ @param[out] L2CacheHandle Pointer to the handle of the L2 Cache SMBIOS record.
+ @param[out] L3CacheHandle Pointer to the handle of the L3 Cache SMBIOS record.
+
+**/
+VOID
+AddSmbiosCacheTypeTable (
+ IN UINTN ProcessorNumber,
+ OUT EFI_SMBIOS_HANDLE *L1CacheHandle,
+ OUT EFI_SMBIOS_HANDLE *L2CacheHandle,
+ OUT EFI_SMBIOS_HANDLE *L3CacheHandle
+ )
+{
+ EFI_STATUS Status;
+ SMBIOS_TABLE_TYPE7 *SmbiosRecord;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ UINT8 CacheLevel;
+ CPU_CACHE_DATA CacheData[CPU_CACHE_LMAX];
+ CHAR8 *OptionalStrStart;
+ UINTN StringBufferSize;
+ UINTN CacheSocketStrLen;
+ EFI_STRING CacheSocketStr;
+ CACHE_SRAM_TYPE_DATA CacheSramType;
+ CPU_CACHE_CONFIGURATION_DATA CacheConfig;
+
+ ZeroMem (CacheData, CPU_CACHE_LMAX * sizeof (CPU_CACHE_DATA));
+
+ //
+ // Check whether the CPU supports CPUID EAX = 4, if yes, get cache data from CPUID EAX = 4,
+ // or no, get cache data from CPUID EAX = 2 to be compatible with the earlier CPU.
+ //
+ if (GetNumberOfCpuidLeafs (ProcessorNumber, BasicCpuidLeaf) > 4 ) {
+ GetCacheDataFromCpuid4 (ProcessorNumber, CacheData);
+ } else {
+ GetCacheDataFromCpuid2 (ProcessorNumber, CacheData);
+ }
+
+ //
+ // Now cache data has been ready.
+ //
+ for (CacheLevel = 0; CacheLevel < CPU_CACHE_LMAX; CacheLevel++) {
+ //
+ // NO smbios record for zero-sized cache.
+ //
+ if (CacheData[CacheLevel].CacheSizeinKB == 0) {
+ continue;
+ }
+
+ DEBUG ((
+ EFI_D_INFO,
+ "CacheData: CacheLevel = 0x%x CacheSizeinKB = 0x%xKB SystemCacheType = 0x%x Associativity = 0x%x\n",
+ CacheLevel + 1,
+ CacheData[CacheLevel].CacheSizeinKB,
+ CacheData[CacheLevel].SystemCacheType,
+ CacheData[CacheLevel].Associativity
+ ));
+
+
+ StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
+ CacheSocketStr = AllocateZeroPool (StringBufferSize);
+ ASSERT (CacheSocketStr != NULL);
+ CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, StringBufferSize, L"L%x-Cache", CacheLevel + 1);
+ ASSERT (CacheSocketStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ //
+ // Report Cache Information to Type 7 SMBIOS Record.
+ //
+
+ SmbiosRecord = AllocatePool (sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1);
+ ASSERT (SmbiosRecord != NULL);
+ ZeroMem (SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION;
+ SmbiosRecord->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE7);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ //
+ // Socket will be the 1st optional string following the formatted structure.
+ //
+ SmbiosRecord->SocketDesignation = 1;
+
+ //
+ // Cache Level - 1 through 8, e.g. an L1 cache would use value 000b and an L3 cache would use 010b.
+ //
+ CacheConfig.Level = CacheLevel;
+ CacheConfig.Socketed = 0; // Not Socketed
+ CacheConfig.Reserved2 = 0;
+ CacheConfig.Location = 0; // Internal Cache
+ CacheConfig.Enable = 1; // Cache enabled
+ CacheConfig.OperationalMode = 1; // Write Back
+ CacheConfig.Reserved1 = 0;
+ CopyMem (&SmbiosRecord->CacheConfiguration, &CacheConfig, 2);
+ //
+ // Only 1K granularity assumed here.
+ //
+ SmbiosRecord->MaximumCacheSize = CacheData[CacheLevel].CacheSizeinKB;
+ SmbiosRecord->InstalledSize = CacheData[CacheLevel].CacheSizeinKB;
+
+ ZeroMem (&CacheSramType, sizeof (CACHE_SRAM_TYPE_DATA));
+ CacheSramType.Synchronous = 1;
+ CopyMem (&SmbiosRecord->SupportedSRAMType, &CacheSramType, 2);
+ CopyMem (&SmbiosRecord->CurrentSRAMType, &CacheSramType, 2);
+
+ SmbiosRecord->CacheSpeed = 0;
+ SmbiosRecord->ErrorCorrectionType = CacheErrorSingleBit;
+ SmbiosRecord->SystemCacheType = (UINT8) CacheData[CacheLevel].SystemCacheType;
+ SmbiosRecord->Associativity = (UINT8) CacheData[CacheLevel].Associativity;
+
+ OptionalStrStart = (CHAR8 *) (SmbiosRecord + 1);
+ UnicodeStrToAsciiStr (CacheSocketStr, OptionalStrStart);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) SmbiosRecord);
+
+ //
+ // Record L1/L2/L3 Cache Smbios Handle, Type 4 SMBIOS Record needs it.
+ //
+ if (CacheLevel + 1 == CPU_CACHE_L1) {
+ *L1CacheHandle = SmbiosHandle;
+ } else if (CacheLevel + 1 == CPU_CACHE_L2) {
+ *L2CacheHandle = SmbiosHandle;
+ } else if (CacheLevel + 1 == CPU_CACHE_L3) {
+ *L3CacheHandle = SmbiosHandle;
+ }
+ FreePool (SmbiosRecord);
+ FreePool (CacheSocketStr);
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CpuSmbios.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CpuSmbios.c
new file mode 100644
index 0000000..193ab19
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CpuSmbios.c
@@ -0,0 +1,126 @@
+/** @file
+ Code to log processor and cache subclass data to smbios record.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Processor.h"
+#include "Cache.h"
+
+EFI_SMBIOS_PROTOCOL *mSmbios;
+EFI_HII_HANDLE mStringHandle;
+UINT32 mPopulatedSocketCount;
+
+/**
+ Add SMBIOS Processor Type and Cache Type tables for the CPU.
+**/
+VOID
+AddCpuSmbiosTables (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE L1CacheHandle;
+ EFI_SMBIOS_HANDLE L2CacheHandle;
+ EFI_SMBIOS_HANDLE L3CacheHandle;
+ UINT32 PreviousPackageNumber;
+ UINT32 PackageNumber;
+ UINTN ProcessorIndex;
+ UINTN *SocketProcessorNumberTable;
+ UINT32 SocketIndex;
+
+ L1CacheHandle = 0xFFFF;
+ L2CacheHandle = 0xFFFF;
+ L3CacheHandle = 0xFFFF;
+
+ //
+ // Initialize the mSmbios to contain the SMBIOS protocol,
+ //
+ Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &mSmbios);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize strings to HII database
+ //
+ mStringHandle = HiiAddPackages (
+ &gEfiCallerIdGuid,
+ NULL,
+ CpuMpDxeStrings,
+ NULL
+ );
+ ASSERT (mStringHandle != NULL);
+
+ SocketProcessorNumberTable = AllocateZeroPool (mCpuConfigConextBuffer.NumberOfProcessors * sizeof (UINTN));
+ ASSERT (SocketProcessorNumberTable != NULL);
+
+ //
+ // Detect populated sockets (comparing the processors' PackangeNumber) and record their ProcessorNumber.
+ // For example:
+ // ProcessorNumber: 0 1 2 3 (PackageNumber 0) 4 5 6 7 (PackageNumber 1)
+ // And then, populated socket count will be 2 and record ProcessorNumber 0 for Socket 0, ProcessorNumber 4 for Socket 1
+ //
+
+ //
+ // System has 1 populated socket at least, initialize mPopulatedSocketCount to 1 and record ProcessorNumber 0 for it.
+ //
+ mPopulatedSocketCount = 1;
+ SocketProcessorNumberTable[0] = 0;
+ GetProcessorLocation (0, &PreviousPackageNumber, NULL, NULL);
+
+ //
+ // Scan and compare the processors' PackageNumber to find the populated sockets.
+ //
+ for (ProcessorIndex = 1; ProcessorIndex < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorIndex++) {
+ GetProcessorLocation (ProcessorIndex, &PackageNumber, NULL, NULL);
+ if (PackageNumber != PreviousPackageNumber) {
+ //
+ // Found a new populated socket.
+ //
+ PreviousPackageNumber = PackageNumber;
+ mPopulatedSocketCount++;
+ SocketProcessorNumberTable[mPopulatedSocketCount - 1] = ProcessorIndex;
+ }
+ }
+
+ //
+ // Add SMBIOS tables for populated sockets.
+ //
+ for (SocketIndex = 0; SocketIndex < mPopulatedSocketCount; SocketIndex++) {
+ AddSmbiosCacheTypeTable (SocketProcessorNumberTable[SocketIndex], &L1CacheHandle, &L2CacheHandle, &L3CacheHandle);
+ AddSmbiosProcessorTypeTable (SocketProcessorNumberTable[SocketIndex], L1CacheHandle, L2CacheHandle, L3CacheHandle);
+ }
+ FreePool (SocketProcessorNumberTable);
+
+ //
+ // Register notification functions for Smbios Processor Type.
+ //
+ SmbiosProcessorTypeTableCallback ();
+}
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Processor.h b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Processor.h
new file mode 100644
index 0000000..c517c3e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Processor.h
@@ -0,0 +1,172 @@
+/** @file
+ Include file for record processor subclass data with Smbios protocol.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _PROCESSOR_H_
+#define _PROCESSOR_H_
+
+#include "MpCommon.h"
+
+//
+// This is the string tool generated data representing our strings.
+//
+extern UINT8 CpuMpDxeStrings[];
+extern EFI_SMBIOS_PROTOCOL *mSmbios;
+extern EFI_HII_HANDLE mStringHandle;
+extern UINT32 mPopulatedSocketCount;
+
+//
+// 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_STRING_ID StringRef;
+} CPU_PROCESSOR_VERSION_INFORMATION;
+
+//
+// It is defined for SMBIOS_TABLE_TYPE4.Status.
+//
+typedef struct {
+ UINT8 CpuStatus :3; // Indicates the status of the processor.
+ UINT8 Reserved1 :3; // Reserved for future use. Should be set to zero.
+ UINT8 SocketPopulated :1; // Indicates if the processor socket is populated or not.
+ UINT8 Reserved2 :1; // Reserved for future use. Should be set to zero.
+} CPU_PROCESSOR_STATUS_DATA;
+
+//
+// It is defined for SMBIOS_TABLE_TYPE4.ProcessorCharacteristics.
+//
+typedef struct {
+ UINT16 Reserved :1;
+ UINT16 Unknown :1;
+ UINT16 Capable64Bit :1;
+ UINT16 Reserved2 :13;
+} CPU_PROCESSOR_CHARACTERISTICS_DATA;
+
+/**
+ Add Processor Information to Type 4 SMBIOS Record for Socket Populated.
+
+ @param[in] ProcessorNumber Processor number of specified processor.
+ @param[in] L1CacheHandle The handle of the L1 Cache SMBIOS record.
+ @param[in] L2CacheHandle The handle of the L2 Cache SMBIOS record.
+ @param[in] L3CacheHandle The handle of the L3 Cache SMBIOS record.
+
+**/
+VOID
+AddSmbiosProcessorTypeTable (
+ IN UINTN ProcessorNumber,
+ IN EFI_SMBIOS_HANDLE L1CacheHandle,
+ IN EFI_SMBIOS_HANDLE L2CacheHandle,
+ IN EFI_SMBIOS_HANDLE L3CacheHandle
+ );
+
+/**
+ Register notification functions for Pcds related to Smbios Processor Type.
+**/
+VOID
+SmbiosProcessorTypeTableCallback (
+ VOID
+ );
+
+/**
+ Returns the processor voltage of the processor installed in the system.
+
+ @param ProcessorNumber Processor number of specified processor.
+
+ @return Processor Voltage in mV
+
+**/
+UINT16
+GetProcessorVoltage (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Returns the procesor version string token installed in the system.
+
+ @param ProcessorNumber Processor number of specified processor.
+ @param Version Pointer to the output processor version.
+
+**/
+VOID
+GetProcessorVersion (
+ IN UINTN ProcessorNumber,
+ OUT CPU_PROCESSOR_VERSION_INFORMATION *Version
+ );
+
+/**
+ Returns the processor family of the processor installed in the system.
+
+ @param ProcessorNumber Processor number of specified processor.
+
+ @return Processor Family
+
+**/
+PROCESSOR_FAMILY_DATA
+GetProcessorFamily (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Returns the procesor manufaturer string token installed in the system.
+
+ @param ProcessorNumber Processor number of specified processor.
+
+ @return Processor Manufacturer string token.
+
+**/
+EFI_STRING_ID
+GetProcessorManufacturer (
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Checks if processor is Intel or not.
+
+ @param ProcessorNumber Processor number of specified processor.
+
+ @return TRUE Intel Processor.
+ @return FALSE Not Intel Processor.
+
+**/
+BOOLEAN
+IsIntelProcessor (
+ IN UINTN ProcessorNumber
+ );
+
+#endif
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorData.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorData.c
new file mode 100644
index 0000000..21cd45e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorData.c
@@ -0,0 +1,203 @@
+/** @file
+ Code to retrieve processor sublcass data.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Cpu.h"
+#include "Processor.h"
+
+/**
+ Returns the procesor version string token installed in the system.
+
+ @param ProcessorNumber Processor number of specified processor.
+ @param Version Pointer to the output processor version.
+
+**/
+VOID
+GetProcessorVersion (
+ IN UINTN ProcessorNumber,
+ OUT CPU_PROCESSOR_VERSION_INFORMATION *Version
+ )
+{
+ CHAR16 BrandIdString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1];
+ EFI_CPUID_REGISTER *CpuBrandString;
+ UINT8 Index;
+
+ //
+ // Create the string using Brand ID String.
+ //
+ Version->StringValid = FALSE;
+
+ if (IsIntelProcessor (ProcessorNumber)) {
+ Version->StringRef = STRING_TOKEN (STR_INTEL_GENUINE_PROCESSOR);
+
+ CpuBrandString = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_BRAND_STRING1);
+ ASSERT (CpuBrandString != NULL);
+
+ //
+ // Check if Brand ID String is supported or filled up
+ //
+ if (CpuBrandString->RegEax != 0) {
+ AsciiStrToUnicodeStr ((CHAR8 *) CpuBrandString, (CHAR16 *) &BrandIdString[0]);
+
+ CpuBrandString = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_BRAND_STRING2);
+ ASSERT (CpuBrandString != NULL);
+ AsciiStrToUnicodeStr ((CHAR8 *) CpuBrandString, (CHAR16 *) &BrandIdString[16]);
+
+ CpuBrandString = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_BRAND_STRING3);
+ ASSERT (CpuBrandString != NULL);
+ AsciiStrToUnicodeStr ((CHAR8 *) CpuBrandString, (CHAR16 *) &BrandIdString[32]);
+
+ //
+ // Remove preceeding spaces
+ //
+ Index = 0;
+ while (((Index < MAXIMUM_CPU_BRAND_STRING_LENGTH) && (BrandIdString[Index] == 0x20)) != 0) {
+ Index++;
+ }
+
+ ASSERT (Index <= MAXIMUM_CPU_BRAND_STRING_LENGTH);
+ 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.
+
+ @param ProcessorNumber Processor number of specified processor.
+
+ @return Processor Manufacturer string token.
+
+**/
+EFI_STRING_ID
+GetProcessorManufacturer (
+ IN UINTN ProcessorNumber
+ )
+{
+ if (IsIntelProcessor (ProcessorNumber)) {
+ return STRING_TOKEN (STR_INTEL_CORPORATION);
+ } else {
+ return STRING_TOKEN (STR_UNKNOWN);
+ }
+}
+
+/**
+ Checks if processor is Intel or not.
+
+ @param ProcessorNumber Processor number of specified processor.
+
+ @return TRUE Intel Processor.
+ @return FALSE Not Intel Processor.
+
+**/
+BOOLEAN
+IsIntelProcessor (
+ IN UINTN ProcessorNumber
+ )
+{
+ EFI_CPUID_REGISTER *Reg;
+
+ Reg = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_SIGNATURE);
+ ASSERT (Reg != NULL);
+
+ //
+ // After CPUID(0), check if EBX contians 'uneG', ECX contains 'letn', and EDX contains 'Ieni'
+ //
+ if ((Reg->RegEbx != 0x756e6547) || (Reg->RegEcx != 0x6c65746e) || (Reg->RegEdx != 0x49656e69)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Returns the processor family of the processor installed in the system.
+
+ @param ProcessorNumber Processor number of specified processor.
+
+ @return Processor Family
+
+**/
+PROCESSOR_FAMILY_DATA
+GetProcessorFamily (
+ IN UINTN ProcessorNumber
+ )
+{
+ UINT32 FamilyId;
+ UINT32 ModelId;
+
+ if (IsIntelProcessor (ProcessorNumber)) {
+
+ GetProcessorVersionInfo (ProcessorNumber, &FamilyId, &ModelId, NULL, NULL);
+
+ return ProcessorFamilyPentium;
+ }
+
+ return ProcessorFamilyUnknown;
+}
+
+/**
+ Returns the processor voltage of the processor installed in the system.
+
+ @param ProcessorNumber Processor number of specified processor.
+
+ @return Processor Voltage in mV
+
+**/
+UINT16
+GetProcessorVoltage (
+ IN UINTN ProcessorNumber
+ )
+{
+ UINT16 VoltageInmV;
+ EFI_CPUID_REGISTER *Reg;
+
+ Reg = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_VERSION_INFO);
+ ASSERT (Reg != NULL);
+
+ if ((Reg->RegEax >> 8 & 0x3F) == 0xF) {
+ VoltageInmV = 3000;
+ } else {
+ VoltageInmV = 1600;
+ }
+
+ return VoltageInmV;
+}
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorSubClass.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorSubClass.c
new file mode 100644
index 0000000..9913647
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorSubClass.c
@@ -0,0 +1,537 @@
+/** @file
+ Code to log processor subclass data with Smbios protocol.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Cpu.h"
+#include "Processor.h"
+
+UINTN mCpuSocketStrNumber = 1;
+UINTN mCpuAssetTagStrNumber = 4;
+
+/**
+ Add Type 4 SMBIOS Record for Socket Unpopulated.
+**/
+VOID
+AddUnpopulatedSmbiosProcessorTypeTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ UINTN TotalSize;
+ SMBIOS_TABLE_TYPE4 *SmbiosRecord;
+ CHAR8 *OptionalStrStart;
+ EFI_STRING_ID Token;
+ EFI_STRING CpuSocketStr;
+ UINTN CpuSocketStrLen;
+
+ //
+ // Get CPU Socket string, it will be updated when PcdPlatformCpuSocketNames is set.
+ //
+ Token = STRING_TOKEN (STR_UNKNOWN);
+ CpuSocketStr = HiiGetPackageString (&gEfiCallerIdGuid, Token ,NULL);
+ ASSERT (CpuSocketStr != NULL);
+ CpuSocketStrLen = StrLen (CpuSocketStr);
+ ASSERT (CpuSocketStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ //
+ // Report Processor Information to Type 4 SMBIOS Record.
+ //
+
+ TotalSize = sizeof (SMBIOS_TABLE_TYPE4) + CpuSocketStrLen + 1 + 1;
+ SmbiosRecord = AllocatePool (TotalSize);
+ ASSERT (SmbiosRecord != NULL);
+ ZeroMem (SmbiosRecord, TotalSize);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;
+ SmbiosRecord->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE4);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ //
+ // Socket will be the 1st optional string following the formatted structure.
+ //
+ SmbiosRecord->Socket = (UINT8) mCpuSocketStrNumber;
+ SmbiosRecord->ProcessorType = CentralProcessor;
+
+ //
+ // Just indicate CPU Socket Unpopulated.
+ // CPU_PROCESSOR_STATUS_DATA.SocketPopulated: 1- CPU Socket populated and 0 - CPU Socket Unpopulated
+ //
+ SmbiosRecord->Status = 0;
+
+ SmbiosRecord->MaxSpeed = (UINT16) PcdGet32 (PcdPlatformCpuMaxCoreFrequency);
+ SmbiosRecord->ProcessorUpgrade = ProcessorUpgradeSocketLGA775;
+
+ SmbiosRecord->L1CacheHandle = 0xFFFF;
+ SmbiosRecord->L2CacheHandle = 0xFFFF;
+ SmbiosRecord->L3CacheHandle = 0xFFFF;
+
+ OptionalStrStart = (CHAR8 *) (SmbiosRecord + 1);
+ UnicodeStrToAsciiStr (CpuSocketStr, OptionalStrStart);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord);
+ FreePool (SmbiosRecord);
+ FreePool (CpuSocketStr);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Add Processor Information to Type 4 SMBIOS Record for Socket Populated.
+
+ @param[in] ProcessorNumber Processor number of specified processor.
+ @param[in] L1CacheHandle The handle of the L1 Cache SMBIOS record.
+ @param[in] L2CacheHandle The handle of the L2 Cache SMBIOS record.
+ @param[in] L3CacheHandle The handle of the L3 Cache SMBIOS record.
+
+**/
+VOID
+AddSmbiosProcessorTypeTable (
+ IN UINTN ProcessorNumber,
+ IN EFI_SMBIOS_HANDLE L1CacheHandle,
+ IN EFI_SMBIOS_HANDLE L2CacheHandle,
+ IN EFI_SMBIOS_HANDLE L3CacheHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ UINTN TotalSize;
+ EFI_STRING_ID Token;
+ CHAR8 *OptionalStrStart;
+ EFI_STRING CpuManuStr;
+ EFI_STRING CpuVerStr;
+ EFI_STRING CpuSocketStr;
+ EFI_STRING CpuAssetTagStr;
+ UINTN CpuManuStrLen;
+ UINTN CpuVerStrLen;
+ UINTN CpuSocketStrLen;
+ UINTN CpuAssetTagStrLen;
+ SMBIOS_TABLE_TYPE4 *SmbiosRecord;
+ EFI_CPUID_REGISTER *CpuidRegister;
+ UINT16 ProcessorVoltage;
+ CPU_PROCESSOR_VERSION_INFORMATION Version;
+ CPU_PROCESSOR_STATUS_DATA ProcessorStatus;
+ CPU_PROCESSOR_CHARACTERISTICS_DATA ProcessorCharacteristics;
+ UINT16 PackageThreadCount;
+ UINT16 CoreThreadCount;
+ UINT8 CoreCount;
+
+ CoreCount = 0;
+
+ //
+ // Get CPU Socket string, it will be updated when PcdPlatformCpuSocketNames is set.
+ //
+ Token = STRING_TOKEN (STR_UNKNOWN);
+ CpuSocketStr = HiiGetPackageString (&gEfiCallerIdGuid, Token ,NULL);
+ ASSERT (CpuSocketStr != NULL);
+ CpuSocketStrLen = StrLen (CpuSocketStr);
+ ASSERT (CpuSocketStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ //
+ // Get CPU Manufacture string.
+ //
+ Token = GetProcessorManufacturer (ProcessorNumber);
+ CpuManuStr = HiiGetPackageString (&gEfiCallerIdGuid, Token, NULL);
+ ASSERT (CpuManuStr != NULL);
+ CpuManuStrLen = StrLen (CpuManuStr);
+ ASSERT (CpuManuStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ //
+ // Get CPU Version string.
+ //
+ GetProcessorVersion (ProcessorNumber, &Version);
+ if (Version.StringValid) {
+ Token = HiiSetString (mStringHandle, 0, Version.BrandString, NULL);
+ if (Token == 0) {
+ Token = Version.StringRef;
+ }
+ } else {
+ Token = Version.StringRef;
+ }
+ CpuVerStr = HiiGetPackageString (&gEfiCallerIdGuid, Token, NULL);
+ ASSERT (CpuVerStr != NULL);
+ CpuVerStrLen = StrLen (CpuVerStr);
+ ASSERT (CpuVerStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ //
+ // Get CPU Asset Tag string, it will be updated when PcdPlatformCpuAssetTags is set.
+ //
+ Token = STRING_TOKEN (STR_UNKNOWN);
+ CpuAssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, Token ,NULL);
+ ASSERT (CpuAssetTagStr != NULL);
+ CpuAssetTagStrLen = StrLen (CpuAssetTagStr);
+ ASSERT (CpuAssetTagStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ //
+ // Get CPU core count.
+ //
+ if (GetNumberOfCpuidLeafs (ProcessorNumber, BasicCpuidLeaf) > EFI_CPUID_CORE_TOPOLOGY) {
+ CpuidRegister = GetExtendedTopologyEnumerationCpuidLeafs (ProcessorNumber, 1);
+ PackageThreadCount = (UINT16) (CpuidRegister->RegEbx);
+ CpuidRegister = GetExtendedTopologyEnumerationCpuidLeafs (ProcessorNumber, 0);
+ CoreThreadCount = (UINT16) (CpuidRegister->RegEbx);
+ CoreCount = (UINT8) (PackageThreadCount / CoreThreadCount);
+ }
+
+ //
+ // Report Processor Information to Type 4 SMBIOS Record.
+ //
+
+ TotalSize = sizeof (SMBIOS_TABLE_TYPE4) + CpuSocketStrLen + 1 + CpuManuStrLen + 1 + CpuVerStrLen + 1 + CpuAssetTagStrLen + 1 + 1;
+ SmbiosRecord = AllocatePool (TotalSize);
+ ASSERT (SmbiosRecord != NULL);
+ ZeroMem (SmbiosRecord, TotalSize);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;
+ SmbiosRecord->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE4);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ //
+ // Socket will be the 1st optional string following the formatted structure.
+ //
+ SmbiosRecord->Socket = (UINT8) mCpuSocketStrNumber;
+ SmbiosRecord->ProcessorType = CentralProcessor;
+ SmbiosRecord->ProcessorFamily = (UINT8) GetProcessorFamily (ProcessorNumber);
+ //
+ // Manu will be the 2nd optional string following the formatted structure.
+ //
+ SmbiosRecord->ProcessorManufacture = 2;
+
+ CpuidRegister = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_VERSION_INFO);
+ ASSERT (CpuidRegister != NULL);
+ *(UINT32 *) &SmbiosRecord->ProcessorId.Signature = CpuidRegister->RegEax;
+ *(UINT32 *) &SmbiosRecord->ProcessorId.FeatureFlags = CpuidRegister->RegEdx,
+
+ //
+ // Version will be the 3rd optional string following the formatted structure.
+ //
+ SmbiosRecord->ProcessorVersion = 3;
+
+ ProcessorVoltage = GetProcessorVoltage (ProcessorNumber); // mV unit
+ ProcessorVoltage = (UINT16) ((ProcessorVoltage * 10) / 1000);
+ *(UINT8 *) &SmbiosRecord->Voltage = (UINT8) ProcessorVoltage;
+ SmbiosRecord->Voltage.ProcessorVoltageIndicateLegacy = 1;
+
+ SmbiosRecord->ExternalClock = (UINT16) (GET_CPU_MISC_DATA (ProcessorNumber, IntendedFsbFrequency));
+ SmbiosRecord->MaxSpeed = (UINT16) PcdGet32 (PcdPlatformCpuMaxCoreFrequency);
+ SmbiosRecord->CurrentSpeed = (UINT16) (GET_CPU_MISC_DATA (ProcessorNumber, IntendedFsbFrequency) * GET_CPU_MISC_DATA (ProcessorNumber, MaxCoreToBusRatio));
+
+ ProcessorStatus.CpuStatus = 1; // CPU Enabled
+ ProcessorStatus.Reserved1 = 0;
+ ProcessorStatus.SocketPopulated = 1; // CPU Socket Populated
+ ProcessorStatus.Reserved2 = 0;
+ CopyMem (&SmbiosRecord->Status, &ProcessorStatus, 1);
+
+ SmbiosRecord->ProcessorUpgrade = ProcessorUpgradeSocketLGA775;
+
+ SmbiosRecord->L1CacheHandle = L1CacheHandle;
+ SmbiosRecord->L2CacheHandle = L2CacheHandle;
+ SmbiosRecord->L3CacheHandle = L3CacheHandle;
+
+ //
+ // AssetTag will be the 4th optional string following the formatted structure.
+ //
+ SmbiosRecord->AssetTag = (UINT8) mCpuAssetTagStrNumber;
+
+ SmbiosRecord->CoreCount = CoreCount;
+
+ ProcessorCharacteristics.Reserved = 0;
+ ProcessorCharacteristics.Capable64Bit = 1; // 64-bit Capable
+ ProcessorCharacteristics.Unknown = 0;
+ ProcessorCharacteristics.Reserved2 = 0;
+ CopyMem (&SmbiosRecord->ProcessorCharacteristics, &ProcessorCharacteristics, 2);
+
+ OptionalStrStart = (CHAR8 *) (SmbiosRecord + 1);
+ UnicodeStrToAsciiStr (CpuSocketStr, OptionalStrStart);
+ UnicodeStrToAsciiStr (CpuManuStr, OptionalStrStart + CpuSocketStrLen + 1);
+ UnicodeStrToAsciiStr (CpuVerStr, OptionalStrStart + CpuSocketStrLen + 1 + CpuManuStrLen + 1);
+ UnicodeStrToAsciiStr (CpuAssetTagStr, OptionalStrStart + CpuSocketStrLen + 1 + CpuManuStrLen + 1 + CpuVerStrLen + 1);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord);
+ FreePool (SmbiosRecord);
+ FreePool (CpuSocketStr);
+ FreePool (CpuManuStr);
+ FreePool (CpuVerStr);
+ FreePool (CpuAssetTagStr);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Get Type 4 SMBIOS Record table.
+
+ @param[in, out] SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the
+ next SMBIOS record handle. If it is zero on entry, then the first SMBIOS record
+ handle will be returned. If it returns zero on exit, then there are no more SMBIOS records.
+ @param[out] Record Returned pointer to record buffer .
+
+**/
+VOID
+GetSmbiosProcessorTypeTable (
+ IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle,
+ OUT EFI_SMBIOS_TABLE_HEADER *Record OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_TYPE RecordType;
+ EFI_SMBIOS_TABLE_HEADER *Buffer;
+
+ RecordType = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;
+ do {
+ Status = mSmbios->GetNext (
+ mSmbios,
+ SmbiosHandle,
+ &RecordType,
+ &Buffer,
+ NULL
+ );
+ if (!EFI_ERROR(Status)) {
+ if (Record != NULL) {
+ Record = Buffer;
+ }
+ return;
+ }
+ } while (!EFI_ERROR(Status));
+
+}
+
+/**
+ Notification function when PcdPlatformCpuSocketCount is set.
+
+ @param[in] CallBackGuid The PCD token GUID being set.
+ @param[in] CallBackToken The PCD token number being set.
+ @param[in, out] TokenData A pointer to the token data being set.
+ @param[in] TokenDataSize The size, in bytes, of the data being set.
+
+**/
+VOID
+EFIAPI
+CallbackOnPcdPlatformCpuSocketCount (
+ IN CONST GUID *CallBackGuid, OPTIONAL
+ IN UINTN CallBackToken,
+ IN OUT VOID *TokenData,
+ IN UINTN TokenDataSize
+ )
+{
+ UINT32 CpuSocketCount;
+ UINT32 SocketIndex;
+
+ CpuSocketCount = 0;
+ if (CallBackToken == PcdToken (PcdPlatformCpuSocketCount)) {
+ if (TokenDataSize == sizeof (UINT32)) {
+ CpuSocketCount = ReadUnaligned32 (TokenData);
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "Callback: PcdPlatformCpuSocketCount is set\n"));
+
+ if (CpuSocketCount <= mPopulatedSocketCount) {
+ return;
+ }
+
+ //
+ // Add Type 4 SMBIOS Record for Socket Unpopulated.
+ //
+ for (SocketIndex = mPopulatedSocketCount; SocketIndex < CpuSocketCount; SocketIndex++) {
+ AddUnpopulatedSmbiosProcessorTypeTable ();
+ }
+
+}
+
+/**
+ Notification function when PcdPlatformCpuSocketNames is set.
+
+ @param[in] CallBackGuid The PCD token GUID being set.
+ @param[in] CallBackToken The PCD token number being set.
+ @param[in, out] TokenData A pointer to the token data being set.
+ @param[in] TokenDataSize The size, in bytes, of the data being set.
+
+**/
+VOID
+EFIAPI
+CallbackOnPcdPlatformCpuSocketNames (
+ IN CONST GUID *CallBackGuid, OPTIONAL
+ IN UINTN CallBackToken,
+ IN OUT VOID *TokenData,
+ IN UINTN TokenDataSize
+ )
+{
+ CHAR16 **CpuSocketNames;
+ CHAR8 *CpuSocketStr;
+ UINTN CpuSocketStrLen;
+ UINT32 SocketIndex;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ UINT32 CpuSocketCount;
+
+ CpuSocketNames = NULL;
+ if (CallBackToken == PcdToken (PcdPlatformCpuSocketNames)) {
+ if (TokenDataSize == sizeof (UINT64)) {
+ CpuSocketNames = (CHAR16 **) (UINTN) ReadUnaligned64 (TokenData);
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "Callback: PcdPlatformCpuSocketNames is set\n"));
+
+ if (CpuSocketNames == NULL) {
+ return;
+ }
+
+ CpuSocketCount = PcdGet32 (PcdPlatformCpuSocketCount);
+ if (CpuSocketCount < mPopulatedSocketCount) {
+ CpuSocketCount = mPopulatedSocketCount;
+ }
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ SocketIndex = 0;
+
+ //
+ // Update CPU Socket string for Socket Populated.
+ //
+ do {
+ GetSmbiosProcessorTypeTable (&SmbiosHandle, NULL);
+ if (SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {
+ return;
+ }
+ CpuSocketStrLen = StrLen (CpuSocketNames[SocketIndex]);
+ ASSERT (CpuSocketStrLen <= SMBIOS_STRING_MAX_LENGTH);
+ CpuSocketStr = AllocatePool (CpuSocketStrLen + 1);
+ UnicodeStrToAsciiStr (CpuSocketNames[SocketIndex], CpuSocketStr);
+ mSmbios->UpdateString (mSmbios, &SmbiosHandle, &mCpuSocketStrNumber, CpuSocketStr);
+ FreePool (CpuSocketStr);
+ } while ((++SocketIndex) < CpuSocketCount);
+
+}
+
+/**
+ Notification function when PcdPlatformCpuAssetTags is set.
+
+ @param[in] CallBackGuid The PCD token GUID being set.
+ @param[in] CallBackToken The PCD token number being set.
+ @param[in, out] TokenData A pointer to the token data being set.
+ @param[in] TokenDataSize The size, in bytes, of the data being set.
+
+**/
+VOID
+EFIAPI
+CallbackOnPcdPlatformCpuAssetTags (
+ IN CONST GUID *CallBackGuid, OPTIONAL
+ IN UINTN CallBackToken,
+ IN OUT VOID *TokenData,
+ IN UINTN TokenDataSize
+ )
+{
+ CHAR16 **CpuAssetTags;
+ CHAR8 *CpuAssetTagStr;
+ UINTN CpuAssetTagStrLen;
+ UINT32 SocketIndex;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+
+ CpuAssetTags = NULL;
+ if (CallBackToken == PcdToken (PcdPlatformCpuAssetTags)) {
+ if (TokenDataSize == sizeof (UINT64)) {
+ CpuAssetTags = (CHAR16 **) (UINTN) ReadUnaligned64 (TokenData);
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "Callback: PcdPlatformCpuAssetTags is set\n"));
+
+ if (CpuAssetTags == NULL) {
+ return;
+ }
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ SocketIndex = 0;
+
+ //
+ // Update CPU Asset Tag string for Socket Populated.
+ //
+ do {
+ GetSmbiosProcessorTypeTable (&SmbiosHandle, NULL);
+ if (SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {
+ return;
+ }
+ CpuAssetTagStrLen = StrLen (CpuAssetTags[SocketIndex]);
+ ASSERT (CpuAssetTagStrLen <= SMBIOS_STRING_MAX_LENGTH);
+ CpuAssetTagStr = AllocatePool (CpuAssetTagStrLen + 1);
+ UnicodeStrToAsciiStr (CpuAssetTags[SocketIndex], CpuAssetTagStr);
+ mSmbios->UpdateString (mSmbios, &SmbiosHandle, &mCpuAssetTagStrNumber, CpuAssetTagStr);
+ FreePool (CpuAssetTagStr);
+ } while ((++SocketIndex) < mPopulatedSocketCount);
+
+}
+
+/**
+ Register notification functions for Pcds related to Smbios Processor Type.
+**/
+VOID
+SmbiosProcessorTypeTableCallback (
+ VOID
+ )
+{
+ UINT32 CpuSocketCount;
+ UINT64 CpuSocketNames;
+ UINT64 CpuAssetTags;
+
+ CpuSocketCount = PcdGet32 (PcdPlatformCpuSocketCount);
+ CpuSocketNames = PcdGet64 (PcdPlatformCpuSocketNames);
+ CpuAssetTags = PcdGet64 (PcdPlatformCpuAssetTags);
+
+ //
+ // PcdPlatformCpuSocketCount, PcdPlatformCpuSocketNames and PcdPlatformCpuAssetTags
+ // have default value 0 in *.dec, check whether they have been set with valid value,
+ // if yes, process them directly, or no, register notification functions for them.
+ //
+ if (CpuSocketCount <= mPopulatedSocketCount) {
+ LibPcdCallbackOnSet (NULL, PcdToken (PcdPlatformCpuSocketCount), CallbackOnPcdPlatformCpuSocketCount);
+ } else {
+ CallbackOnPcdPlatformCpuSocketCount (NULL, PcdToken (PcdPlatformCpuSocketCount), &CpuSocketCount, sizeof (UINT32));
+ }
+ if (CpuSocketNames == 0) {
+ LibPcdCallbackOnSet (NULL, PcdToken (PcdPlatformCpuSocketNames), CallbackOnPcdPlatformCpuSocketNames);
+ } else {
+ CallbackOnPcdPlatformCpuSocketNames (NULL, PcdToken (PcdPlatformCpuSocketNames), &CpuSocketNames, sizeof (UINT64));
+ }
+ if (CpuAssetTags == 0) {
+ LibPcdCallbackOnSet (NULL, PcdToken (PcdPlatformCpuAssetTags), CallbackOnPcdPlatformCpuAssetTags);
+ } else {
+ CallbackOnPcdPlatformCpuAssetTags (NULL, PcdToken (PcdPlatformCpuAssetTags), &CpuAssetTags, sizeof (UINT64));
+ }
+}
+
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SelectLfp.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SelectLfp.c
new file mode 100755
index 0000000..29a345b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SelectLfp.c
@@ -0,0 +1,221 @@
+/** @file
+
+ Code for Selecting Least-Feature Processor as BSP
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: SelectLfp.c
+
+**/
+
+#include "MpService.h"
+#include "Cpu.h"
+
+//
+// Common set of processors' feature flags.
+//
+UINT32 CommonFeatureFlagSet[6];
+//
+// Flags of whether corresponding processor matches common set.
+//
+BOOLEAN MatchingCommonSet[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];
+
+/**
+ Get the common set of processors' feature flags.
+
+ This function calculates the common set of processors' feature flags.
+ Processor's feature flags include 6 segments: CPUID(1).ECX, CPUID(1).EDX,
+ CPUID(0x80000001).EAX, CPUID(0x80000001).EBX, CPUID(0x80000001).ECX,
+ and CPUID(0x80000001).EDX. "AND" them together and result is the common set.
+
+**/
+VOID
+GetCommonFeatureFlagSet (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER *CpuidRegisters;
+ UINTN ProcessorNumber;
+
+ //
+ // Initialize common set of feature flag with all "1"s.
+ //
+ SetMem32 (CommonFeatureFlagSet, sizeof (CommonFeatureFlagSet), 0xffffffff);
+
+ //
+ // Traverse all processors' feature flags
+ //
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+
+ //
+ // AND CPUID(1).ECX and CPUID(1).EDX with common set
+ //
+ CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_VERSION_INFO);
+ ASSERT (CpuidRegisters != NULL);
+ CommonFeatureFlagSet[0] &= CpuidRegisters->RegEcx;
+ CommonFeatureFlagSet[1] &= CpuidRegisters->RegEdx;
+
+ //
+ // AND CPUID(0x80000001).EAX, CPUID(0x80000001).EBX, CPUID(0x80000001).ECX,
+ // and CPUID(0x80000001).EDX with common set.
+ //
+ CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_EXTENDED_CPU_SIG);
+ ASSERT (CpuidRegisters != NULL);
+ CommonFeatureFlagSet[2] &= CpuidRegisters->RegEax;
+ CommonFeatureFlagSet[3] &= CpuidRegisters->RegEbx;
+ CommonFeatureFlagSet[4] &= CpuidRegisters->RegEcx;
+ CommonFeatureFlagSet[5] &= CpuidRegisters->RegEdx;
+ }
+}
+
+/**
+ Checks which processors match the common set of feature flag
+
+ This function Checks which processors match the common set of feature flag.
+
+ @retval TRUE At least one processor matches the common set of feature flag.
+ @retval FALSE No processor matches the common set of feature flag.
+
+**/
+BOOLEAN
+CompareProcessorsWithCommonSet (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER *CpuidRegisters;
+ UINTN ProcessorNumber;
+ BOOLEAN ReturnValue;
+
+ ReturnValue = FALSE;
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+ MatchingCommonSet[ProcessorNumber] = FALSE;
+
+ //
+ // Compare CPUID(1).ECX and CPUID(1).EDX with common set
+ //
+ CpuidRegisters = GetProcessorCpuid (0, EFI_CPUID_VERSION_INFO);
+ ASSERT (CpuidRegisters != NULL);
+ if (CommonFeatureFlagSet[0] != CpuidRegisters->RegEcx || CommonFeatureFlagSet[1] != CpuidRegisters->RegEdx) {
+ continue;
+ }
+
+ //
+ // Compare CPUID(0x80000001).EAX, CPUID(0x80000001).EBX, CPUID(0x80000001).ECX,
+ // and CPUID(0x80000001).EDX with common set.
+ //
+ CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_EXTENDED_CPU_SIG);
+ ASSERT (CpuidRegisters != NULL);
+ if (CommonFeatureFlagSet[2] != CpuidRegisters->RegEax || CommonFeatureFlagSet[3] != CpuidRegisters->RegEbx ||
+ CommonFeatureFlagSet[4] != CpuidRegisters->RegEcx || CommonFeatureFlagSet[5] != CpuidRegisters->RegEdx) {
+ continue;
+ }
+
+ //
+ // If the processor matches common set, flag it, and set return value as TRUE.
+ //
+ MatchingCommonSet[ProcessorNumber] = TRUE;
+ ReturnValue = TRUE;
+ }
+
+ return ReturnValue;
+}
+
+/**
+ Select least-feature processor as BSP
+
+ This function selects least-feature processor as BSP.
+
+**/
+VOID
+SelectLfpAsBsp (
+ VOID
+ )
+{
+ UINTN ProcessorNumber;
+ UINTN OldestProcessorNumber;
+ UINT32 OldestProcessorFms[3];
+ UINT32 FamilyId;
+ UINT32 ModelId;
+ UINT32 SteppingId;
+ BOOLEAN MatchingProcessorExist;
+
+ //
+ // Calculate the common set of processors' feature flags
+ //
+ GetCommonFeatureFlagSet ();
+
+ //
+ // Compare all logical processors with common set.
+ //
+ MatchingProcessorExist = CompareProcessorsWithCommonSet ();
+
+ OldestProcessorFms[2] = 0xffffffff;
+ OldestProcessorFms[1] = 0;
+ OldestProcessorFms[0] = 0;
+ OldestProcessorNumber = mCpuConfigConextBuffer.BspNumber;
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+
+ //
+ // If only 1 processor matches common set, it should be BSP
+ // If more than 1 processors match common set, the one with lowest CPUID should be BSP.
+ // If no processor matches common set, the processor with lowest CPUID should be BSP.
+ //
+ if (!MatchingProcessorExist || MatchingCommonSet[ProcessorNumber]) {
+ GetProcessorVersionInfo (ProcessorNumber, &FamilyId, &ModelId, &SteppingId, NULL);
+
+ if (FamilyId > OldestProcessorFms[2]) {
+ continue;
+ }
+
+ if (FamilyId == OldestProcessorFms[2]) {
+ if (ModelId > OldestProcessorFms[1]) {
+ continue;
+ }
+ if (ModelId == OldestProcessorFms[1]) {
+ if (SteppingId >= OldestProcessorFms[0]) {
+ continue;
+ }
+ }
+ }
+
+ OldestProcessorFms[2] = FamilyId;
+ OldestProcessorFms[1] = ModelId;
+ OldestProcessorFms[0] = SteppingId;
+ OldestProcessorNumber = ProcessorNumber;
+ }
+ }
+
+ //
+ // If current BSP is not the least-feature processor, then switch BSP.
+ //
+ if (OldestProcessorNumber != mCpuConfigConextBuffer.BspNumber) {
+ SwitchBSP (&mMpService, OldestProcessorNumber, TRUE);
+ DEBUG ((EFI_D_INFO, "BSP switched to processor: %8d\r\n", OldestProcessorNumber));
+ }
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Setting.c b/IA32FamilyCpuBasePkg/CpuMpDxe/Setting.c
new file mode 100644
index 0000000..20b3141
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Setting.c
@@ -0,0 +1,351 @@
+/** @file
+ Code for Setting phase.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Setting.c
+
+**/
+
+#include "Cpu.h"
+#include "MpService.h"
+#include "CpuOnlyReset.h"
+
+BOOLEAN mRestoreSettingAfterInit = FALSE;
+BOOLEAN mSetBeforeCpuOnlyReset;
+
+/**
+ Programs registers for the calling processor.
+
+ This function programs registers for the calling processor.
+
+ @param PreSmmInit Specify the target register table.
+ If TRUE, the target is the pre-SMM-init register table.
+ If FALSE, the target is the post-SMM-init register table.
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+SetProcessorRegisterEx (
+ IN BOOLEAN PreSmmInit,
+ IN UINTN ProcessorNumber
+ )
+{
+ CPU_REGISTER_TABLE *RegisterTable;
+ CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
+ UINTN Index;
+ UINTN Value;
+ UINTN StartIndex;
+ UINTN EndIndex;
+
+ if (PreSmmInit) {
+ RegisterTable = &mCpuConfigConextBuffer.PreSmmInitRegisterTable[ProcessorNumber];
+ } else {
+ RegisterTable = &mCpuConfigConextBuffer.RegisterTable[ProcessorNumber];
+ }
+
+ //
+ // If microcode patch has been applied, then the first register table entry
+ // is for microcode upate, so it is skipped.
+ //
+ StartIndex = 0;
+
+ if (mSetBeforeCpuOnlyReset) {
+ EndIndex = StartIndex + RegisterTable->NumberBeforeReset;
+ } else {
+ StartIndex += RegisterTable->NumberBeforeReset;
+ EndIndex = RegisterTable->TableLength;
+ }
+
+ //
+ // Traverse Register Table of this logical processor
+ //
+ for (Index = StartIndex; Index < EndIndex; Index++) {
+
+ RegisterTableEntry = &RegisterTable->RegisterTableEntry[Index];
+
+ //
+ // Check the type of specified register
+ //
+ switch (RegisterTableEntry->RegisterType) {
+ //
+ // The specified register is Control Register
+ //
+ case ControlRegister:
+ switch (RegisterTableEntry->Index) {
+ case 0:
+ Value = AsmReadCr0 ();
+ Value = (UINTN) BitFieldWrite64 (
+ Value,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ RegisterTableEntry->Value
+ );
+ AsmWriteCr0 (Value);
+ break;
+ case 2:
+ Value = AsmReadCr2 ();
+ Value = (UINTN) BitFieldWrite64 (
+ Value,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ RegisterTableEntry->Value
+ );
+ AsmWriteCr2 (Value);
+ break;
+ case 3:
+ Value = AsmReadCr3 ();
+ Value = (UINTN) BitFieldWrite64 (
+ Value,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ RegisterTableEntry->Value
+ );
+ AsmWriteCr3 (Value);
+ break;
+ case 4:
+ Value = AsmReadCr4 ();
+ Value = (UINTN) BitFieldWrite64 (
+ Value,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ RegisterTableEntry->Value
+ );
+ AsmWriteCr4 (Value);
+ break;
+ case 8:
+ //
+ // Do we need to support CR8?
+ //
+ break;
+ default:
+ break;
+ }
+ break;
+ //
+ // The specified register is Model Specific Register
+ //
+ case Msr:
+ //
+ // If this function is called to restore register setting after INIT signal,
+ // there is no need to restore MSRs in register table.
+ //
+ if (!mRestoreSettingAfterInit) {
+ if (RegisterTableEntry->ValidBitLength >= 64) {
+ //
+ // If length is not less than 64 bits, then directly write without reading
+ //
+ AsmWriteMsr64 (
+ RegisterTableEntry->Index,
+ RegisterTableEntry->Value
+ );
+ } else {
+ //
+ // Set the bit section according to bit start and length
+ //
+ AsmMsrBitFieldWrite64 (
+ RegisterTableEntry->Index,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ RegisterTableEntry->Value
+ );
+ }
+ }
+ break;
+ //
+ // Enable or disable cache
+ //
+ case CacheControl:
+ //
+ // If value of the entry is 0, then disable cache. Otherwise, enable cache.
+ //
+ if (RegisterTableEntry->Value == 0) {
+ AsmDisableCache ();
+ } else {
+ AsmEnableCache ();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ Programs registers after SMM initialization for the calling processor.
+
+ This function programs registers after SMM initialization for the calling processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+SetProcessorRegister (
+ IN UINTN ProcessorNumber
+ )
+{
+ SetProcessorRegisterEx (FALSE, ProcessorNumber);
+}
+
+/**
+ Programs registers before SMM initialization for the calling processor.
+
+ This function programs registers before SMM initialization for the calling processor.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+
+**/
+VOID
+SetPreSmmInitProcessorRegister (
+ IN UINTN ProcessorNumber
+ )
+{
+ SetProcessorRegisterEx (TRUE, ProcessorNumber);
+}
+
+/**
+ Triggers CPU-only reset and restores processor environment.
+
+ This function triggers CPU-only reset and restores processor environment.
+
+**/
+VOID
+CpuOnlyResetAndRestore (
+ VOID
+ )
+{
+ MTRR_SETTINGS MtrrSetting;
+
+ MtrrGetAllMtrrs (&MtrrSetting);
+
+ InitiateCpuOnlyReset ();
+
+ DispatchAPAndWait (
+ TRUE,
+ 0,
+ EarlyMpInit
+ );
+
+ EarlyMpInit (mCpuConfigConextBuffer.BspNumber);
+
+ ProgramVirtualWireMode ();
+}
+
+/**
+ Programs processor registers according to register tables.
+
+ This function programs processor registers according to register tables.
+
+**/
+VOID
+SettingPhase (
+ VOID
+ )
+{
+ UINT8 CallbackSignalValue;
+ UINTN Index;
+ UINTN ProcessorNumber;
+ CPU_REGISTER_TABLE *RegisterTable;
+ BOOLEAN NeedCpuOnlyReset;
+
+ //
+ // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back.
+ //
+ CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_PROCESSOR_SETTING_SIGNAL);
+ //
+ // Checks whether the callback function requests to bypass Setting phase.
+ //
+ if (CallbackSignalValue == CPU_BYPASS_SIGNAL) {
+ return;
+ }
+
+ //
+ // Check if CPU-only reset is needed
+ //
+ NeedCpuOnlyReset = FALSE;
+ for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {
+ RegisterTable = &mCpuConfigConextBuffer.RegisterTable[Index];
+ if (RegisterTable->NumberBeforeReset > 0) {
+ NeedCpuOnlyReset = TRUE;
+ break;
+ }
+ }
+
+ //
+ // if CPU-only reset is needed, then program corresponding registers, and
+ // trigger CPU-only reset.
+ //
+ if (NeedCpuOnlyReset) {
+ mSetBeforeCpuOnlyReset = TRUE;
+ DispatchAPAndWait (
+ TRUE,
+ 0,
+ SetProcessorRegister
+ );
+
+ SetProcessorRegister (mCpuConfigConextBuffer.BspNumber);
+
+ CpuOnlyResetAndRestore ();
+ }
+
+ //
+ // Program processors' registers in sequential mode.
+ //
+ mSetBeforeCpuOnlyReset = FALSE;
+ for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {
+
+ ProcessorNumber = mCpuConfigConextBuffer.SettingSequence[Index];
+
+ if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {
+ SetProcessorRegister (ProcessorNumber);
+ } else {
+
+ DispatchAPAndWait (
+ FALSE,
+ GET_CPU_MISC_DATA (ProcessorNumber, ApicID),
+ SetProcessorRegister
+ );
+ }
+
+ RegisterTable = &mCpuConfigConextBuffer.RegisterTable[ProcessorNumber];
+ RegisterTable->InitialApicId = GetInitialLocalApicId (ProcessorNumber);
+ }
+ //
+ // Set PcdCpuCallbackSignal to trigger callback function
+ //
+ PcdSet8 (PcdCpuCallbackSignal, CPU_PROCESSOR_SETTING_END_SIGNAL);
+
+ //
+ // From now on, SetProcessorRegister() will be called only by SimpleApProcWrapper()
+ // and ApProcWrapper to restore register settings after INIT signal, so switch
+ // this flag from FALSE to TRUE.
+ //
+ mRestoreSettingAfterInit = TRUE;
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Strings.uni b/IA32FamilyCpuBasePkg/CpuMpDxe/Strings.uni
new file mode 100644
index 0000000..8478d3e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Strings.uni
Binary files differ
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.c b/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.c
new file mode 100644
index 0000000..4571684
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.c
@@ -0,0 +1,167 @@
+/** @file
+
+ Code for Execute Disable Bit Feature
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Xd.c
+
+**/
+
+#include "Xd.h"
+
+BOOLEAN EnableExecuteDisableBit[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];
+
+/**
+ Detect capability of XD feature for specified processor.
+
+ This function detects capability of XD feature for specified processor.
+
+ @param ProcessorNumber The handle number of specified processor.
+
+**/
+VOID
+XdDetect (
+ UINTN ProcessorNumber
+ )
+{
+ EFI_CPUID_REGISTER *CpuidRegisters;
+
+ //
+ // Check whether 0x80000001 is supported by CPUID
+ //
+ if (GetNumberOfCpuidLeafs (ProcessorNumber, ExtendedCpuidLeaf) > 2) {
+ //
+ // Check CPUID(0x80000001).EDX[20]
+ //
+ CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_EXTENDED_CPU_SIG);
+ ASSERT (CpuidRegisters != NULL);
+
+ if (BitFieldRead32 (CpuidRegisters->RegEdx, N_CPUID_XD_BIT_AVAILABLE, N_CPUID_XD_BIT_AVAILABLE) == 1) {
+ SetProcessorFeatureCapability (ProcessorNumber, ExecuteDisableBit, NULL);
+ }
+ }
+}
+
+/**
+ Configures Processor Feature Lists for XD feature for all processors.
+
+ This function configures Processor Feature Lists for XD feature for all processors.
+
+**/
+VOID
+XdConfigFeatureList (
+ VOID
+ )
+{
+ UINTN ProcessorNumber;
+ BOOLEAN XdSupported;
+ BOOLEAN Setting;
+
+ XdSupported = TRUE;
+ Setting = FALSE;
+
+ //
+ // Check whether all logical processors support XD
+ //
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+ if (!GetProcessorFeatureCapability (ProcessorNumber, ExecuteDisableBit, NULL)) {
+ XdSupported = FALSE;
+ break;
+ }
+ }
+
+ if (XdSupported) {
+ //
+ // Set the bit of XD capability
+ //
+ PcdSet32 (PcdCpuProcessorFeatureCapability, PcdGet32 (PcdCpuProcessorFeatureCapability) | PCD_CPU_EXECUTE_DISABLE_BIT);
+ //
+ // Checks whether user indicates to enable XD
+ //
+ if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_EXECUTE_DISABLE_BIT) != 0) {
+ //
+ // Set the bit of XD setting
+ //
+ PcdSet32 (PcdCpuProcessorFeatureSetting, PcdGet32 (PcdCpuProcessorFeatureSetting) | PCD_CPU_EXECUTE_DISABLE_BIT);
+ Setting = TRUE;
+ }
+ }
+
+ //
+ // If XD is not supported by all logical processors, or user indicates to disable XD, then disable XD on all processors.
+ //
+ for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {
+ //
+ // The operation can only be performed on the processors supporting XD feature.
+ //
+ if (GetProcessorFeatureCapability (ProcessorNumber, ExecuteDisableBit, NULL)) {
+ EnableExecuteDisableBit[ProcessorNumber] = Setting;
+ AppendProcessorFeatureIntoList (ProcessorNumber, ExecuteDisableBit, &(EnableExecuteDisableBit[ProcessorNumber]));
+ }
+ }
+}
+
+/**
+ Produces entry of XD feature in Register Table for specified processor.
+
+ This function produces entry of XD feature in Register Table for specified processor.
+
+ @param ProcessorNumber The handle number of specified processor.
+ @param Attribute Pointer to the attribute
+
+**/
+VOID
+XdReg (
+ UINTN ProcessorNumber,
+ VOID *Attribute
+ )
+{
+ BOOLEAN *Enable;
+ UINT64 Value;
+
+ //
+ // If Attribute is TRUE, then write 0 to MSR_IA32_MISC_ENABLE[34].
+ // Otherwise, write 1 to the bit.
+ //
+ Enable = (BOOLEAN *) Attribute;
+ Value = 1;
+ if (*Enable) {
+ Value = 0;
+ }
+
+ WriteRegisterTable (
+ ProcessorNumber,
+ Msr,
+ MSR_IA32_MISC_ENABLE,
+ N_MSR_XD_BIT_DISABLE,
+ 1,
+ Value
+ );
+}
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.h b/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.h
new file mode 100644
index 0000000..bcaa422
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.h
@@ -0,0 +1,82 @@
+/** @file
+
+ Include file for Execute Disable Bit Feature
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: Xd.h
+
+**/
+
+#ifndef _CPU_XD_H_
+#define _CPU_XD_H_
+
+#include "MpCommon.h"
+#include "Cpu.h"
+
+/**
+ Detect capability of XD feature for specified processor.
+
+ This function detects capability of XD feature for specified processor.
+
+ @param ProcessorNumber The handle number of specified processor.
+
+**/
+VOID
+XdDetect (
+ UINTN ProcessorNumber
+ );
+
+/**
+ Configures Processor Feature Lists for XD feature for all processors.
+
+ This function configures Processor Feature Lists for XD feature for all processors.
+
+**/
+VOID
+XdConfigFeatureList (
+ VOID
+ );
+
+/**
+ Produces entry of XD feature in Register Table for specified processor.
+
+ This function produces entry of XD feature in Register Table for specified processor.
+
+ @param ProcessorNumber The handle number of specified processor.
+ @param Attribute Pointer to the attribute
+
+**/
+VOID
+XdReg (
+ UINTN ProcessorNumber,
+ VOID *Attribute
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuPei/Bist.c b/IA32FamilyCpuBasePkg/CpuPei/Bist.c
new file mode 100644
index 0000000..6c0507c
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/Bist.c
@@ -0,0 +1,198 @@
+/** @file
+Implementation of CPU driver for PEI phase.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name: Bist.c
+
+**/
+
+#include "CpuPei.h"
+#include "Bist.h"
+
+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
+
+ Implementation of the PlatformInformation service in EFI_SEC_PLATFORM_INFORMATION_PPI.
+ This function will parse SecPlatform Information from BIST Hob.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param StructureSize Pointer to the variable describing size of the input buffer.
+ @param 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 CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ VOID *DataInHob;
+ UINTN DataSize;
+
+ GuidHob = GetFirstGuidHob (&gEfiHtBistHobGuid);
+ if (GuidHob == NULL) {
+ *StructureSize = 0;
+ return EFI_SUCCESS;
+ }
+
+ DataInHob = GET_GUID_HOB_DATA (GuidHob);
+ DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+
+ //
+ // return the information from BistHob
+ //
+ if ((*StructureSize) < (UINT64) DataSize) {
+ *StructureSize = (UINT64) DataSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *StructureSize = (UINT64) DataSize;
+
+ CopyMem (PlatformInformationRecord, DataInHob, DataSize);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ A callback function to build CPU(only BSP) BIST.
+
+ This function is a callback function to build bsp's BIST by calling SecPlatformInformationPpi
+
+ @param PeiServices Pointer to PEI Services Table
+ @param NotifyDescriptor Address if the notification descriptor data structure
+ @param Ppi Address of the PPI that was installed
+ @retval EFI_SUCCESS Retrieve of the BIST data successfully
+ @retval EFI_SUCCESS No sec platform information ppi export
+ @retval EFI_SUCCESS The boot mode is S3 path
+**/
+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;
+ EFI_PEI_PPI_DESCRIPTOR *SecInformationDescriptor;
+ UINT64 InformationSize;
+ EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformation;
+
+ Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);
+ if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {
+ return EFI_SUCCESS;
+ }
+
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gEfiSecPlatformInformationPpiGuid, // GUID
+ 0, // INSTANCE
+ &SecInformationDescriptor, // EFI_PEI_PPI_DESCRIPTOR
+ &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 = (*PeiServices)->AllocatePool (
+ PeiServices,
+ (UINTN) InformationSize,
+ &SecPlatformInformation
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SecPlatformInformationPpi->PlatformInformation (
+ PeiServices,
+ &InformationSize,
+ SecPlatformInformation
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BuildGuidDataHob (
+ &gEfiHtBistHobGuid,
+ SecPlatformInformation,
+ (UINTN) InformationSize
+ );
+
+ //
+ // The old SecPlatformInformation Ppi is on CAR.
+ // After memory discovered, we should never get it from CAR, or the data will be crashed.
+ // So, we reinstall SecPlatformInformation PPI here.
+ //
+ Status = (*PeiServices)->ReInstallPpi (
+ PeiServices,
+ SecInformationDescriptor,
+ &mPeiSecPlatformInformationPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
diff --git a/IA32FamilyCpuBasePkg/CpuPei/Bist.h b/IA32FamilyCpuBasePkg/CpuPei/Bist.h
new file mode 100644
index 0000000..01b8b40
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/Bist.h
@@ -0,0 +1,82 @@
+/** @file
+Implementation of CPU driver for PEI phase.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name: Bist.h
+
+**/
+
+#ifndef _CPU_BIST_H_
+#define _CPU_BIST_H_
+
+/**
+
+ Implementation of the PlatformInformation service
+
+ Implementation of the PlatformInformation service in EFI_SEC_PLATFORM_INFORMATION_PPI.
+ This function will parse SecPlatform Information from BIST Hob.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param StructureSize Pointer to the variable describing size of the input buffer.
+ @param 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 CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ );
+
+/**
+ A callback function to build CPU(only BSP) BIST.
+
+ This function is a callback function to build bsp's BIST by calling SecPlatformInformationPpi
+
+ @param PeiServices Pointer to PEI Services Table
+ @param NotifyDescriptor Address if the notification descriptor data structure
+ @param Ppi Address of the PPI that was installed
+ @retval EFI_SUCCESS Retrieve of the BIST data successfully
+ @retval EFI_SUCCESS No sec platform information ppi export
+ @retval EFI_SUCCESS The boot mode is S3 path
+**/
+EFI_STATUS
+EFIAPI
+BuildBistHob (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuPei/Cache.c b/IA32FamilyCpuBasePkg/CpuPei/Cache.c
new file mode 100644
index 0000000..2ad5223
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/Cache.c
@@ -0,0 +1,156 @@
+/** @file
+Implementation of CPU driver for PEI phase.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name: Cache.c
+
+**/
+
+#include "CpuPei.h"
+
+/**
+ Reset all the MTRRs to a known state.
+
+ This function provides the PPI for PEI phase to Reset all the MTRRs to a known state(UC)
+ @param PeiServices General purpose services available to every PEIM.
+ @param This Current instance of 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
+ );
+
+/**
+ program the MTRR according to the given range and cache type.
+
+ This function provides the PPI for PEI phase to set the memory attribute by program
+ the MTRR according to the given range and cache type. Actually this function is a
+ wrapper of the MTRR libaray to suit the PEI_CACHE_PPI interface
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This Current instance of Pei Cache PPI.
+ @param MemoryAddress Base Address of Memory to program MTRR.
+ @param MemoryLength Length of Memory to program MTRR.
+ @param 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
+ );
+
+PEI_CACHE_PPI mCachePpi = {
+ PeiSetCacheAttributes,
+ PeiResetCacheAttributes
+};
+
+
+/**
+ program the MTRR according to the given range and cache type.
+
+ This function provides the PPI for PEI phase to set the memory attribute by program
+ the MTRR according to the given range and cache type. Actually this function is a
+ wrapper of the MTRR libaray to suit the PEI_CACHE_PPI interface
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This Current instance of Pei Cache PPI.
+ @param MemoryAddress Base Address of Memory to program MTRR.
+ @param MemoryLength Length of Memory to program MTRR.
+ @param 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
+ )
+{
+
+ RETURN_STATUS Status;
+ //
+ // call MTRR libary function
+ //
+ Status = MtrrSetMemoryAttribute(
+ MemoryAddress,
+ MemoryLength,
+ (MTRR_MEMORY_CACHE_TYPE) MemoryCacheType
+ );
+ return (EFI_STATUS)Status;
+}
+/**
+ Reset all the MTRRs to a known state.
+
+ This function provides the PPI for PEI phase to Reset all the MTRRs to a known state(UC)
+ @param PeiServices General purpose services available to every PEIM.
+ @param This Current instance of 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
+ )
+{
+
+ MTRR_SETTINGS ZeroMtrr;
+
+ //
+ // reset all Mtrrs to 0 include fixed MTRR and variable MTRR
+ //
+ ZeroMem(&ZeroMtrr, sizeof(MTRR_SETTINGS));
+ MtrrSetAllMtrrs(&ZeroMtrr);
+
+ return EFI_SUCCESS;
+}
diff --git a/IA32FamilyCpuBasePkg/CpuPei/CpuPei.h b/IA32FamilyCpuBasePkg/CpuPei/CpuPei.h
new file mode 100644
index 0000000..53da573
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/CpuPei.h
@@ -0,0 +1,58 @@
+/** @file
+Implementation of CPU driver for PEI phase.
+
+This PEIM is to expose the CPUIO ppi, Cache Ppi and BIST hob build notification
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _PEI_CPUPEIM_H_
+#define _PEI_CPUPEIM_H_
+
+
+#include <PiPei.h>
+
+#include <Ppi/Cache.h>
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/SecPlatformInformation.h>
+#include <Guid/HtBistHob.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/PcdLib.h>
+#include <Library/SocketLga775Lib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf b/IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
new file mode 100644
index 0000000..50f06ca
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
@@ -0,0 +1,85 @@
+## @file
+# Implementation of CPU driver for PEI phase.
+#
+# This PEIM is to expose the CPUIO ppi, Cache Ppi and BIST hob build notification
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuPei
+ FILE_GUID = 01359D99-9446-456d-ADA4-50A711C03ADA
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = CpuPeimInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+# HOB Guid C Name: gEfiHtBistHobGuid Hob Type: GUID_EXTENSION
+#
+
+[Sources]
+ Bist.h
+ Bist.c
+ Cache.c
+ CpuPei.h
+ CpuPeim.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MtrrLib
+ HobLib
+ BaseMemoryLib
+ PeiServicesLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ ReportStatusCodeLib
+
+[Guids]
+ gEfiHtBistHobGuid # ALWAYS_CONSUMED
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid # PPI_NOTIFY SOMETIMES_CONSUMED
+ gEfiSecPlatformInformationPpiGuid # PPI SOMETIMES_CONSUMED
+ gPeiCachePpiGuid # PPI ALWAYS_PRODUCED
+
+[Depex]
+ TRUE
+ \ No newline at end of file
diff --git a/IA32FamilyCpuBasePkg/CpuPei/CpuPeim.c b/IA32FamilyCpuBasePkg/CpuPei/CpuPeim.c
new file mode 100644
index 0000000..e2b6ceb
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/CpuPeim.c
@@ -0,0 +1,141 @@
+/** @file
+Implementation of CPU driver for PEI phase.
+
+This PEIM is to expose the Cache Ppi and BIST hob build notification
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name: CpuPeim.c
+
+**/
+
+#include "CpuPei.h"
+#include "Bist.h"
+
+extern PEI_CACHE_PPI mCachePpi;
+//
+// Ppis to be installed
+//
+EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiCachePpiGuid,
+ &mCachePpi
+ }
+};
+
+//
+// Notification to build BIST information
+//
+STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMasterBootModePpiGuid,
+ BuildBistHob
+ }
+};
+
+/**
+ Initialize SSE support.
+**/
+VOID
+InitXMM (
+ VOID
+ )
+{
+
+ UINT32 RegEdx;
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
+
+ //
+ //Check whether SSE2 is supported
+ //
+ if ((RegEdx & BIT26) == 0) {
+ AsmWriteCr0 (AsmReadCr0 () | BIT1);
+ AsmWriteCr4 (AsmReadCr4 () | BIT9 | BIT10);
+ }
+}
+
+
+/**
+ The Entry point of the CPU PEIM
+
+ This function is the Entry point of the CPU PEIM which will install the CachePpi and
+ BuildBISTHob notifier. And also the function will deal with the relocation to memory when
+ permanent memory is ready
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS CachePpi and BIST hob build notification is installed
+ successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuPeimInit (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Report Status Code to indicate the start of CPU PEIM
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR + EFI_CU_HP_PC_POWER_ON_INIT
+ );
+
+ //
+ // Install PPIs
+ //
+ Status = PeiServicesInstallPpi(&mPpiList[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for PPI Notifications
+ //
+ Status = PeiServicesNotifyPpi (&mNotifyList[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Report Status Code to indicate the start of CPU PEI initialization
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR + EFI_CU_PC_INIT_BEGIN
+ );
+
+ InitXMM ();
+
+ return Status;
+}
diff --git a/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec b/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
new file mode 100644
index 0000000..629185b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
@@ -0,0 +1,144 @@
+## @file
+# Package for support of IA32 family processors
+#
+# This package supports IA32 family processors, with CPU DXE module, CPU PEIM, CPU S3 module,
+# SMM modules, related libraries, and corresponding definitions.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = IA32FamilyCpuBasePkg
+ PACKAGE_GUID = 6E0E3B55-5650-4265-A4D9-849D19D6D609
+ PACKAGE_VERSION = 0.4
+
+[Includes]
+ Include
+
+[LibraryClasses]
+ CpuConfigLib|Include/Library/CpuConfigLib.h
+ CpuOnlyResetLib|Include/Library/CpuOnlyResetLib.h
+ PlatformSecLib|Include/Library/PlatformSecLib.h
+ Socket775LgaLib|Include/Library/SocketLga775Lib.h
+ SmmCpuPlatformHookLib|Include/Library/SmmCpuPlatformHookLib.h
+
+[Guids]
+ gEfiHtBistHobGuid = { 0xBE644001, 0xE7D4, 0x48B1, { 0xB0, 0x96, 0x8B, 0xA0, 0x47, 0xBC, 0x7A, 0xE7 }}
+ gEfiCpuTokenSpaceGuid = { 0x2ADA836D, 0x0A3D, 0x43D6, { 0xA2, 0x5A, 0x38, 0x45, 0xCA, 0xD2, 0xD4, 0x00 }}
+
+[Ppis]
+ gPeiCachePpiGuid = { 0xC153205A, 0xE898, 0x4C24, { 0x86, 0x89, 0xA4, 0xB4, 0xBC, 0xC5, 0xC8, 0xA2 }}
+
+[Protocols]
+ gSmmCpuSyncProtocolGuid = { 0xd5950985, 0x8be3, 0x4b1c, { 0xb6, 0x3f, 0x95, 0xd1, 0x5a, 0xb3, 0xb6, 0x5f }}
+ gSmmCpuSync2ProtocolGuid = { 0x9db72e22, 0x9262, 0x4a18, { 0x8f, 0xe0, 0x85, 0xe0, 0x3d, 0xfa, 0x96, 0x73 }}
+ gEfiSmmCpuServiceProtocolGuid = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }}
+
+[PcdsFeatureFlag]
+ gEfiCpuTokenSpaceGuid.PcdCpuMaxCpuIDValueLimitFlag|TRUE|BOOLEAN|0x10000008
+ gEfiCpuTokenSpaceGuid.PcdCpuSelectLfpAsBspFlag|FALSE|BOOLEAN|0x1000000F
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmEnableBspElection|TRUE|BOOLEAN|0x32132106
+ gEfiCpuTokenSpaceGuid.PcdCpuExecuteDisableBitFlag|TRUE|BOOLEAN|0x10000009
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmDebug|FALSE|BOOLEAN|0x1000001B
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmStackGuard|FALSE|BOOLEAN|0x1000001C
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp|FALSE|BOOLEAN|0x32132108
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileEnable|FALSE|BOOLEAN|0x32132109
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileRingBuffer|FALSE|BOOLEAN|0x3213210a
+
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmUncacheCpuSyncData|FALSE|BOOLEAN|0x3213210D
+ gEfiCpuTokenSpaceGuid.PcdCpuHotPlugSupport|FALSE|BOOLEAN|0x3213210C
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock|TRUE|BOOLEAN|0x3213210B
+
+[PcdsFixedAtBuild]
+ gEfiCpuTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|64|UINT32|0x30000002
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmApSyncTimeout|1000000|UINT64|0x32132104
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmStackSize|0x2000|UINT32|0x32132105
+ ##
+ # The PCD is used to specify memory size with bytes to save SMM profile data.
+ # The value should be a multiple of 4KB.
+ ##
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileSize|0x200000|UINT32|0x32132107
+
+ ##
+ # Maximum number of Ppi is provided by SecCore.
+ ##
+ gEfiCpuTokenSpaceGuid.PcdSecCoreMaxPpiSupported|0x6|UINT32|0x10001010
+ gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0xfef00000|UINT32|0x10001001
+ gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x2000|UINT32|0x10001002
+ gEfiCpuTokenSpaceGuid.PcdSecMaximumNumberOfProcessors|1|UINT32|0x10001000
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+ ## Stack size in the temporary RAM.
+ # 0 means half of TemporaryRamSize.
+ gEfiCpuTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0|UINT32|0x10001003
+
+[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
+ gEfiCpuTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000|UINT32|0x30000001
+ gEfiCpuTokenSpaceGuid.PcdCpuApStackSize|0x8000|UINT32|0x30000003
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfiguration|0|UINT32|0x40000001
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfigurationEx1|0|UINT32|0x40000006
+ gEfiCpuTokenSpaceGuid.PcdPlatformHighPowerLoadLineSupport|TRUE|BOOLEAN|0x60000001
+ gEfiCpuTokenSpaceGuid.PcdPlatformDynamicVidSupport|TRUE|BOOLEAN|0x60000002
+ gEfiCpuTokenSpaceGuid.PcdPlatformType|0|UINT8|0x60000003
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxCoreFrequency|0x0|UINT32|0x60000004
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxFsbFrequency|0x0|UINT32|0x60000005
+ ## Base address of the LVL_2 register visible to software.
+ # 16-bit IO port address.
+ gEfiCpuTokenSpaceGuid.PcdCpuAcpiLvl2Addr|0x0|UINT16|0x60008001
+ ## This PCD specifies the AP wait loop mode during POST.
+ # The value is defined as below.
+ # 1: ApInHltLoop, AP is in the Hlt-Loop state.
+ # 2: ApInMwaitLoop, AP is in the Mwait-Loop state.
+ # 3: ApInRunLoop, AP is in the Run-Loop state.
+ gEfiCpuTokenSpaceGuid.PcdCpuApLoopMode|1|UINT8|0x60008006
+
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable|TRUE|BOOLEAN|0x60000013
+ ## This PCD specifies the TCC Activation Offset value
+ gEfiCpuTokenSpaceGuid.PcdCpuTccActivationOffset|0|UINT8|0x6000001B
+
+[PcdsDynamic, PcdsDynamicEx]
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapability|0|UINT32|0x40000002
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSetting|0|UINT32|0x40000003
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapabilityEx1|0|UINT32|0x40000004
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSettingEx1|0|UINT32|0x40000005
+ gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer|0x0|UINT64|0x50000001
+ gEfiCpuTokenSpaceGuid.PcdCpuCallbackSignal|0x0|UINT8|0x50000002
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuFrequencyLists|0x0|UINT64|0x60000006
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketCount|0x0|UINT32|0x60000012
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames|0x0|UINT64|0x60000007
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags|0x0|UINT64|0x60000008
+ gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset|FALSE|BOOLEAN|0x6000000F
+ gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress|0x0|UINT64|0x6000000E
+ gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress|0x0|UINT64|0x6000000D
+ gEfiCpuTokenSpaceGuid.PcdCpuS3DataAddress|0x0|UINT64|0x60000010
+ gEfiCpuTokenSpaceGuid.PcdCpuSocketId|{0}|VOID*|0x60008007
+ gEfiCpuTokenSpaceGuid.PcdCpuHotPlugDataAddress|0x0|UINT64|0x60000011
+
diff --git a/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dsc b/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dsc
new file mode 100644
index 0000000..e60defa
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dsc
@@ -0,0 +1,207 @@
+## @file
+# Package description file for IA32FamilyCpuBasePkg.
+#
+# This DSC file is used for Package Level build.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = IA32FamilyCpuBasePkg
+ PLATFORM_GUID = 54BABF97-1B9B-4fe0-847E-AFA0DF0F26F9
+ PLATFORM_VERSION = 0.4
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/IA32FamilyCpuBasePkg
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this
+# Platform.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
+
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+[LibraryClasses]
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ CpuOnlyResetLib|IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf
+ PlatformSecLib|IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+ SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf
+ MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ CpuConfigLib|IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf
+ S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf
+ S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ SmmLib|MdePkg/Library/SmmLibNull/SmmLibNull.inf
+ LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+
+[LibraryClasses.common.PEIM]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ SmbusLib|MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+
+[LibraryClasses.common.DXE_SMM_DRIVER]
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+ SmmCpuPlatformHookLib|IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+[PcdsFeatureFlag]
+ gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
+ gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE
+ gEfiCpuTokenSpaceGuid.PcdCpuSelectLfpAsBspFlag|TRUE
+
+[PcdsFixedAtBuild]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxFsbFrequency|1066
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxCoreFrequency|3800
+
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault.common.DEFAULT]
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfiguration|0xffffffff
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapability|0
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSetting|0
+ gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer|0
+ gEfiCpuTokenSpaceGuid.PcdCpuCallbackSignal|0
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuFrequencyLists|0
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames|0
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags|0
+ gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress|0
+ gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress|0
+ gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset|FALSE
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+# into firmware volume images. This section is just a list of modules to compile from
+# source into UEFI-compliant binaries.
+# It is the FDF file that contains information on combining binary files into firmware
+# volume images, whose concept is beyond UEFI and is described in PI specification.
+# Binary modules do not need to be listed in this section, as they should be
+# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
+# Logo (Logo.bmp), and etc.
+# There may also be modules listed in this section that are not required in the FDF file,
+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+# generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
+
+[Components]
+ IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf
+ IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.inf
+ IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf
+ IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
+ IA32FamilyCpuBasePkg/SecCore/SecCore.inf
+ IA32FamilyCpuBasePkg/SecCore/Vtf0SecCore.inf
+ IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf
+ IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf
+ IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
+ IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+ IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf
+ IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
+
diff --git a/IA32FamilyCpuBasePkg/Include/AcpiCpuData.h b/IA32FamilyCpuBasePkg/Include/AcpiCpuData.h
new file mode 100644
index 0000000..371996a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/AcpiCpuData.h
@@ -0,0 +1,53 @@
+/** @file
+ Definitions for CPU S3 data.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _ACPI_CPU_DATA_H_
+#define _ACPI_CPU_DATA_H_
+
+typedef struct {
+ BOOLEAN APState;
+ EFI_PHYSICAL_ADDRESS StartupVector;
+ EFI_PHYSICAL_ADDRESS GdtrProfile;
+ EFI_PHYSICAL_ADDRESS IdtrProfile;
+ EFI_PHYSICAL_ADDRESS StackAddress;
+ UINT32 StackSize;
+ UINT32 NumberOfCpus;
+ EFI_PHYSICAL_ADDRESS MtrrTable;
+ EFI_PHYSICAL_ADDRESS PreSmmInitRegisterTable;
+ EFI_PHYSICAL_ADDRESS RegisterTable;
+ EFI_PHYSICAL_ADDRESS ApMachineCheckHandlerBase;
+ UINT32 ApMachineCheckHandlerSize;
+} ACPI_CPU_DATA;
+
+#endif
+
diff --git a/IA32FamilyCpuBasePkg/Include/CpuHotPlugData.h b/IA32FamilyCpuBasePkg/Include/CpuHotPlugData.h
new file mode 100644
index 0000000..aa4e638
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/CpuHotPlugData.h
@@ -0,0 +1,52 @@
+/** @file
+ Definition for a struture sharing information for CPU hot plug.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef _CPU_HOT_PLUG_DATA_H_
+#define _CPU_HOT_PLUG_DATA_H_
+
+typedef struct {
+ //
+ // Placeholder for MP intialization data
+ //
+
+ //
+ // Data required for SMBASE relocation
+ //
+ UINT64 ApicId[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+ UINTN SmBase[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+ UINT32 SmrrBase;
+ UINT32 SmrrSize;
+
+} CPU_HOT_PLUG_DATA;
+
+#endif
+
diff --git a/IA32FamilyCpuBasePkg/Include/Guid/HtBistHob.h b/IA32FamilyCpuBasePkg/Include/Guid/HtBistHob.h
new file mode 100644
index 0000000..08aa3fa
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Guid/HtBistHob.h
@@ -0,0 +1,52 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ HtBistHob.h
+
+Abstract:
+
+ GUID used for HT BIST Status HOB entries in the HOB list.
+
+**/
+
+#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/IA32FamilyCpuBasePkg/Include/Guid/IA32FamilyCpuPkgTokenSpace.h b/IA32FamilyCpuBasePkg/Include/Guid/IA32FamilyCpuPkgTokenSpace.h
new file mode 100644
index 0000000..ca24575
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Guid/IA32FamilyCpuPkgTokenSpace.h
@@ -0,0 +1,44 @@
+/** @file
+ GUID for IA32FamilyCpuBasePkg PCD Token Space
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _IA32FAMILYCPUPKG_TOKEN_SPACE_GUID_H_
+#define _IA32FAMILYCPUPKG_TOKEN_SPACE_GUID_H_
+
+#define CPU_TOKEN_SPACE_GUID \
+ { \
+ 0x2ADA836D, 0x0A3D, 0x43D6, { 0xA2, 0x5A, 0x38, 0x45, 0xCA, 0xD2, 0xD4, 0x00 } \
+ }
+
+extern EFI_GUID gEfiCpuTokenSpaceGuid;
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Include/Library/CpuConfigLib.h b/IA32FamilyCpuBasePkg/Include/Library/CpuConfigLib.h
new file mode 100644
index 0000000..39c7ce9
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Library/CpuConfigLib.h
@@ -0,0 +1,702 @@
+/** @file
+ Public include file for the CPU Configuration Library
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: CpuConfigLib.h
+
+**/
+
+#ifndef _CPU_CONFIG_LIB_H_
+#define _CPU_CONFIG_LIB_H_
+
+//
+// Bits definition of PcdProcessorFeatureUserConfiguration,
+// PcdProcessorFeatureCapability, and PcdProcessorFeatureSetting
+//
+#define PCD_CPU_HT_BIT 0x00000001
+#define PCD_CPU_CMP_BIT 0x00000002
+#define PCD_CPU_L2_CACHE_BIT 0x00000004
+#define PCD_CPU_L2_ECC_BIT 0x00000008
+#define PCD_CPU_VT_BIT 0x00000010
+#define PCD_CPU_LT_BIT 0x00000020
+#define PCD_CPU_EXECUTE_DISABLE_BIT 0x00000040
+#define PCD_CPU_L3_CACHE_BIT 0x00000080
+#define PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT 0x00000100
+#define PCD_CPU_FAST_STRING_BIT 0x00000200
+#define PCD_CPU_FERR_SIGNAL_BREAK_BIT 0x00000400
+#define PCD_CPU_PECI_BIT 0x00000800
+#define PCD_CPU_HARDWARE_PREFETCHER_BIT 0x00001000
+#define PCD_CPU_ADJACENT_CACHE_LINE_PREFETCH_BIT 0x00002000
+#define PCD_CPU_DCU_PREFETCHER_BIT 0x00004000
+#define PCD_CPU_IP_PREFETCHER_BIT 0x00008000
+#define PCD_CPU_MACHINE_CHECK_BIT 0x00010000
+#define PCD_CPU_THERMAL_MANAGEMENT_BIT 0x00040000
+#define PCD_CPU_EIST_BIT 0x00080000
+#define PCD_CPU_C1E_BIT 0x00200000
+#define PCD_CPU_C2E_BIT 0x00400000
+#define PCD_CPU_C3E_BIT 0x00800000
+#define PCD_CPU_C4E_BIT 0x01000000
+#define PCD_CPU_HARD_C4E_BIT 0x02000000
+#define PCD_CPU_DEEP_C4_BIT 0x04000000
+#define PCD_CPU_A20M_DISABLE_BIT 0x08000000
+#define PCD_CPU_MONITOR_MWAIT_BIT 0x10000000
+#define PCD_CPU_TSTATE_BIT 0x20000000
+#define PCD_CPU_TURBO_MODE_BIT 0x80000000
+
+//
+// Bits definition of PcdProcessorFeatureUserConfigurationEx1,
+// PcdProcessorFeatureCapabilityEx1, and PcdProcessorFeatureSettingEx1
+//
+#define PCD_CPU_C_STATE_BIT 0x00000001
+#define PCD_CPU_C1_AUTO_DEMOTION_BIT 0x00000002
+#define PCD_CPU_C3_AUTO_DEMOTION_BIT 0x00000004
+#define PCD_CPU_MLC_STREAMER_PREFETCHER_BIT 0x00000008
+#define PCD_CPU_MLC_SPATIAL_PREFETCHER_BIT 0x00000010
+#define PCD_CPU_THREE_STRIKE_COUNTER_BIT 0x00000020
+#define PCD_CPU_ENERGY_PERFORMANCE_BIAS_BIT 0x00000040
+#define PCD_CPU_DCA_BIT 0x00000080
+#define PCD_CPU_X2APIC_BIT 0x00000100
+#define PCD_CPU_AES_BIT 0x00000200
+#define PCD_CPU_APIC_TPR_UPDATE_MESSAGE_BIT 0x00000400
+#define PCD_CPU_SOCKET_ID_REASSIGNMENT_BIT 0x00000800
+
+//
+// Value definition for PcdCpuCallbackSignal
+//
+#define CPU_BYPASS_SIGNAL 0x00000000
+#define CPU_DATA_COLLECTION_SIGNAL 0x00000001
+#define CPU_PROCESSOR_FEATURE_LIST_CONFIG_SIGNAL 0x00000002
+#define CPU_REGISTER_TABLE_TRANSLATION_SIGNAL 0x00000003
+#define CPU_PROCESSOR_SETTING_SIGNAL 0x00000004
+#define CPU_PROCESSOR_SETTING_END_SIGNAL 0x00000005
+
+typedef struct {
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+} EFI_CPUID_REGISTER;
+
+//
+// Enumeration of processor features
+//
+typedef enum {
+ Ht,
+ Cmp,
+ Vt,
+ ExecuteDisableBit,
+ L3Cache,
+ MaxCpuidValueLimit,
+ FastString,
+ FerrSignalBreak,
+ Peci,
+ HardwarePrefetcher,
+ AdjacentCacheLinePrefetch,
+ DcuPrefetcher,
+ IpPrefetcher,
+ ThermalManagement,
+ Eist,
+ BiDirectionalProchot,
+ Forcepr,
+ C1e,
+ C2e,
+ C3e,
+ C4e,
+ HardC4e,
+ DeepC4,
+ Microcode,
+ Microcode2,
+ MachineCheck,
+ GateA20MDisable,
+ MonitorMwait,
+ TState,
+ TurboMode,
+ CState,
+ C1AutoDemotion,
+ C3AutoDemotion,
+ MlcStreamerPrefetcher,
+ MlcSpatialPrefetcher,
+ ThreeStrikeCounter,
+ EnergyPerformanceBias,
+ Dca,
+ X2Apic,
+ Aes,
+ ApicTprUpdateMessage,
+ TccActivation,
+ CpuFeatureMaximum
+} CPU_FEATURE_ID;
+
+//
+// Structure for collected processor feature capability,
+// and feature-specific attribute.
+//
+typedef struct {
+ BOOLEAN Capability;
+ VOID *Attribute;
+} CPU_FEATURE_DATA;
+
+//
+// Structure for collected CPUID data.
+//
+typedef struct {
+ EFI_CPUID_REGISTER *CpuIdLeaf;
+ UINTN NumberOfBasicCpuidLeafs;
+ UINTN NumberOfExtendedCpuidLeafs;
+ UINTN NumberOfCacheAndTlbCpuidLeafs;
+ UINTN NumberOfDeterministicCacheParametersCpuidLeafs;
+ UINTN NumberOfExtendedTopologyEnumerationLeafs;
+} CPU_CPUID_DATA;
+
+typedef struct {
+ UINTN Ratio;
+ UINTN Vid;
+ UINTN Power;
+ UINTN TransitionLatency;
+ UINTN BusMasterLatency;
+} FVID_ENTRY;
+
+//
+// Miscellaneous processor data
+//
+typedef struct {
+ //
+ // Local Apic Data
+ //
+ UINT32 InitialApicID; ///< Initial APIC ID
+ UINT32 ApicID; ///< Current APIC ID
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ UINT32 ApicVersion;
+ //
+ // Frequency data
+ //
+ UINTN IntendedFsbFrequency;
+ UINTN ActualFsbFrequency;
+ BOOLEAN FrequencyLocked;
+ UINTN MaxCoreToBusRatio;
+ UINTN MinCoreToBusRatio;
+ UINTN MaxTurboRatio;
+ UINTN MaxVid;
+ UINTN MinVid;
+ UINTN PackageTdp;
+ UINTN CoreTdp;
+ UINTN NumberOfPStates;
+ FVID_ENTRY *FvidTable;
+ //
+ // Config TDP data
+ //
+ UINTN PkgMinPwrLvl1;
+ UINTN PkgMaxPwrLvl1;
+ UINTN ConfigTDPLvl1Ratio;
+ UINTN PkgTDPLvl1;
+ UINTN PkgMinPwrLvl2;
+ UINTN PkgMaxPwrLvl2;
+ UINTN ConfigTDPLvl2Ratio;
+ UINTN PkgTDPLvl2;
+
+ //
+ // Other data
+ //
+ UINT32 PlatformRequirement;
+ UINT64 HealthData;
+ UINT32 MicrocodeRevision;
+} CPU_MISC_DATA;
+
+//
+// Structure for all collected processor data
+//
+typedef struct {
+ CPU_CPUID_DATA CpuidData;
+ EFI_CPU_PHYSICAL_LOCATION ProcessorLocation;
+ CPU_MISC_DATA CpuMiscData;
+ CPU_FEATURE_DATA FeatureData[CpuFeatureMaximum];
+ UINT8 PackageIdBitOffset;
+ BOOLEAN PackageBsp;
+} CPU_COLLECTED_DATA;
+
+#define GET_CPU_MISC_DATA(ProcessorNumber, Item) \
+ ((mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber]).CpuMiscData.Item)
+
+//
+// Signature for feature list entry
+//
+#define EFI_CPU_FEATURE_ENTRY_SIGNATURE SIGNATURE_32 ('C', 'f', 't', 'r')
+
+//
+// Node of processor feature list
+//
+typedef struct {
+ UINT32 Signature;
+ CPU_FEATURE_ID FeatureID;
+ VOID *Attribute;
+ LIST_ENTRY Link;
+} CPU_FEATURE_ENTRY;
+
+#define CPU_FEATURE_ENTRY_FROM_LINK(link) CR (link, CPU_FEATURE_ENTRY, Link, EFI_CPU_FEATURE_ENTRY_SIGNATURE)
+
+//
+// Register types in register table
+//
+typedef enum _REGISTER_TYPE {
+ Msr,
+ ControlRegister,
+ MemoryMapped,
+ CacheControl
+} REGISTER_TYPE;
+
+//
+// Element of register table entry
+//
+typedef struct {
+ REGISTER_TYPE RegisterType;
+ UINT32 Index;
+ UINT8 ValidBitStart;
+ UINT8 ValidBitLength;
+ UINT64 Value;
+} CPU_REGISTER_TABLE_ENTRY;
+
+//
+// Register table definition, including current table length,
+// allocated size of this table, and pointer to the list of table entries.
+//
+typedef struct {
+ UINT32 TableLength;
+ UINT32 NumberBeforeReset;
+ UINT32 AllocatedSize;
+ UINT32 InitialApicId;
+ CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
+} CPU_REGISTER_TABLE;
+
+//
+// Definition of Processor Configuration Context Buffer
+//
+typedef struct {
+ UINTN NumberOfProcessors;
+ UINTN BspNumber;
+ CPU_COLLECTED_DATA *CollectedDataBuffer;
+ LIST_ENTRY *FeatureLinkListEntry;
+ CPU_REGISTER_TABLE *PreSmmInitRegisterTable;
+ CPU_REGISTER_TABLE *RegisterTable;
+ UINTN *SettingSequence;
+} CPU_CONFIG_CONTEXT_BUFFER;
+
+//
+// Structure conveying socket ID configuration information.
+//
+typedef struct {
+ UINT8 DefaultSocketId;
+ UINT8 NewSocketId;
+} CPU_SOCKET_ID_INFO;
+
+extern CPU_CONFIG_CONTEXT_BUFFER *mCpuConfigLibConfigConextBuffer;
+
+/**
+ Set feature capability and related attribute.
+
+ This function sets the feature capability and its attribute.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureID The ID of the feature.
+ @param Attribute Feature-specific data.
+
+**/
+VOID
+EFIAPI
+SetProcessorFeatureCapability (
+ IN UINTN ProcessorNumber,
+ IN CPU_FEATURE_ID FeatureID,
+ IN VOID *Attribute
+ );
+
+/**
+ Clears feature capability and related attribute.
+
+ This function clears the feature capability and its attribute.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureID The ID of the feature.
+
+**/
+VOID
+EFIAPI
+ClearProcessorFeatureCapability (
+ IN UINTN ProcessorNumber,
+ IN CPU_FEATURE_ID FeatureID
+ );
+
+/**
+ Get feature capability and related attribute.
+
+ This function gets the feature capability and its attribute.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureID The ID of the feature.
+ @param Attribute Pointer to the output feature-specific data.
+
+ @retval TRUE The feature is supported by the processor
+ @retval FALSE The feature is not supported by the processor
+
+**/
+BOOLEAN
+EFIAPI
+GetProcessorFeatureCapability (
+ IN UINTN ProcessorNumber,
+ IN CPU_FEATURE_ID FeatureID,
+ OUT VOID **Attribute OPTIONAL
+ );
+
+typedef enum {
+ BasicCpuidLeaf,
+ ExtendedCpuidLeaf,
+ CacheAndTlbCpuidLeafs,
+ DeterministicCacheParametersCpuidLeafs,
+ ExtendedTopologyEnumerationCpuidLeafs
+} CPUID_TYPE;
+
+/**
+ Get the number of CPUID leafs of various types.
+
+ This function get the number of CPUID leafs of various types.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param CpuidType The type of the CPU id.
+
+ @return Maximal index of CPUID instruction for basic leafs.
+
+**/
+UINTN
+EFIAPI
+GetNumberOfCpuidLeafs (
+ IN UINTN ProcessorNumber,
+ IN CPUID_TYPE CpuidType
+ );
+
+/**
+ Get the pointer to specified CPUID leaf.
+
+ This function gets the pointer to specified CPUID leaf.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param Index Index of the CPUID leaf.
+
+ @return Pointer to specified CPUID leaf
+
+**/
+EFI_CPUID_REGISTER*
+EFIAPI
+GetProcessorCpuid (
+ IN UINTN ProcessorNumber,
+ IN UINTN Index
+ );
+
+/**
+ Get the pointer to specified CPUID leaf of cache and TLB parameters.
+
+ This function gets the pointer to specified CPUID leaf of cache and TLB parameters.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param Index Index of the CPUID leaf.
+
+ @return Pointer to specified CPUID leaf.
+
+**/
+EFI_CPUID_REGISTER*
+EFIAPI
+GetCacheAndTlbCpuidLeaf (
+ IN UINTN ProcessorNumber,
+ IN UINTN Index
+ );
+
+/**
+ Get the pointer to specified CPUID leaf of deterministic cache parameters.
+
+ This function gets the pointer to specified CPUID leaf of deterministic cache parameters.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param Index Index of the CPUID leaf.
+
+ @return Pointer to specified CPUID leaf.
+
+**/
+EFI_CPUID_REGISTER*
+EFIAPI
+GetDeterministicCacheParametersCpuidLeaf (
+ IN UINTN ProcessorNumber,
+ IN UINTN Index
+ );
+
+/**
+ Get the pointer to specified CPUID leaf of Extended Topology Enumeration.
+
+ This function gets the pointer to specified CPUID leaf of Extended Topology Enumeration.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+ @param Index Index of the CPUID leaf.
+
+ @return Pointer to specified CPUID leaf.
+
+**/
+EFI_CPUID_REGISTER*
+EFIAPI
+GetExtendedTopologyEnumerationCpuidLeafs (
+ IN UINTN ProcessorNumber,
+ IN UINTN Index
+ );
+
+/**
+ Get the version information of specified logical processor.
+
+ This function gets the version information of specified logical processor,
+ including family ID, model ID, stepping ID and processor type.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param DisplayedFamily Pointer to family ID for output
+ @param DisplayedModel Pointer to model ID for output
+ @param SteppingId Pointer to stepping ID for output
+ @param ProcessorType Pointer to processor type for output
+
+**/
+VOID
+EFIAPI
+GetProcessorVersionInfo (
+ IN UINTN ProcessorNumber,
+ OUT UINT32 *DisplayedFamily OPTIONAL,
+ OUT UINT32 *DisplayedModel OPTIONAL,
+ OUT UINT32 *SteppingId OPTIONAL,
+ OUT UINT32 *ProcessorType OPTIONAL
+ );
+
+/**
+ Get initial local APIC ID of specified logical processor
+
+ This function gets initial local APIC ID of specified logical processor.
+
+ @param ProcessorNumber Handle number of specified logical processor
+
+ @return Initial local APIC ID of specified logical processor
+
+**/
+UINT32
+EFIAPI
+GetInitialLocalApicId (
+ UINTN ProcessorNumber
+ );
+
+/**
+ Get the location of specified processor.
+
+ This function gets the location of specified processor, including
+ package number, core number within package, thread number within core.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+ @param PackageNumber Pointer to the output package number.
+ @param CoreNumber Pointer to the output core number.
+ @param ThreadNumber Pointer to the output thread number.
+
+**/
+VOID
+EFIAPI
+GetProcessorLocation (
+ IN UINTN ProcessorNumber,
+ OUT UINT32 *PackageNumber OPTIONAL,
+ OUT UINT32 *CoreNumber OPTIONAL,
+ OUT UINT32 *ThreadNumber OPTIONAL
+ );
+
+/**
+ Get the Feature entry at specified position in a feature list.
+
+ This function gets the Feature entry at specified position in a feature list.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureIndex The index of the node in feature list.
+ @param Attribute Pointer to output feature-specific attribute
+
+ @return Feature ID of specified feature. CpuFeatureMaximum means not found
+
+**/
+CPU_FEATURE_ID
+EFIAPI
+GetProcessorFeatureEntry (
+ IN UINTN ProcessorNumber,
+ IN UINTN FeatureIndex,
+ OUT VOID **Attribute OPTIONAL
+ );
+
+/**
+ Append a feature entry at the end of a feature list.
+
+ This function appends a feature entry at the end of a feature list.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureID ID of the specified feature.
+ @param Attribute Feature-specific attribute.
+
+ @retval EFI_SUCCESS This function always return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+AppendProcessorFeatureIntoList (
+ IN UINTN ProcessorNumber,
+ IN CPU_FEATURE_ID FeatureID,
+ IN VOID *Attribute
+ );
+
+/**
+ Delete a feature entry in a feature list.
+
+ This function deletes a feature entry in a feature list.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureIndex The index of the node in feature list.
+
+ @retval EFI_SUCCESS The feature node successfully removed.
+ @retval EFI_INVALID_PARAMETER Index surpasses the length of list.
+
+**/
+EFI_STATUS
+EFIAPI
+DeleteProcessorFeatureFromList (
+ IN UINTN ProcessorNumber,
+ IN UINTN FeatureIndex
+ );
+
+/**
+ Insert a feature entry into a feature list.
+
+ This function insert a feature entry into a feature list before a node specified by FeatureIndex.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureIndex The index of the new node in feature list.
+ @param FeatureID ID of the specified feature.
+ @param Attribute Feature-specific attribute.
+
+ @retval EFI_SUCCESS The feature node successfully inserted.
+ @retval EFI_INVALID_PARAMETER Index surpasses the length of list.
+
+**/
+EFI_STATUS
+EFIAPI
+InsertProcessorFeatureIntoList (
+ IN UINTN ProcessorNumber,
+ IN UINTN FeatureIndex,
+ IN CPU_FEATURE_ID FeatureID,
+ IN VOID *Attribute
+ );
+
+/**
+ Add an entry in the post-SMM-init register table.
+
+ This function adds an entry in the post-SMM-init register table, with given register type,
+ register index, bit section and value.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param RegisterType Type of the register to program
+ @param Index Index of the register to program
+ @param ValidBitStart Start of the bit section
+ @param ValidBitLength Length of the bit section
+ @param Value Value to write
+
+**/
+VOID
+EFIAPI
+WriteRegisterTable (
+ IN UINTN ProcessorNumber,
+ IN REGISTER_TYPE RegisterType,
+ IN UINT32 Index,
+ IN UINT8 ValidBitStart,
+ IN UINT8 ValidBitLength,
+ IN UINT64 Value
+ );
+
+/**
+ Add an entry in the pre-SMM-init register table.
+
+ This function adds an entry in the pre-SMM-init register table, with given register type,
+ register index, bit section and value.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param RegisterType Type of the register to program
+ @param Index Index of the register to program
+ @param ValidBitStart Start of the bit section
+ @param ValidBitLength Length of the bit section
+ @param Value Value to write
+
+**/
+VOID
+EFIAPI
+WritePreSmmInitRegisterTable (
+ IN UINTN ProcessorNumber,
+ IN REGISTER_TYPE RegisterType,
+ IN UINT32 Index,
+ IN UINT8 ValidBitStart,
+ IN UINT8 ValidBitLength,
+ IN UINT64 Value
+ );
+
+/**
+ Set the sequence of processor setting.
+
+ This function sets the a processor setting at the position in
+ setting sequence specified by Index.
+
+ @param Index The zero-based index in the sequence.
+ @param ProcessorNumber Handle number of the processor to set.
+
+ @retval EFI_SUCCESS The sequence successfully modified.
+ @retval EFI_INVALID_PARAMETER Index surpasses the boundary of sequence.
+ @retval EFI_NOT_FOUND Processor specified by ProcessorNumber does not exist.
+
+**/
+EFI_STATUS
+SetSettingSequence (
+ IN UINTN Index,
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Set PcdCpuCallbackSignal, and then read the value back.
+
+ This function sets PCD entry PcdCpuCallbackSignal. If there is callback
+ function registered on it, the callback function will be triggered, and
+ it may change the value of PcdCpuCallbackSignal. This function then reads
+ the value of PcdCpuCallbackSignal back, the check whether it has been changed.
+
+ @param Value The value to set to PcdCpuCallbackSignal.
+
+ @return The value of PcdCpuCallbackSignal read back.
+
+**/
+UINT8
+SetAndReadCpuCallbackSignal (
+ IN UINT8 Value
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Include/Library/CpuOnlyResetLib.h b/IA32FamilyCpuBasePkg/Include/Library/CpuOnlyResetLib.h
new file mode 100644
index 0000000..a1532ed
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Library/CpuOnlyResetLib.h
@@ -0,0 +1,50 @@
+/** @file
+ Public include file for the CPU-Only Reset Library.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: CpuOnlyResetLib.h
+
+**/
+
+#ifndef __CPU_ONLY_RESET_LIB_H__
+#define __CPU_ONLY_RESET_LIB_H__
+
+/**
+ Performs a CPU only reset.
+ This function performs a CPU-only reset.
+
+**/
+VOID
+EFIAPI
+CpuOnlyReset(
+ VOID
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Include/Library/PlatformSecLib.h b/IA32FamilyCpuBasePkg/Include/Library/PlatformSecLib.h
new file mode 100644
index 0000000..133e840
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Library/PlatformSecLib.h
@@ -0,0 +1,82 @@
+/** @file
+ This library class defines interface for platform to perform platform
+ specific initialization in Sec phase.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __PLATFORM_SEC_LIB_H__
+#define __PLATFORM_SEC_LIB_H__
+
+
+/**
+ A developer supplied function to perform platform specific operations.
+
+ It's a developer supplied function to perform any operations appropriate to a
+ given platform. It's invoked just before passing control to PEI core by SEC
+ core. Platform developer may modify the SecCoreData passed to PEI Core.
+ It returns a platform specific PPI list that platform wishes to pass to PEI core.
+ The Generic SEC core module will merge this list to join the final list passed to
+ PEI core.
+
+ @param SecCoreData The same parameter as passing to PEI core. It
+ could be overridden by this function.
+
+ @return The platform specific PPI list to be passed to PEI core or
+ NULL if there is no need of such platform specific PPI list.
+
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+EFIAPI
+SecPlatformMain (
+ IN OUT EFI_SEC_PEI_HAND_OFF *SecCoreData
+ );
+
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param StructureSize Pointer to the variable describing size of the input buffer.
+ @param 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 CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Include/Library/SmmCpuPlatformHookLib.h b/IA32FamilyCpuBasePkg/Include/Library/SmmCpuPlatformHookLib.h
new file mode 100644
index 0000000..bc2710f
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Library/SmmCpuPlatformHookLib.h
@@ -0,0 +1,137 @@
+/** @file
+ Public include file for the SMM CPU Platform Hook Library.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __SMM_CPU_PLATFORM_HOOK_LIB_H__
+#define __SMM_CPU_PLATFORM_HOOK_LIB_H__
+
+/**
+ Checks if platform produces a valid SMI.
+
+ This function checks if platform produces a valid SMI. This function is
+ called at SMM entry to detect if this is a spurious SMI. This function
+ must be implemented in an MP safe way because it is called by multiple CPU
+ threads.
+
+ @retval TRUE There is a valid SMI
+ @retval FALSE There is no valid SMI
+
+**/
+BOOLEAN
+EFIAPI
+PlatformValidSmi (
+ VOID
+ );
+
+/**
+ Clears platform top level SMI status bit.
+
+ This function clears platform top level SMI status bit.
+
+ @retval TRUE The platform top level SMI status is cleared.
+ @retval FALSE The paltform top level SMI status cannot be cleared.
+
+**/
+BOOLEAN
+EFIAPI
+ClearTopLevelSmiStatus (
+ VOID
+ );
+
+/**
+ Performs platform specific way of SMM BSP election.
+
+ This function performs platform specific way of SMM BSP election.
+
+ @param IsBsp Output parameter. TRUE: the CPU this function executes
+ on is elected to be the SMM BSP. FALSE: the CPU this
+ function executes on is to be SMM AP.
+
+ @retval EFI_SUCCESS The function executes successfully.
+ @retval EFI_NOT_READY The function does not determine whether this CPU should be
+ BSP or AP. This may occur if hardware init sequence to
+ enable the determination is yet to be done, or the function
+ chooses not to do BSP election and will let SMM CPU driver to
+ use its default BSP election process.
+ @retval EFI_DEVICE_ERROR The function cannot determine whether this CPU should be
+ BSP or AP due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSmmBspElection (
+ OUT BOOLEAN *IsBsp
+ );
+
+
+typedef enum {
+ SmmPageSize4K,
+ SmmPageSize2M,
+ SmmPageSize1G,
+ MaxSmmPageSizeType
+} SMM_PAGE_SIZE_TYPE;
+
+
+/**
+ Get platform page table attribute .
+
+ This function gets page table attribute of platform.
+
+ @param Address Input parameter. Obtain the page table entries attribute on this address.
+ @param PageSize Output parameter. The size of the page.
+ @param NumOfPages Output parameter. Number of page.
+ @param PageAttribute Output parameter. Paging Attributes (WB, UC, etc).
+
+ @retval EFI_SUCCESS The platform page table attribute from the address is determined.
+ @retval EFI_UNSUPPORTED The paltform not supoort to get page table attribute from the address.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformPageTableAttribute (
+ IN UINT64 Address,
+ OUT SMM_PAGE_SIZE_TYPE *PageSize,
+ OUT UINTN *NumOfPages,
+ OUT UINTN *PageAttribute
+ );
+
+/**
+ Platform hook called when exiting SMM.
+
+**/
+VOID
+EFIAPI
+PlatformSmmExitProcessing (
+ VOID
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Include/Library/SocketLga775Lib.h b/IA32FamilyCpuBasePkg/Include/Library/SocketLga775Lib.h
new file mode 100644
index 0000000..26ab146
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Library/SocketLga775Lib.h
@@ -0,0 +1,185 @@
+/** @file
+ Public include file for CPU definitions and CPU library functions that
+ apply to CPUs that fit into an LGA775 spocket.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: CpuOnlyResetLib.h
+
+**/
+
+#ifndef __SOCKET_LGA_775_H__
+#define __SOCKET_LGA_775_H__
+
+//
+// Processor Family and Model information.
+//
+#define PENTIUM_FAMILY_ID 0x05
+#define QUARK_MODEL_ID 0x09
+
+//
+// Definition for CPUID Index
+//
+#define EFI_CPUID_SIGNATURE 0x0
+#define EFI_CPUID_VERSION_INFO 0x1
+#define EFI_CPUID_CACHE_INFO 0x2
+#define EFI_CPUID_SERIAL_NUMBER 0x3
+#define EFI_CPUID_CACHE_PARAMS 0x4
+#define EFI_CPUID_EXTENDED_TOPOLOGY 0xB
+#define EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID 0x0
+#define EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT 0x1
+#define EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE 0x2
+
+#define EFI_CPUID_EXTENDED_FUNCTION 0x80000000
+#define EFI_CPUID_EXTENDED_CPU_SIG 0x80000001
+#define EFI_CPUID_BRAND_STRING1 0x80000002
+#define EFI_CPUID_BRAND_STRING2 0x80000003
+#define EFI_CPUID_BRAND_STRING3 0x80000004
+#define EFI_CPUID_ADDRESS_SIZE 0x80000008
+
+//
+// Definition for MSR address
+//
+#define EFI_MSR_IA32_TIME_STAMP_COUNTER 0x10
+#define EFI_MSR_IA32_APIC_BASE 0x1B
+#define MSR_IA32_MISC_ENABLE 0x1A0
+
+//
+// Definition for Local APIC registers and related values
+//
+#define LOCAL_APIC_LVT_TIMER 0x320
+#define LOCAL_APIC_TIMER_INIT_COUNT 0x380
+#define LOCAL_APIC_TIMER_COUNT 0x390
+#define LOCAL_APIC_TIMER_DIVIDE 0x3E0
+
+
+#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 IA32_PG_P 1u
+#define IA32_PG_RW (1u << 1)
+#define IA32_PG_USR (1u << 2)
+#define IA32_PG_WT (1u << 3)
+#define IA32_PG_CD (1u << 4)
+#define IA32_PG_A (1u << 5)
+#define IA32_PG_D (1u << 6)
+#define IA32_PG_PS (1u << 7)
+#define IA32_PG_G (1u << 8)
+#define IA32_PG_AVL1 (7u << 9)
+#define IA32_PG_PAT_2M (1u << 12)
+#define IA32_PG_PAT_4K IA32_PG_PS
+#define IA32_PG_AVL2 (0x7ffull << 52)
+
+#define IA32_CPUID_SS 0x08000000
+
+#define IA32_MTRRCAP 0xfe
+
+#define SMM_DEFAULT_SMBASE 0x30000
+#define SMM_HANDLER_OFFSET 0x8000
+#define SMM_PSD_OFFSET 0xfb00
+#define SMM_CPU_STATE_OFFSET 0xfc00
+
+#define SMM_CPU_INTERVAL SIZE_2KB
+
+#pragma pack (1)
+
+typedef struct {
+ UINT64 Signature; // Offset 0x00
+ UINT16 Reserved1; // Offset 0x08
+ UINT16 Reserved2; // Offset 0x0A
+ UINT16 Reserved3; // Offset 0x0C
+ UINT16 SmmCs; // Offset 0x0E
+ UINT16 SmmDs; // Offset 0x10
+ UINT16 SmmSs; // Offset 0x12
+ UINT16 SmmOtherSegment; // Offset 0x14
+ UINT16 Reserved4; // Offset 0x16
+ UINT64 Reserved5; // Offset 0x18
+ UINT64 Reserved6; // Offset 0x20
+ UINT64 Reserved7; // Offset 0x28
+ UINT64 SmmGdtPtr; // Offset 0x30
+ UINT32 SmmGdtSize; // Offset 0x38
+ UINT32 Reserved8; // Offset 0x3C
+ UINT64 Reserved9; // Offset 0x40
+ UINT64 Reserved10; // Offset 0x48
+ UINT16 Reserved11; // Offset 0x50
+ UINT16 Reserved12; // Offset 0x52
+ UINT32 Reserved13; // Offset 0x54
+ UINT64 MtrrBaseMaskPtr; // Offset 0x58
+} PROCESSOR_SMM_DESCRIPTOR;
+
+///
+///
+///
+#define SOCKET_LGA_775_SMM_MIN_REV_ID_IOMISC 0x30004
+#define SOCKET_LGA_775_SMM_MIN_REV_ID_x64 0x30006
+
+///
+/// SMM Save State IOMisc related defines
+///
+//
+// I/O Length BitMap
+//
+#define SMM_IO_LENGTH_BYTE 0x01
+#define SMM_IO_LENGTH_WORD 0x02
+#define SMM_IO_LENGTH_DWORD 0x04
+
+//
+// I/O Instruction Type BitMap
+//
+#define SMM_IO_TYPE_IN_IMMEDIATE 0x9
+#define SMM_IO_TYPE_IN_DX 0x1
+#define SMM_IO_TYPE_OUT_IMMEDIATE 0x8
+#define SMM_IO_TYPE_OUT_DX 0x0
+#define SMM_IO_TYPE_INS 0x3
+#define SMM_IO_TYPE_OUTS 0x2
+#define SMM_IO_TYPE_REP_INS 0x7
+#define SMM_IO_TYPE_REP_OUTS 0x6
+
+typedef union {
+ struct {
+ UINT32 SmiFlag:1;
+ UINT32 Length:3;
+ UINT32 Type:4;
+ UINT32 Reserved1:8;
+ UINT32 Port:16;
+ } Bits;
+ UINT32 Uint32;
+} SOCKET_LGA_775_SMM_CPU_STATE_IOMISC;
+
+#pragma pack ()
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Include/Ppi/Cache.h b/IA32FamilyCpuBasePkg/Include/Ppi/Cache.h
new file mode 100644
index 0000000..b673fe2
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Ppi/Cache.h
@@ -0,0 +1,84 @@
+/** @file
+
+
+ Cache PPI definition.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _PEI_CACHE_PPI_H_
+#define _PEI_CACHE_PPI_H_
+
+#define PEI_CACHE_PPI_GUID \
+ { \
+ 0xc153205a, 0xe898, 0x4c24, {0x86, 0x89, 0xa4, 0xb4, 0xbc, 0xc5, 0xc8, 0xa2 } \
+ }
+
+typedef struct _PEI_CACHE_PPI PEI_CACHE_PPI;
+
+//
+// EFI_MEMORY_CACHE_TYPE
+//
+typedef INT32 EFI_MEMORY_CACHE_TYPE;
+
+//
+// PEI_SET_CACHE_PPI
+//
+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
+ );
+
+//
+// PEI_RESET_CACHE_PPI
+//
+typedef
+EFI_STATUS
+(EFIAPI *PEI_RESET_CACHE_PPI) (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This
+ );
+
+//
+// PEI_CACHE_PPI
+//
+struct _PEI_CACHE_PPI {
+ PEI_SET_CACHE_PPI SetCache;
+ PEI_RESET_CACHE_PPI ResetCache;
+};
+
+extern EFI_GUID gPeiCachePpiGuid;
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuService.h b/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuService.h
new file mode 100644
index 0000000..896959b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuService.h
@@ -0,0 +1,231 @@
+/** @file
+
+
+ Smm CPU Service protocol definition.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SMM_CPU_SERVICE_PROTOCOL_H_
+#define _SMM_CPU_SERVICE_PROTOCOL_H_
+
+//
+// Share some definitions with MP Services and CPU Arch Protocol
+//
+#include <Protocol/MpService.h>
+#include <Protocol/Cpu.h>
+
+#define EFI_SMM_CPU_SERVICE_PROTOCOL_GUID \
+ { \
+ 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 } \
+ }
+
+typedef struct _EFI_SMM_CPU_SERVICE_PROTOCOL EFI_SMM_CPU_SERVICE_PROTOCOL;
+
+//
+// Protocol functions
+//
+
+/**
+ Gets processor 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_SMM_CPU_SERVICE_PROTOCOL
+ instance.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
+ the requested processor is deposited.
+
+ @retval EFI_SUCCESS Processor information was returned.
+ @retval EFI_DEVICE_ERROR The calling processor is an AP.
+ @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
+ @retval EFI_NOT_FOUND The processor with the handle specified by
+ ProcessorNumber does not exist in the platform.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_SMM_GET_PROCESSOR_INFO) (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ );
+
+/**
+ 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.
+
+ 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_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of AP that is to become the new
+ BSP. The range is from 0 to the total number of
+ logical processors minus 1.
+
+ @retval EFI_SUCCESS BSP successfully switched.
+ @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
+ this service returning.
+ @retval EFI_UNSUPPORTED Switching the BSP is not supported.
+ @retval EFI_SUCCESS The calling processor is an AP.
+ @retval EFI_NOT_FOUND The processor with the handle specified by
+ ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
+ a disabled AP.
+ @retval EFI_NOT_READY The specified AP is busy.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_SMM_SWITCH_BSP) (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Notify that a new processor has been added to the system.
+
+ The SMM CPU driver should add the processor to the SMM CPU list.
+
+ If the processor is disabled it won't participate any SMI handler during subsequent SMIs.
+
+ @param This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param ProcessorId The hardware ID of the processor.
+ @param ProcessorNumber The handle number of processor.
+ @param ProcessorResource A pointer to EFI_SMM_PROCESSOR_RESOURCE which holds the assigned resources.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ALREADY_STARTED Processor already present.
+ @retval EFI_NOT_READY Space for a new handle could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SMM_ADD_PROCESSOR) (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINT64 ProcessorId,
+ OUT UINTN *ProcessorNumber
+ );
+
+/**
+ Notify that a processor is hot-removed.
+
+ Remove a processor from the CPU list of the SMM CPU driver. After this API is called, the removed processor
+ must not respond to SMIs in the coherence domain.
+
+ @param This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param ProcessorId The hardware ID of the processor.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND Processor with the hardware ID specified by ProcessorId does not exist.
+ @retval EFI_NOT_READY Specified AP is busy.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SMM_REMOVE_PROCESSOR) (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ 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. 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_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of AP that is to become the new
+ BSP. The range is from 0 to the total number of
+ logical processors minus 1.
+
+ @retval EFI_SUCCESS The current processor handle number was returned
+ in ProcessorNumber.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_SMM_WHOAMI) (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ OUT UINTN *ProcessorNumber
+ );
+
+/**
+ Register exception handler.
+
+ @param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
+ @param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
+ the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
+ of the UEFI 2.0 specification.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ If this parameter is NULL, then the handler will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SMM_REGISTER_EXCEPTION_HANDLER) (
+ IN EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+//
+// This protocol provides CPU services from SMM.
+//
+struct _EFI_SMM_CPU_SERVICE_PROTOCOL {
+ EFI_SMM_GET_PROCESSOR_INFO GetProcessorInfo;
+ EFI_SMM_SWITCH_BSP SwitchBsp;
+ EFI_SMM_ADD_PROCESSOR AddProcessor;
+ EFI_SMM_REMOVE_PROCESSOR RemoveProcessor;
+ EFI_SMM_WHOAMI WhoAmI;
+ EFI_SMM_REGISTER_EXCEPTION_HANDLER RegisterExceptionHandler;
+};
+
+extern EFI_GUID gEfiSmmCpuServiceProtocolGuid;
+
+#endif
+
diff --git a/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuSync.h b/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuSync.h
new file mode 100644
index 0000000..e4c4811
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuSync.h
@@ -0,0 +1,131 @@
+/** @file
+
+
+ Smm CPU Sync protocol definition.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SMM_CPU_SYNC_PROTOCOL_H_
+#define _SMM_CPU_SYNC_PROTOCOL_H_
+
+#define SMM_CPU_SYNC_PROTOCOL_GUID \
+ { \
+ 0xd5950985, 0x8be3, 0x4b1c, { 0xb6, 0x3f, 0x95, 0xd1, 0x5a, 0xb3, 0xb6, 0x5f } \
+ }
+
+typedef struct _SMM_CPU_SYNC_PROTOCOL SMM_CPU_SYNC_PROTOCOL;
+
+//
+// Data structures
+//
+
+typedef enum {
+ SmmCpuSyncModeTradition,
+ SmmCpuSyncModeRelaxedAp,
+ SmmCpuSyncModeMax
+} SMM_CPU_SYNC_MODE;
+
+//
+// Protocol functions
+//
+
+/**
+ Given timeout constraint, wait for all APs to arrive, and insure if this function returns EFI_SUCCESS, then
+ no AP will execute normal mode code before entering SMM, so it is safe to access shared hardware resource
+ between SMM and normal mode. Note if there are SMI disabled APs, this function will return EFI_NOT_READY.
+
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS No AP will execute normal mode code before entering SMM, so it is safe to access
+ shared hardware resource between SMM and normal mode
+ @retval EFI_NOT_READY One or more CPUs may still execute normal mode code
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC_CHECK_AP_ARRIVAL)(
+ IN SMM_CPU_SYNC_PROTOCOL *This
+ );
+
+
+/**
+ Set SMM synchronization mode starting from the next SMI run.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode The SMM synchronization mode to be set and effective from the next SMI run.
+
+ @retval EFI_SUCCESS The function completes successfully.
+ @retval EFI_INVALID_PARAMETER SynMode is not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC_SET_MODE) (
+ IN SMM_CPU_SYNC_PROTOCOL *This,
+ IN SMM_CPU_SYNC_MODE SyncMode
+ );
+
+
+/**
+ Get current effective SMM synchronization mode.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode Output parameter. The current effective SMM synchronization mode.
+
+ @retval EFI_SUCCESS The SMM synchronization mode has been retrieved successfully.
+ @retval EFI_INVALID_PARAMETER SyncMode is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC_GET_MODE) (
+ IN SMM_CPU_SYNC_PROTOCOL *This,
+ OUT SMM_CPU_SYNC_MODE *SyncMode
+ );
+
+/**
+ This protocol provides services on SMM CPU syncrhonization related status and controls
+**/
+struct _SMM_CPU_SYNC_PROTOCOL {
+ SMM_CPU_SYNC_CHECK_AP_ARRIVAL CheckApArrival;
+ SMM_CPU_SYNC_SET_MODE SetMode;
+ SMM_CPU_SYNC_GET_MODE GetMode;
+};
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gSmmCpuSyncProtocolGuid;
+
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuSync2.h b/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuSync2.h
new file mode 100644
index 0000000..c38e5e9
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Protocol/SmmCpuSync2.h
@@ -0,0 +1,224 @@
+/** @file
+
+
+ Smm CPU Sync2 protocol definition.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SMM_CPU_SYNC2_PROTOCOL_H_
+#define _SMM_CPU_SYNC2_PROTOCOL_H_
+
+#include "SmmCpuSync.h"
+
+#define SMM_CPU_SYNC2_PROTOCOL_GUID \
+ { \
+ 0x9db72e22, 0x9262, 0x4a18, { 0x8f, 0xe0, 0x85, 0xe0, 0x3d, 0xfa, 0x96, 0x73 } \
+ }
+
+typedef struct _SMM_CPU_SYNC2_PROTOCOL SMM_CPU_SYNC2_PROTOCOL;
+
+typedef enum {
+ SmmCpuSync2StateNormal,
+ SmmCpuSync2StateDelayed,
+ SmmCpuSync2StateBlocked,
+ SmmCpuSync2StateDisabled,
+ SmmCpuSync2StateMax
+} SMM_CPU_SYNC2_CPU_STATE;
+
+//
+// Protocol functions
+//
+
+/**
+ Given timeout constraint, wait for all APs to arrive, and insure if this function returns EFI_SUCCESS, then
+ no AP will execute normal mode code before entering SMM, so it is safe to access shared hardware resource
+ between SMM and normal mode. Note if there are SMI disabled APs, this function will return EFI_NOT_READY.
+
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS No AP will execute normal mode code before entering SMM, so it is safe to access
+ shared hardware resource between SMM and normal mode
+ @retval EFI_NOT_READY One or more CPUs may still execute normal mode code
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC2_CHECK_AP_ARRIVAL)(
+ IN SMM_CPU_SYNC2_PROTOCOL *This
+ );
+
+
+/**
+ Set SMM synchronization mode starting from the next SMI run.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode The SMM synchronization mode to be set and effective from the next SMI run.
+
+ @retval EFI_SUCCESS The function completes successfully.
+ @retval EFI_INVALID_PARAMETER SynMode is not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC2_SET_MODE) (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN SMM_CPU_SYNC_MODE SyncMode
+ );
+
+
+/**
+ Get current effective SMM synchronization mode.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode Output parameter. The current effective SMM synchronization mode.
+
+ @retval EFI_SUCCESS The SMM synchronization mode has been retrieved successfully.
+ @retval EFI_INVALID_PARAMETER SyncMode is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC2_GET_MODE) (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ OUT SMM_CPU_SYNC_MODE *SyncMode
+ );
+
+
+/**
+ Checks CPU SMM synchronization state
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @param CpuIndex Index of the CPU for which the state is to be retrieved.
+
+ @param CpuState The state of the CPU
+
+ @retval EFI_SUCCESS Returns EFI_SUCCESS if the CPU's state is retrieved.
+
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid or CpuState is NULL
+
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC2_CHECK_CPU_STATE)(
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex,
+ OUT SMM_CPU_SYNC2_CPU_STATE *CpuState
+ );
+
+
+/**
+ Change CPU's SMM enabling state.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @param CpuIndex Index of the CPU to enable / disable SMM
+
+ @param Enable If TRUE, enable SMM; if FALSE disable SMM
+
+ @retval EFI_SUCCESS The CPU's SMM enabling state is changed.
+
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+
+ @retval EFI_UNSUPPORTED Returns EFI_UNSUPPORTED the CPU does not support dynamically enabling / disabling SMI
+
+ @retval EFI_DEVICE_ERROR Error occured in changing SMM enabling state.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC2_CHANGE_SMM_ENABLING)(
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex,
+ IN BOOLEAN Enable
+ );
+
+
+/**
+ Send SMI IPI to a specific CPU
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @param CpuIndex Index of the CPU to send SMI to. "-1" means all-exclude-self.
+
+ @retval EFI_SUCCESS The SMI IPI is sent successfully.
+
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+
+ @retval EFI_DEVICE_ERROR Error occured in sending SMI IPI.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC2_SEND_SMI)(
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex
+ );
+
+
+/**
+ Send SMI IPI to all CPUs excluding self
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The SMI IPI is sent successfully.
+
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+
+ @retval EFI_DEVICE_ERROR Error occured in sending SMI IPI.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SMM_CPU_SYNC2_SEND_SMI_ALL_EXCLUDING_SELF)(
+ IN SMM_CPU_SYNC2_PROTOCOL *This
+ );
+
+/**
+ This protocol provides services on SMM CPU syncrhonization related status and controls
+**/
+struct _SMM_CPU_SYNC2_PROTOCOL {
+ SMM_CPU_SYNC2_CHECK_AP_ARRIVAL CheckApArrival;
+ SMM_CPU_SYNC2_SET_MODE SetMode;
+ SMM_CPU_SYNC2_GET_MODE GetMode;
+ SMM_CPU_SYNC2_CHECK_CPU_STATE CheckCpuState;
+ SMM_CPU_SYNC2_CHANGE_SMM_ENABLING ChangeSmmEnabling;
+ SMM_CPU_SYNC2_SEND_SMI SendSmi;
+ SMM_CPU_SYNC2_SEND_SMI_ALL_EXCLUDING_SELF SendSmiAllExcludingSelf;
+};
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gSmmCpuSync2ProtocolGuid;
+
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfig.c b/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfig.c
new file mode 100644
index 0000000..3d7cf51
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfig.c
@@ -0,0 +1,1002 @@
+/** @file
+
+ CPU Configuration Library.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: CpuConfig.c
+
+**/
+
+
+#include "CpuConfig.h"
+
+CPU_CONFIG_CONTEXT_BUFFER *mCpuConfigLibConfigConextBuffer;
+
+/**
+ The constructor function of CPU Configuration Library.
+
+ The constructor function caches the value of PCD entry PcdCpuConfigContextBuffer.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuConfigLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Get the pointer to CPU Configuration Context Buffer from PcdCpuConfigContextBuffer.
+ // This PCD entry is set by CPU driver.
+ //
+ mCpuConfigLibConfigConextBuffer = (CPU_CONFIG_CONTEXT_BUFFER *) (UINTN) PcdGet64 (PcdCpuConfigContextBuffer);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set feature capability and related attribute.
+
+ This function sets the feature capability and its attribute.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureID The ID of the feature.
+ @param Attribute Feature-specific data.
+
+**/
+VOID
+EFIAPI
+SetProcessorFeatureCapability (
+ IN UINTN ProcessorNumber,
+ IN CPU_FEATURE_ID FeatureID,
+ IN VOID *Attribute
+ )
+{
+ CPU_COLLECTED_DATA *CpuCollectedData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
+
+ //
+ // Set the feature capability of the specified processor as TRUE,
+ // and set feature-specified attribute for the feature.
+ //
+ CpuCollectedData->FeatureData[FeatureID].Capability = TRUE;
+ CpuCollectedData->FeatureData[FeatureID].Attribute = Attribute;
+}
+
+/**
+ Clears feature capability and related attribute.
+
+ This function clears the feature capability and its attribute.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureID The ID of the feature.
+
+**/
+VOID
+EFIAPI
+ClearProcessorFeatureCapability (
+ IN UINTN ProcessorNumber,
+ IN CPU_FEATURE_ID FeatureID
+ )
+{
+ CPU_COLLECTED_DATA *CpuCollectedData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
+
+ //
+ // Set the feature capability of the specified processor as FALSE,
+ // and clears feature-specified attribute for the feature.
+ //
+ CpuCollectedData->FeatureData[FeatureID].Capability = FALSE;
+ CpuCollectedData->FeatureData[FeatureID].Attribute = NULL;
+}
+
+/**
+ Get feature capability and related attribute.
+
+ This function gets the feature capability and its attribute.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureID The ID of the feature.
+ @param Attribute Pointer to the output feature-specific data.
+
+ @retval TRUE The feature is supported by the processor
+ @retval FALSE The feature is not supported by the processor
+
+**/
+BOOLEAN
+EFIAPI
+GetProcessorFeatureCapability (
+ IN UINTN ProcessorNumber,
+ IN CPU_FEATURE_ID FeatureID,
+ OUT VOID **Attribute OPTIONAL
+ )
+{
+ CPU_COLLECTED_DATA *CpuCollectedData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
+
+ //
+ // If Attribute is not NULL, set feature-specified attribute to it.
+ //
+ if (Attribute != NULL) {
+ *Attribute = CpuCollectedData->FeatureData[FeatureID].Attribute;
+ }
+
+ return CpuCollectedData->FeatureData[FeatureID].Capability;
+}
+
+/**
+ Get the number of CPUID leafs of various types.
+
+ This function get the number of CPUID leafs of various types.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param CpuidType The type of the cpu id.
+
+ @return Maximal index of CPUID instruction for basic leafs.
+
+**/
+UINTN
+EFIAPI
+GetNumberOfCpuidLeafs (
+ IN UINTN ProcessorNumber,
+ IN CPUID_TYPE CpuidType
+ )
+{
+ UINTN NumberOfLeafs;
+ CPU_CPUID_DATA *CpuidData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
+
+ switch (CpuidType) {
+ case BasicCpuidLeaf:
+ NumberOfLeafs = CpuidData->NumberOfBasicCpuidLeafs;
+ break;
+ case ExtendedCpuidLeaf:
+ NumberOfLeafs = CpuidData->NumberOfExtendedCpuidLeafs;
+ break;
+ case CacheAndTlbCpuidLeafs:
+ NumberOfLeafs = CpuidData->NumberOfCacheAndTlbCpuidLeafs;
+ break;
+ case DeterministicCacheParametersCpuidLeafs:
+ NumberOfLeafs = CpuidData->NumberOfDeterministicCacheParametersCpuidLeafs;
+ break;
+ case ExtendedTopologyEnumerationCpuidLeafs:
+ NumberOfLeafs = CpuidData->NumberOfExtendedTopologyEnumerationLeafs;
+ break;
+ default:
+ NumberOfLeafs = 0;
+ break;
+ }
+
+ return NumberOfLeafs;
+}
+
+/**
+ Get the pointer to specified CPUID leaf.
+
+ This function gets the pointer to specified CPUID leaf.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param Index Index of the CPUID leaf.
+
+ @return Pointer to specified CPUID leaf
+
+**/
+EFI_CPUID_REGISTER*
+EFIAPI
+GetProcessorCpuid (
+ IN UINTN ProcessorNumber,
+ IN UINTN Index
+)
+{
+ CPU_CPUID_DATA *CpuidData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
+
+ //
+ // If Index specifies basic CPUID leafs, then locate basic leaf to return.
+ //
+ if (Index < CpuidData->NumberOfBasicCpuidLeafs) {
+ return (&CpuidData->CpuIdLeaf[Index]);
+ }
+
+ //
+ // If Index specifies extended CPUID leafs, then locate extended leaf to return.
+ //
+ if (Index >= 0x80000000 && Index < 0x80000000 + CpuidData->NumberOfExtendedCpuidLeafs) {
+ return (&CpuidData->CpuIdLeaf[Index - 0x80000000 + CpuidData->NumberOfBasicCpuidLeafs]);
+ }
+
+ //
+ // If Index specifies invalid CPUID index, then return NULL.
+ //
+ return NULL;
+}
+
+/**
+ Get the pointer to specified CPUID leaf of cache and TLB parameters.
+
+ This function gets the pointer to specified CPUID leaf of cache and TLB parameters.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param Index Index of the CPUID leaf.
+
+ @return Pointer to specified CPUID leaf.
+
+**/
+EFI_CPUID_REGISTER*
+EFIAPI
+GetCacheAndTlbCpuidLeaf (
+ IN UINTN ProcessorNumber,
+ IN UINTN Index
+)
+{
+ UINTN StartIndex;
+ CPU_CPUID_DATA *CpuidData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
+
+ //
+ // The first leaf resides in basic leaf 2
+ //
+ if (Index == 0) {
+ return (&CpuidData->CpuIdLeaf[2]);
+ }
+
+ //
+ // If index is greater than zero, calculate the start index of deterministic cache CPUID leafs.
+ //
+ StartIndex = CpuidData->NumberOfBasicCpuidLeafs + CpuidData->NumberOfExtendedCpuidLeafs;
+
+ return (&CpuidData->CpuIdLeaf[Index + StartIndex - 1]);
+}
+
+/**
+ Get the pointer to specified CPUID leaf of deterministic cache parameters.
+
+ This function gets the pointer to specified CPUID leaf of deterministic cache parameters.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param Index Index of the CPUID leaf.
+
+ @return Pointer to specified CPUID leaf.
+
+**/
+EFI_CPUID_REGISTER*
+EFIAPI
+GetDeterministicCacheParametersCpuidLeaf (
+ IN UINTN ProcessorNumber,
+ IN UINTN Index
+)
+{
+ UINTN StartIndex;
+ CPU_CPUID_DATA *CpuidData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
+
+ //
+ // Calculate the start index of deterministic cache CPUID leafs.
+ //
+ StartIndex = CpuidData->NumberOfBasicCpuidLeafs;
+ StartIndex += CpuidData->NumberOfExtendedCpuidLeafs;
+ StartIndex += CpuidData->NumberOfCacheAndTlbCpuidLeafs - 1;
+
+ return (&CpuidData->CpuIdLeaf[Index + StartIndex]);
+}
+
+/**
+ Get the pointer to specified CPUID leaf of Extended Topology Enumeration.
+
+ This function gets the pointer to specified CPUID leaf of Extended Topology Enumeration.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+ @param Index Index of the CPUID leaf.
+
+ @return Pointer to specified CPUID leaf.
+
+**/
+EFI_CPUID_REGISTER*
+EFIAPI
+GetExtendedTopologyEnumerationCpuidLeafs (
+ IN UINTN ProcessorNumber,
+ IN UINTN Index
+ )
+{
+ UINTN StartIndex;
+ CPU_CPUID_DATA *CpuidData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
+
+ //
+ // Calculate the start index of Extended Topology Enumeration CPUID leafs.
+ //
+ StartIndex = CpuidData->NumberOfBasicCpuidLeafs;
+ StartIndex += CpuidData->NumberOfExtendedCpuidLeafs;
+ StartIndex += CpuidData->NumberOfCacheAndTlbCpuidLeafs - 1;
+ StartIndex += CpuidData->NumberOfDeterministicCacheParametersCpuidLeafs;
+
+ return (&CpuidData->CpuIdLeaf[Index + StartIndex]);
+}
+
+/**
+ Get the version information of specified logical processor.
+
+ This function gets the version information of specified logical processor,
+ including family ID, model ID, stepping ID and processor type.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param DisplayedFamily Pointer to family ID for output
+ @param DisplayedModel Pointer to model ID for output
+ @param SteppingId Pointer to stepping ID for output
+ @param ProcessorType Pointer to processor type for output
+
+**/
+VOID
+EFIAPI
+GetProcessorVersionInfo (
+ IN UINTN ProcessorNumber,
+ OUT UINT32 *DisplayedFamily OPTIONAL,
+ OUT UINT32 *DisplayedModel OPTIONAL,
+ OUT UINT32 *SteppingId OPTIONAL,
+ OUT UINT32 *ProcessorType OPTIONAL
+ )
+{
+ EFI_CPUID_REGISTER *VersionInfo;
+ UINT32 RegEax;
+ UINT32 FamilyId;
+ UINT32 ExtendedFamilyId;
+ UINT32 ExtendedModelId;
+
+ //
+ // Get CPUID(1).EAX
+ //
+ VersionInfo = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_VERSION_INFO);
+ ASSERT (VersionInfo != NULL);
+ RegEax = VersionInfo->RegEax;
+
+ //
+ // Processor Type is CPUID(1).EAX[12:13]
+ //
+ if (ProcessorType != NULL) {
+ *ProcessorType = BitFieldRead32 (RegEax, 12, 13);
+ }
+
+ //
+ // Stepping ID is CPUID(1).EAX[0:3]
+ //
+ if (SteppingId != NULL) {
+ *SteppingId = BitFieldRead32 (RegEax, 0, 3);
+ }
+
+ //
+ // The Extended Family ID needs to be examined only when the Family ID is 0FH.
+ // If Family ID is 0FH, Displayed Family ID = Family ID + Extended Family ID.
+ // Otherwise, Displayed Family ID is Family ID
+ //
+ FamilyId = BitFieldRead32 (RegEax, 8, 11);
+ if (DisplayedFamily != NULL) {
+ *DisplayedFamily = FamilyId;
+ if (FamilyId == 0x0f) {
+ ExtendedFamilyId = BitFieldRead32 (RegEax, 20, 27);
+ *DisplayedFamily += ExtendedFamilyId;
+ }
+ }
+
+ //
+ // The Extended Model ID needs to be examined only when the Family ID is 06H or 0FH.
+ // If Family ID is 06H or 0FH, Displayed Model ID = Model ID + (Extended Model ID << 4).
+ // Otherwise, Displayed Model ID is Model ID.
+ //
+ if (DisplayedModel != NULL) {
+ *DisplayedModel = BitFieldRead32 (RegEax, 4, 7);
+ if (FamilyId == 0x06 || FamilyId == 0x0f) {
+ ExtendedModelId = BitFieldRead32 (RegEax, 16, 19);
+ *DisplayedModel += (ExtendedModelId << 4);
+ }
+ }
+}
+
+/**
+ Get initial local APIC ID of specified logical processor
+
+ This function gets initial local APIC ID of specified logical processor.
+
+ @param ProcessorNumber Handle number of specified logical processor
+
+ @return Initial local APIC ID of specified logical processor
+
+**/
+UINT32
+EFIAPI
+GetInitialLocalApicId (
+ UINTN ProcessorNumber
+ )
+{
+ CPU_COLLECTED_DATA *CpuCollectedData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
+
+ return (CpuCollectedData->CpuidData.CpuIdLeaf[1].RegEbx >> 24) & 0xff;
+}
+
+/**
+ Get the location of specified processor.
+
+ This function gets the location of specified processor, including
+ package number, core number within package, thread number within core.
+
+ @param ProcessorNumber Handle number of specified logical processor.
+ @param PackageNumber Pointer to the output package number.
+ @param CoreNumber Pointer to the output core number.
+ @param ThreadNumber Pointer to the output thread number.
+
+**/
+VOID
+EFIAPI
+GetProcessorLocation (
+ IN UINTN ProcessorNumber,
+ OUT UINT32 *PackageNumber OPTIONAL,
+ OUT UINT32 *CoreNumber OPTIONAL,
+ OUT UINT32 *ThreadNumber OPTIONAL
+)
+{
+ CPU_COLLECTED_DATA *CpuCollectedData;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
+
+ //
+ // If PackageNumber is not NULL, set the package number of the specified processor to it.
+ //
+ if (PackageNumber != NULL) {
+ *PackageNumber = CpuCollectedData->ProcessorLocation.Package;
+ }
+
+ //
+ // If CoreNumber is not NULL, set the core number within package to it.
+ //
+ if (CoreNumber != NULL) {
+ *CoreNumber = CpuCollectedData->ProcessorLocation.Core;
+ }
+
+ //
+ // If ThreadNumber is not NULL, set the thread number within core to it.
+ //
+ if (ThreadNumber != NULL) {
+ *ThreadNumber = CpuCollectedData->ProcessorLocation.Thread;
+ }
+}
+
+/**
+ Get the Feature entry at specified position in a feature list.
+
+ This function gets the Feature entry at specified position in a feature list.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureIndex The index of the node in feature list.
+ @param Attribute Pointer to output feature-specific attribute
+
+ @return Feature ID of specified feature. CpuFeatureMaximum means not found
+
+**/
+CPU_FEATURE_ID
+EFIAPI
+GetProcessorFeatureEntry (
+ IN UINTN ProcessorNumber,
+ IN UINTN FeatureIndex,
+ OUT VOID **Attribute OPTIONAL
+ )
+{
+ CPU_FEATURE_ENTRY *FeatureEntry;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+
+ if (Attribute != NULL) {
+ *Attribute = NULL;
+ }
+
+ //
+ // Search for specified entry. If not found, return CpuFeatureMaximum.
+ //
+ FeatureEntry = SearchFeatureEntry (ProcessorNumber, FeatureIndex);
+ if (FeatureEntry == NULL) {
+ return CpuFeatureMaximum;
+ }
+
+ //
+ // If Attribute is not NULL, set the feature-specified attribute to it.
+ //
+ if (Attribute != NULL) {
+ *Attribute = FeatureEntry->Attribute;
+ }
+
+ return (FeatureEntry->FeatureID);
+}
+
+/**
+ Append a feature entry at the end of a feature list.
+
+ This function appends a feature entry at the end of a feature list.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureID ID of the specified feature.
+ @param Attribute Feature-specific attribute.
+
+ @retval EFI_SUCCESS This function always return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+AppendProcessorFeatureIntoList (
+ IN UINTN ProcessorNumber,
+ IN CPU_FEATURE_ID FeatureID,
+ IN VOID *Attribute
+ )
+{
+ LIST_ENTRY *List;
+ CPU_FEATURE_ENTRY *NewEntry;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+ List = &mCpuConfigLibConfigConextBuffer->FeatureLinkListEntry[ProcessorNumber];
+
+ //
+ // Create a new feature node with given Feature ID and feature-specific attribute
+ //
+ NewEntry = CreateFeatureEntry (FeatureID, Attribute);
+
+ //
+ // Append the new node at the end of the list
+ //
+ InsertTailList (List, &(NewEntry->Link));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete a feature entry in a feature list.
+
+ This function deletes a feature entry in a feature list.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureIndex The index of the node in feature list.
+
+ @retval EFI_SUCCESS The feature node successfully removed.
+ @retval EFI_INVALID_PARAMETER FeatureIndex surpasses the length of list.
+
+**/
+EFI_STATUS
+EFIAPI
+DeleteProcessorFeatureFromList (
+ IN UINTN ProcessorNumber,
+ IN UINTN FeatureIndex
+ )
+{
+ CPU_FEATURE_ENTRY *FeatureEntry;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+
+ //
+ // Search for specified entry. If SearchFeatureEntry() returns NULL, then
+ // it means FeatureIndex surpasses the length of list.
+ // Return EFI_INVALID_PARAMETER.
+ //
+ FeatureEntry = SearchFeatureEntry (ProcessorNumber, FeatureIndex);
+ if (FeatureEntry == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Remove the entry from list, and free its memory region.
+ //
+ RemoveEntryList (&(FeatureEntry->Link));
+ FreePool (FeatureEntry);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Insert a feature entry into a feature list.
+
+ This function insert a feature entry into a feature list before a node specified by Feature Index.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureIndex The index of the new node in feature list.
+ @param FeatureID ID of the specified feature.
+ @param Attribute Feature-specific attribute.
+
+ @retval EFI_SUCCESS The feature node successfully inserted.
+ @retval EFI_INVALID_PARAMETER FeatureIndex surpasses the length of list.
+
+**/
+EFI_STATUS
+EFIAPI
+InsertProcessorFeatureIntoList (
+ IN UINTN ProcessorNumber,
+ IN UINTN FeatureIndex,
+ IN CPU_FEATURE_ID FeatureID,
+ IN VOID *Attribute
+ )
+{
+ CPU_FEATURE_ENTRY *FeatureEntry;
+ CPU_FEATURE_ENTRY *NewEntry;
+
+ //
+ // Search for specified entry. If SearchFeatureEntry() returns NULL, then
+ // it means FeatureIndex surpasses the length of list.
+ // Return EFI_INVALID_PARAMETER.
+ //
+ FeatureEntry = SearchFeatureEntry (ProcessorNumber, FeatureIndex);
+ if (FeatureEntry == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Create a new feature node with given Feature ID and feature-specific attribute
+ //
+ NewEntry = CreateFeatureEntry (FeatureID, Attribute);
+
+ //
+ // Insert the new node before specified feature entry.
+ //
+ InsertHeadList (&(FeatureEntry->Link), &(NewEntry->Link));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add an entry in specified register table.
+
+ This function adds an entry in specified register table, with given register type,
+ register index, bit section and value.
+
+ @param PreSmmInit Specify the target register table.
+ If TRUE, the target is the pre-SMM-init register table.
+ If FALSE, the target is the post-SMM-init register table.
+ @param ProcessorNumber Handle number of specified logical processor
+ @param RegisterType Type of the register to program
+ @param Index Index of the register to program
+ @param ValidBitStart Start of the bit section
+ @param ValidBitLength Length of the bit section
+ @param Value Value to write
+
+**/
+VOID
+EFIAPI
+WriteRegisterTableEx (
+ IN BOOLEAN PreSmmInit,
+ IN UINTN ProcessorNumber,
+ IN REGISTER_TYPE RegisterType,
+ IN UINT32 Index,
+ IN UINT8 ValidBitStart,
+ IN UINT8 ValidBitLength,
+ IN UINT64 Value
+ )
+{
+ EFI_STATUS Status;
+ CPU_REGISTER_TABLE *RegisterTable;
+ EFI_PHYSICAL_ADDRESS Address;
+ UINTN AllocatePages;
+
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+
+ if (PreSmmInit) {
+ RegisterTable = &mCpuConfigLibConfigConextBuffer->PreSmmInitRegisterTable[ProcessorNumber];
+ } else {
+ RegisterTable = &mCpuConfigLibConfigConextBuffer->RegisterTable[ProcessorNumber];
+ }
+
+ //
+ // If register table is full, allocate one more page for it.
+ // It must be in ACPI NVS memory under 4G, for consumption by S3 resume.
+ //
+ if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
+ Address = 0xffffffff;
+ AllocatePages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ AllocatePages + 1,
+ &Address
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // If there are records existing in the register table, then copy its contents
+ // to new region and free the old one.
+ //
+ if (RegisterTable->AllocatedSize > 0) {
+ CopyMem (
+ (VOID *) (UINTN) Address,
+ RegisterTable->RegisterTableEntry,
+ RegisterTable->AllocatedSize
+ );
+ //
+ // RegisterTableEntry is allocated by gBS AllocatePages() service.
+ // So, gBS FreePages() servcie is used to free it.
+ //
+ gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) RegisterTable->RegisterTableEntry,
+ AllocatePages
+ );
+ }
+
+ //
+ // Adjust the allocated size and register table base address.
+ //
+ RegisterTable->AllocatedSize += EFI_PAGE_SIZE;
+ RegisterTable->RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) Address;
+ }
+
+ //
+ // Append entry in the register table.
+ //
+ RegisterTable->RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;
+ RegisterTable->RegisterTableEntry[RegisterTable->TableLength].Index = Index;
+ RegisterTable->RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;
+ RegisterTable->RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;
+ RegisterTable->RegisterTableEntry[RegisterTable->TableLength].Value = Value;
+
+ RegisterTable->TableLength++;
+}
+
+/**
+ Add an entry in the post-SMM-init register table.
+
+ This function adds an entry in the post-SMM-init register table, with given register type,
+ register index, bit section and value.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param RegisterType Type of the register to program
+ @param Index Index of the register to program
+ @param ValidBitStart Start of the bit section
+ @param ValidBitLength Length of the bit section
+ @param Value Value to write
+
+**/
+VOID
+EFIAPI
+WriteRegisterTable (
+ IN UINTN ProcessorNumber,
+ IN REGISTER_TYPE RegisterType,
+ IN UINT32 Index,
+ IN UINT8 ValidBitStart,
+ IN UINT8 ValidBitLength,
+ IN UINT64 Value
+ )
+{
+ WriteRegisterTableEx (
+ FALSE,
+ ProcessorNumber,
+ RegisterType,
+ Index,
+ ValidBitStart,
+ ValidBitLength,
+ Value
+ );
+}
+
+/**
+ Add an entry in the pre-SMM-init register table.
+
+ This function adds an entry in the pre-SMM-init register table, with given register type,
+ register index, bit section and value.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param RegisterType Type of the register to program
+ @param Index Index of the register to program
+ @param ValidBitStart Start of the bit section
+ @param ValidBitLength Length of the bit section
+ @param Value Value to write
+
+**/
+VOID
+EFIAPI
+WritePreSmmInitRegisterTable (
+ IN UINTN ProcessorNumber,
+ IN REGISTER_TYPE RegisterType,
+ IN UINT32 Index,
+ IN UINT8 ValidBitStart,
+ IN UINT8 ValidBitLength,
+ IN UINT64 Value
+ )
+{
+ WriteRegisterTableEx (
+ TRUE,
+ ProcessorNumber,
+ RegisterType,
+ Index,
+ ValidBitStart,
+ ValidBitLength,
+ Value
+ );
+}
+
+/**
+ Set the sequence of processor setting.
+
+ This function sets the a processor setting at the position in
+ setting sequence specified by Index.
+
+ @param Index The zero-based index in the sequence.
+ @param ProcessorNumber Handle number of the processor to set.
+
+ @retval EFI_SUCCESS The sequence successfully modified.
+ @retval EFI_INVALID_PARAMETER Index surpasses the boundary of sequence.
+ @retval EFI_NOT_FOUND Processor specified by ProcessorNumber does not exist.
+
+**/
+EFI_STATUS
+SetSettingSequence (
+ IN UINTN Index,
+ IN UINTN ProcessorNumber
+ )
+{
+ ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
+
+ //
+ // Check whether parameter Index is valid.
+ //
+ if (Index >= mCpuConfigLibConfigConextBuffer->NumberOfProcessors) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check whether parameter ProcessorNumber is valid.
+ //
+ if (ProcessorNumber >= mCpuConfigLibConfigConextBuffer->NumberOfProcessors) {
+ return EFI_NOT_FOUND;
+ }
+
+ mCpuConfigLibConfigConextBuffer->SettingSequence[Index] = ProcessorNumber;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PcdCpuCallbackSignal, and then read the value back.
+
+ This function sets PCD entry PcdCpuCallbackSignal. If there is callback
+ function registered on it, the callback function will be triggered, and
+ it may change the value of PcdCpuCallbackSignal. This function then reads
+ the value of PcdCpuCallbackSignal back, the check whether it has been changed.
+
+ @param Value The value to set to PcdCpuCallbackSignal.
+
+ @return The value of PcdCpuCallbackSignal read back.
+
+**/
+UINT8
+SetAndReadCpuCallbackSignal (
+ IN UINT8 Value
+ )
+{
+ //
+ // Set PcdCpuCallbackSignal, and trigger callback function
+ //
+ PcdSet8 (PcdCpuCallbackSignal, Value);
+ //
+ // Read the value of PcdCpuCallbackSignal back. It may have been
+ // changed by callback function.
+ //
+ return (PcdGet8 (PcdCpuCallbackSignal));
+}
+
+/**
+ Worker function to create a new feature entry.
+
+ This is a worker function to create a new feature entry. The new entry is added to
+ the feature list by other functions in the library.
+
+ @param FeatureID The ID of the feature.
+ @param Attribute Feature-specific data.
+
+ @return Pointer to the created entry.
+
+**/
+CPU_FEATURE_ENTRY *
+CreateFeatureEntry (
+ IN CPU_FEATURE_ID FeatureID,
+ IN VOID *Attribute
+ )
+{
+ CPU_FEATURE_ENTRY *Node;
+
+ Node = AllocateZeroPool (sizeof (CPU_FEATURE_ENTRY));
+ ASSERT (Node != NULL);
+
+ Node->Signature = EFI_CPU_FEATURE_ENTRY_SIGNATURE;
+ Node->FeatureID = FeatureID;
+ Node->Attribute = Attribute;
+
+ return Node;
+}
+
+/**
+ Worker function to search for a feature entry in processor feature list.
+
+ This is a worker function to search for a feature entry in processor feature list.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureIndex The index of the node in feature list.
+
+ @return Pointer to the feature node. If FeatureIndex surpasses the length of list, NULL is returned.
+
+**/
+CPU_FEATURE_ENTRY *
+SearchFeatureEntry (
+ IN UINTN ProcessorNumber,
+ IN UINTN FeatureIndex
+ )
+{
+ LIST_ENTRY *List;
+ LIST_ENTRY *Link;
+ CPU_FEATURE_ENTRY *FeatureEntry;
+ UINTN Index;
+
+ List = &mCpuConfigLibConfigConextBuffer->FeatureLinkListEntry[ProcessorNumber];
+
+ //
+ // Get the first node in list. If list is empty, return NULL.
+ //
+ Link = GetFirstNode (List);
+ if (IsNull (List, Link)) {
+ return NULL;
+ }
+
+ //
+ // Try to get the node specified by Index. If not found, return NULL.
+ //
+ for (Index = 1; Index < FeatureIndex; Index++) {
+ Link = GetNextNode (List, Link);
+ if (IsNull (List, Link)) {
+ return NULL;
+ }
+ }
+
+ FeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Link);
+ return FeatureEntry;
+}
diff --git a/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfig.h b/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfig.h
new file mode 100644
index 0000000..2dbe16a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfig.h
@@ -0,0 +1,92 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ CpuConfig.h
+
+Abstract:
+
+ Header for the status code data hub logging component
+
+**/
+
+#ifndef _CPU_CONFIG_H_
+#define _CPU_CONFIG_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/MpService.h>
+
+#include <Library/CpuConfigLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/SocketLga775Lib.h>
+
+/**
+ Worker function to create a new feature entry.
+
+ This is a worker function to create a new feature entry. The new entry is added to
+ the feature list by other functions in the library.
+
+ @param FeatureID The ID of the feature.
+ @param Attribute Feature-specific data.
+
+ @return The address of the created entry.
+
+**/
+CPU_FEATURE_ENTRY *
+CreateFeatureEntry (
+ IN CPU_FEATURE_ID FeatureID,
+ IN VOID *Attribute
+ );
+
+/**
+ Worker function to search for a feature entry in processor feature list.
+
+ This is a worker function to search for a feature entry in processor feature list.
+
+ @param ProcessorNumber Handle number of specified logical processor
+ @param FeatureIndex The index of the new node in feature list.
+
+ @return Pointer to the feature node. If not found, NULL is returned.
+
+**/
+CPU_FEATURE_ENTRY *
+SearchFeatureEntry (
+ IN UINTN ProcessorNumber,
+ IN UINTN FeatureIndex
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf b/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf
new file mode 100644
index 0000000..79cb215
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf
@@ -0,0 +1,74 @@
+## @file
+# Component description file for CPU Configuration Library.
+#
+# CPU Configuration Library implementation that retrieves data in Processor
+# Configuration Context Buffer.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuConfigLib
+ FILE_GUID = 041bf780-dc3e-49ab-1111-4b8607540000
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuConfigLib
+
+ CONSTRUCTOR = CpuConfigLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ CpuConfig.h
+ CpuConfig.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+
+
+[Pcd]
+ gEfiCpuTokenSpaceGuid.PcdCpuCallbackSignal
+ gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer
+
diff --git a/IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.c b/IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.c
new file mode 100644
index 0000000..4a2f83b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.c
@@ -0,0 +1,340 @@
+/** @file
+ Timer Library functions built upon local APIC on IA32/x64.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Base.h>
+
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/SocketLga775Lib.h>
+#include <Library/LocalApicLib.h>
+
+//
+// The following array is FSB frequencies defined in Pentinum family
+// CPUs, its value unit is HZ.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 mPentinumFSBFrequencies[] = {
+ 400000000
+};
+
+/**
+ The function to get CPU intended FSB frequency.
+
+ This function reads the type of CPU by CPUID and returns FSB frequecny,
+ if CPU not supportted, then ASSERT().
+
+ @retval CPU intended FSB frequency.
+
+**/
+UINT32
+GetIntendFsbFrequency (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT32 BasicFamilyId;
+ UINT32 FamilyId;
+ UINT32 ModelId;
+ UINT32 ExtendedModelId;
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
+
+ //
+ // The Extended Family ID needs to be examined only when the Family ID is 0FH.
+ //
+ BasicFamilyId = BitFieldRead32 (RegEax, 8, 11);
+ FamilyId = BasicFamilyId;
+ if (BasicFamilyId == 0x0F) {
+ FamilyId += BitFieldRead32 (RegEax, 20, 27);
+ }
+
+ //
+ // The Extended Model ID needs to be examined only when the Family ID is 06H or 0FH.
+ //
+ ModelId = BitFieldRead32 (RegEax, 4, 7);
+ if (BasicFamilyId == 0x06 || BasicFamilyId == 0x0f) {
+ ExtendedModelId = BitFieldRead32 (RegEax, 16, 19);
+ ModelId += ExtendedModelId << 4;
+ }
+
+ switch (FamilyId) {
+ case PENTIUM_FAMILY_ID:
+ //
+ // It's Pentinum Family CPUs.
+ //
+ switch (ModelId) {
+ case QUARK_MODEL_ID:
+ return mPentinumFSBFrequencies[0];
+ }
+ break;
+ }
+
+ //
+ // Always assert() for those unsupported CPUs
+ //
+ ASSERT (FALSE);
+
+ return (UINT32) -1;
+}
+
+
+/**
+ Internal function to return the frequency of the local APIC timer.
+
+ Internal function to return the frequency of the local APIC timer.
+
+ @return The frequency of the timer in Hz.
+
+**/
+UINT32
+InternalX86GetTimerFrequency (
+ VOID
+ )
+{
+ UINT32 Freq;
+ UINTN DivideValue;
+
+ Freq = GetIntendFsbFrequency ();
+ GetApicTimerState (&DivideValue, NULL, NULL);
+ return Freq / ((UINT32) DivideValue);
+}
+
+/**
+ Internal function to read the current tick counter of local APIC.
+
+ Internal function to read the current tick counter of local APIC.
+
+ @return The tick counter read.
+
+**/
+INT32
+InternalX86GetTimerTick (
+ VOID
+ )
+{
+ return GetApicTimerCurrentCount ();
+}
+
+/**
+ Stalls the CPU for at least the given number of ticks.
+
+ Stalls the CPU for at least the given number of ticks. It's invoked by
+ MicroSecondDelay() and NanoSecondDelay().
+
+ @param Delay A period of time to delay in ticks.
+
+**/
+VOID
+InternalX86Delay (
+ IN UINT32 Delay
+ )
+{
+ INT32 Ticks;
+
+ //
+ // The target timer count is calculated here
+ //
+ Ticks = InternalX86GetTimerTick () - Delay;
+
+ //
+ // Wait until time out
+ // Delay > 2^31 could not be handled by this function
+ // Timer wrap-arounds are handled correctly by this function
+ //
+ while (InternalX86GetTimerTick () - Ticks >= 0);
+}
+
+/**
+ Stalls the CPU for at least the given number of microseconds.
+
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param MicroSeconds The minimum number of microseconds to delay.
+
+ @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+ InternalX86Delay (
+ (UINT32)DivU64x32 (
+ MultU64x64 (
+ InternalX86GetTimerFrequency (),
+ MicroSeconds
+ ),
+ 1000000u
+ )
+ );
+ return MicroSeconds;
+}
+
+/**
+ Stalls the CPU for at least the given number of nanoseconds.
+
+ Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+ @param NanoSeconds The minimum number of nanoseconds to delay.
+
+ @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+ IN UINTN NanoSeconds
+ )
+{
+ InternalX86Delay (
+ (UINT32)DivU64x32 (
+ MultU64x64 (
+ InternalX86GetTimerFrequency (),
+ NanoSeconds
+ ),
+ 1000000000u
+ )
+ );
+ return NanoSeconds;
+}
+
+/**
+ Retrieves the current value of a 64-bit free running performance counter.
+
+ Retrieves the current value of a 64-bit free running performance counter. The
+ counter can either count up by 1 or count down by 1. If the physical
+ performance counter counts by a larger increment, then the counter values
+ must be translated. The properties of the counter can be retrieved from
+ GetPerformanceCounterProperties().
+
+ @return The current value of the free running performance counter.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounter (
+ VOID
+ )
+{
+ return (UINT64)(UINT32)InternalX86GetTimerTick ();
+}
+
+/**
+ Retrieves the 64-bit frequency in Hz and the range of performance counter
+ values.
+
+ If StartValue is not NULL, then the value that the performance counter starts
+ with immediately after is it rolls over is returned in StartValue. If
+ EndValue is not NULL, then the value that the performance counter end with
+ immediately before it rolls over is returned in EndValue. The 64-bit
+ frequency of the performance counter in Hz is always returned. If StartValue
+ is less than EndValue, then the performance counter counts up. If StartValue
+ is greater than EndValue, then the performance counter counts down. For
+ example, a 64-bit free running counter that counts up would have a StartValue
+ of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+ that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+ @param StartValue The value the performance counter starts with when it
+ rolls over.
+ @param EndValue The value that the performance counter ends with before
+ it rolls over.
+
+ @return The frequency in Hz.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+ OUT UINT64 *StartValue, OPTIONAL
+ OUT UINT64 *EndValue OPTIONAL
+ )
+{
+ if (StartValue != NULL) {
+ *StartValue = GetApicTimerInitCount ();
+ }
+
+ if (EndValue != NULL) {
+ *EndValue = 0;
+ }
+
+ return (UINT64) InternalX86GetTimerFrequency ();
+}
+
+/**
+ Converts elapsed ticks of performance counter to time in nanoseconds.
+
+ This function converts the elapsed ticks of running performance counter to
+ time value in unit of nanoseconds.
+
+ @param Ticks The number of elapsed ticks of running performance counter.
+
+ @return The elapsed time in nanoseconds.
+
+**/
+UINT64
+EFIAPI
+GetTimeInNanoSecond (
+ IN UINT64 Ticks
+ )
+{
+ UINT64 Frequency;
+ UINT64 NanoSeconds;
+ UINT64 Remainder;
+ INTN Shift;
+
+ Frequency = GetPerformanceCounterProperties (NULL, NULL);
+
+ //
+ // Ticks
+ // Time = --------- x 1,000,000,000
+ // Frequency
+ //
+ NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
+
+ //
+ // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
+ // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
+ // i.e. highest bit set in Remainder should <= 33.
+ //
+ Shift = MAX (0, HighBitSet64 (Remainder) - 33);
+ Remainder = RShiftU64 (Remainder, (UINTN) Shift);
+ Frequency = RShiftU64 (Frequency, (UINTN) Shift);
+ NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
+
+ return NanoSeconds;
+}
diff --git a/IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.inf b/IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.inf
new file mode 100644
index 0000000..3568c8f
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.inf
@@ -0,0 +1,66 @@
+## @file
+# Component description file for Baser Timer Library
+#
+# Timer Library that only uses CPU resources to provide calibrated
+# delays on IA-32 and x64. Note: Because CpuLocalApci timer could be programmed
+# by OS, it cannot be used by SMM drivers and runtime drivers, ACPI timer is
+# recommended for SMM drivers and runtime drivers.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuLocalApicTimerLib
+ FILE_GUID = cceaaf66-aa18-40b1-bfda-e826bc626ddd
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TimerLib|BASE DXE_CORE DXE_DRIVER PEIM PEI_CORE SEC UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ CpuLocalApicTimerLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ DebugLib
+ IoLib
+ BaseLib
+ LocalApicLib
+
diff --git a/IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.c b/IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.c
new file mode 100644
index 0000000..6d13536
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.c
@@ -0,0 +1,53 @@
+/** @file
+ Null instance of Cpu-Only Reset Lib.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: CpuOnlyResetLibNull.c
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <Base.h>
+
+/**
+ Provides null implementation for Cpu-Only Reset Lib.
+ This function provides null implementation for Cpu-Only Reset Lib.
+
+**/
+VOID
+EFIAPI
+CpuOnlyReset(
+ VOID
+ )
+{
+ return;
+}
diff --git a/IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf b/IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf
new file mode 100644
index 0000000..a46ef11
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf
@@ -0,0 +1,76 @@
+## @file
+# Library functions for CpuOnlyResetLib.
+#
+# Null instance of Cpu-Only Reset Lib.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuOnlyResetLibNull
+ FILE_GUID = 20fca949-1012-4c9d-8d7c-b15ca6344504
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuOnlyResetLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+ CpuOnlyResetLibNull.c
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
diff --git a/IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.c b/IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.c
new file mode 100644
index 0000000..2b2648a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.c
@@ -0,0 +1,101 @@
+/** @file
+ Null instance of Platform Sec Lib.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+
+
+/**
+ A developer supplied function to perform platform specific operations.
+
+ It's a developer supplied function to perform any operations appropriate to a
+ given platform. It's invoked just before passing control to PEI core by SEC
+ core. Platform developer may modify the SecCoreData passed to PEI Core.
+ It returns a platform specific PPI list that platform wishes to pass to PEI core.
+ The Generic SEC core module will merge this list to join the final list passed to
+ PEI core.
+
+ @param SecCoreData The same parameter as passing to PEI core. It
+ could be overridden by this function.
+
+ @return The platform specific PPI list to be passed to PEI core or
+ NULL if there is no need of such platform specific PPI list.
+
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+EFIAPI
+SecPlatformMain (
+ IN OUT EFI_SEC_PEI_HAND_OFF *SecCoreData
+ )
+{
+ return NULL;
+}
+
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param StructureSize Pointer to the variable describing size of the input buffer.
+ @param 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 CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function provides dummy function so that SecCore can pass pass build
+ Validation in IA32FamilyCpuBasePkg. All real platform library instances needs
+ to implement the real entry point in assembly.
+**/
+VOID
+EFIAPI
+_ModuleEntryPoint (
+ VOID
+ )
+{
+ return;
+}
diff --git a/IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf b/IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
new file mode 100644
index 0000000..b74b5f7
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -0,0 +1,76 @@
+## @file
+# Library functions for PlatformSecLib.
+#
+# Null instance of Platform Sec Lib.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformSecLibNull
+ FILE_GUID = 6695974D-968C-420b-80B9-7870CD20118F
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformSecLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+ PlatformSecLibNull.c
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
diff --git a/IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.c b/IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.c
new file mode 100644
index 0000000..648735e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.c
@@ -0,0 +1,143 @@
+/** @file
+
+ CPU Configuration Library.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Library/SmmCpuPlatformHookLib.h>
+
+
+/**
+ Checks if platform produces a valid SMI.
+
+ This function checks if platform produces a valid SMI. This function is
+ called at SMM entry to detect if this is a spurious SMI. This function
+ must be implemented in an MP safe way because it is called by multiple CPU
+ threads.
+
+ @retval TRUE There is a valid SMI
+ @retval FALSE There is no valid SMI
+
+**/
+BOOLEAN
+EFIAPI
+PlatformValidSmi (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+/**
+ Clears platform top level SMI status bit.
+
+ This function clears platform top level SMI status bit.
+
+ @retval TRUE The platform top level SMI status is cleared.
+ @retval FALSE The paltform top level SMI status cannot be cleared.
+
+**/
+BOOLEAN
+EFIAPI
+ClearTopLevelSmiStatus (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+/**
+ Performs platform specific way of SMM BSP election.
+
+ This function performs platform specific way of SMM BSP election.
+
+ @param IsBsp Output parameter. TRUE: the CPU this function executes
+ on is elected to be the SMM BSP. FALSE: the CPU this
+ function executes on is to be SMM AP.
+
+ @retval EFI_SUCCESS The function executes successfully.
+ @retval EFI_NOT_READY The function does not determine whether this CPU should be
+ BSP or AP. This may occur if hardware init sequence to
+ enable the determination is yet to be done, or the function
+ chooses not to do BSP election and will let SMM CPU driver to
+ use its default BSP election process.
+ @retval EFI_DEVICE_ERROR The function cannot determine whether this CPU should be
+ BSP or AP due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSmmBspElection (
+ OUT BOOLEAN *IsBsp
+ )
+{
+ return EFI_NOT_READY;
+}
+
+/**
+ Get platform page table attribute .
+
+ This function gets page table attribute of platform.
+
+ @param Address Input parameter. Obtain the page table entries attribute on this address.
+ @param PageSize Output parameter. The size of the page.
+ @param NumOfPages Output parameter. Number of page.
+ @param PageAttribute Output parameter. Paging Attributes (WB, UC, etc).
+
+ @retval EFI_SUCCESS The platform page table attribute from the address is determined.
+ @retval EFI_UNSUPPORTED The paltform not supoort to get page table attribute from the address.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformPageTableAttribute (
+ IN UINT64 Address,
+ IN OUT SMM_PAGE_SIZE_TYPE *PageSize,
+ IN OUT UINTN *NumOfPages,
+ IN OUT UINTN *PageAttribute
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Platform hook called when exiting SMM.
+
+**/
+VOID
+EFIAPI
+PlatformSmmExitProcessing (
+ VOID
+ )
+{
+}
diff --git a/IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf b/IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf
new file mode 100644
index 0000000..b97baed
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf
@@ -0,0 +1,65 @@
+## @file
+# Component description file for CPU Configuration Library.
+#
+# CPU Configuration Library implementation that retrieves data in Processor
+# Configuration Context Buffer.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmCpuPlatformHookLibNull
+ FILE_GUID = 1328AEBC-010B-46ec-832E-1DB2890C2452
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SmmCpuPlatformHookLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+[Sources]
+ SmmCpuPlatformHookLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.c b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.c
new file mode 100644
index 0000000..fcf2a7d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.c
@@ -0,0 +1,449 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PiSmmCommunicationPei.c
+
+Abstract:
+
+ PiSmmCommunication PEI Driver.
+
+**/
+
+#include <PiPei.h>
+#include <PiDxe.h>
+#include <PiSmm.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/SmmCommunication.h>
+#include <Ppi/SmmCommunication.h>
+#include <Ppi/SmmAccess.h>
+#include <Ppi/SmmControl.h>
+#include <Guid/AcpiS3Context.h>
+
+#include "PiSmmCommunicationPrivate.h"
+
+/**
+ the whole picture is below:
+
+ +----------------------------------+
+ | ACPI_VARIABLE_HOB |
+ | SmramDescriptor | <- DRAM
+ | CpuStart |
+ +----------------------------------+---
+ |
+ +----------------------------------+<--
+ | SMM_S3_RESUME_STATE |
+ | Signature | <- SMRAM
+ | Smst |
+ +----------------------------------+---
+ |
+ +----------------------------------+<--
+ | EFI_SMM_SYSTEM_TABLE2 |
+ | NumberOfTableEntries | <- SMRAM
+ | SmmConfigurationTable |
+ +----------------------------------+---
+ |
+ +----------------------------------+<--
+ | EFI_SMM_COMMUNICATION_CONTEXT |
+ | SwSmiNumber | <- SMRAM
+ | AcpiTableAddress |
+ +----------------------------------+---
+ |
+ +----------------------------------+<--
+ | EFI_SMM_COMMUNICATION_ACPI_TABLE |
+ | SwSmiNumber | <- AcpiNvs
+ | BufferPtrAddress |
+ +----------------------------------+---
+ |
+ +----------------------------------+<--
+ | EFI_SMM_COMMUNICATE_HEADER |
+ | HeaderGuid | <- DRAM
+ | MessageLength |
+ +----------------------------------+
+
+**/
+
+#if defined (MDE_CPU_IA32)
+typedef struct {
+ EFI_TABLE_HEADER Hdr;
+ UINT64 SmmFirmwareVendor;
+ UINT64 SmmFirmwareRevision;
+ UINT64 SmmInstallConfigurationTable;
+ UINT64 SmmIoMemRead;
+ UINT64 SmmIoMemWrite;
+ UINT64 SmmIoIoRead;
+ UINT64 SmmIoIoWrite;
+ UINT64 SmmAllocatePool;
+ UINT64 SmmFreePool;
+ UINT64 SmmAllocatePages;
+ UINT64 SmmFreePages;
+ UINT64 SmmStartupThisAp;
+ UINT64 CurrentlyExecutingCpu;
+ UINT64 NumberOfCpus;
+ UINT64 CpuSaveStateSize;
+ UINT64 CpuSaveState;
+ UINT64 NumberOfTableEntries;
+ UINT64 SmmConfigurationTable;
+} EFI_SMM_SYSTEM_TABLE2_64;
+
+typedef struct {
+ EFI_GUID VendorGuid;
+ UINT64 VendorTable;
+} EFI_CONFIGURATION_TABLE64;
+#endif
+
+#if defined (MDE_CPU_X64)
+typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64;
+typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64;
+#endif
+
+/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
+ @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
+ @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
+ being returned. Zero if the handler does not wish to reply with any data.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
+ @retval EFI_NOT_STARTED The service is NOT started.
+**/
+EFI_STATUS
+EFIAPI
+Communicate (
+ IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommSize
+ );
+
+EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunicationPpi = { Communicate };
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiSmmCommunicationPpiGuid,
+ &mSmmCommunicationPpi
+};
+
+/**
+ Get SMM communication context.
+
+ @return SMM communication context.
+**/
+EFI_SMM_COMMUNICATION_CONTEXT *
+GetCommunicationContext (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
+
+ GuidHob = GetFirstGuidHob (&gEfiPeiSmmCommunicationPpiGuid);
+ ASSERT (GuidHob != NULL);
+
+ SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)GET_GUID_HOB_DATA (GuidHob);
+
+ return SmmCommunicationContext;
+}
+
+/**
+ Set SMM communication context.
+
+ @param SmmCommunicationContext SMM communication context.
+**/
+VOID
+SetCommunicationContext (
+ IN EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN BufferSize;
+
+ BufferSize = sizeof (*SmmCommunicationContext);
+ Hob.Raw = BuildGuidHob (
+ &gEfiPeiSmmCommunicationPpiGuid,
+ BufferSize
+ );
+ ASSERT (Hob.Raw);
+
+ CopyMem ((VOID *)Hob.Raw, SmmCommunicationContext, sizeof(*SmmCommunicationContext));
+}
+
+/**
+ Get VendorTable by VendorGuid in Smst.
+
+ @param Signature Signature of SMM_S3_RESUME_STATE
+ @param Smst SMM system table
+ @param VendorGuid vendor guid
+
+ @return vendor table.
+**/
+VOID *
+InternalSmstGetVendorTableByGuid (
+ IN UINT64 Signature,
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ EFI_CONFIGURATION_TABLE *SmmConfigurationTable;
+ UINTN NumberOfTableEntries;
+ UINTN Index;
+ EFI_SMM_SYSTEM_TABLE2_64 *Smst64;
+ EFI_CONFIGURATION_TABLE64 *SmmConfigurationTable64;
+
+ if ((sizeof(UINTN) == sizeof(UINT32)) && (Signature == SMM_S3_RESUME_SMM_64)) {
+ //
+ // 32 PEI + 64 DXE
+ //
+ Smst64 = (EFI_SMM_SYSTEM_TABLE2_64 *)Smst;
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64->SmmConfigurationTable));
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst64->NumberOfTableEntries));
+ SmmConfigurationTable64 = (EFI_CONFIGURATION_TABLE64 *)(UINTN)Smst64->SmmConfigurationTable;
+ NumberOfTableEntries = (UINTN)Smst64->NumberOfTableEntries;
+ for (Index = 0; Index < NumberOfTableEntries; Index++) {
+ if (CompareGuid (&SmmConfigurationTable64[Index].VendorGuid, VendorGuid)) {
+ return (VOID *)(UINTN)SmmConfigurationTable64[Index].VendorTable;
+ }
+ }
+ return NULL;
+ } else {
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst->SmmConfigurationTable));
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst->NumberOfTableEntries));
+ SmmConfigurationTable = Smst->SmmConfigurationTable;
+ NumberOfTableEntries = Smst->NumberOfTableEntries;
+ for (Index = 0; Index < NumberOfTableEntries; Index++) {
+ if (CompareGuid (&SmmConfigurationTable[Index].VendorGuid, VendorGuid)) {
+ return (VOID *)SmmConfigurationTable[Index].VendorTable;
+ }
+ }
+ return NULL;
+ }
+}
+
+/**
+ Init SMM communication context.
+**/
+VOID
+InitCommunicationContext (
+ VOID
+ )
+{
+ EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
+ SMM_S3_RESUME_STATE *SmmS3ResumeState;
+ VOID *GuidHob;
+ EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
+
+ GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+ ASSERT (GuidHob != NULL);
+ SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
+ SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
+
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState));
+ DEBUG ((EFI_D_INFO, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState->Smst));
+
+ SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)InternalSmstGetVendorTableByGuid (
+ SmmS3ResumeState->Signature,
+ (EFI_SMM_SYSTEM_TABLE2 *)(UINTN)SmmS3ResumeState->Smst,
+ &gEfiPeiSmmCommunicationPpiGuid
+ );
+ ASSERT (SmmCommunicationContext != NULL);
+
+ SetCommunicationContext (SmmCommunicationContext);
+
+ return ;
+}
+
+/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
+ @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
+ @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
+ being returned. Zero if the handler does not wish to reply with any data.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
+ @retval EFI_NOT_STARTED The service is NOT started.
+**/
+EFI_STATUS
+EFIAPI
+Communicate (
+ IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommSize
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_CONTROL_PPI *SmmControl;
+ PEI_SMM_ACCESS_PPI *SmmAccess;
+ UINT8 SmiCommand;
+ UINTN Size;
+ EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;
+ EFI_SMM_COMMUNICATION_ACPI_TABLE *SmmCommunicationAcpiTable;
+
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Enter\n"));
+
+ if (CommBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get needed resource
+ //
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmControlPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmControl
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_STARTED;
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmAccess
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_STARTED;
+ }
+
+ //
+ // Check SMRAM locked, it should be done after SMRAM lock.
+ //
+ if (!SmmAccess->LockState) {
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));
+ return EFI_NOT_STARTED;
+ }
+
+ SmmCommunicationContext = GetCommunicationContext ();
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei AcpiTableAddress - %x\n", (UINTN)SmmCommunicationContext->AcpiTableAddress));
+
+ SmmCommunicationAcpiTable = (EFI_SMM_COMMUNICATION_ACPI_TABLE *)(UINTN)SmmCommunicationContext->AcpiTableAddress;
+ //
+ // No need to check if BufferPtrAddress is 0, because it is in PEI phase.
+ //
+ SmmCommunicationAcpiTable->BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer;
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN)CommBuffer));
+
+ //
+ // Send command
+ //
+ SmiCommand = (UINT8)SmmCommunicationContext->SwSmiNumber;
+ Size = sizeof(SmiCommand);
+ Status = SmmControl->Trigger (
+ (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
+ SmmControl,
+ (INT8 *)&SmiCommand,
+ &Size,
+ FALSE,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Setting BufferPtrAddress to 0 means this transaction is done.
+ //
+ SmmCommunicationAcpiTable->BufferPtrAddress = 0;
+
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Exit\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Entry Point for PI SMM communication PEIM.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Pointer to PEI Services table.
+
+ @retval EFI_SUCEESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+EFIAPI
+PiSmmCommunicationPeiEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_ACCESS_PPI *SmmAccess;
+ EFI_BOOT_MODE BootMode;
+ UINTN Index;
+
+ BootMode = GetBootModeHob ();
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmAccess
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_STARTED;
+ }
+
+ //
+ // Check SMRAM locked, it should be done before SMRAM lock.
+ //
+ if (SmmAccess->LockState) {
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Open all SMRAM
+ //
+ for (Index = 0; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+
+ InitCommunicationContext ();
+
+ PeiServicesInstallPpi (&mPpiList);
+
+ return RETURN_SUCCESS;
+}
diff --git a/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf
new file mode 100644
index 0000000..5416302
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf
@@ -0,0 +1,78 @@
+## @file
+# Component description file for PI SMM Communication PEIM.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PiSmmCommunicationPei
+ FILE_GUID = 1C8B7F78-1699-40e6-AF33-9B995D16B043
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PiSmmCommunicationPeiEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ PiSmmCommunicationPei.c
+ PiSmmCommunicationPrivate.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ PeiServicesTablePointerLib
+ PeiServicesLib
+ BaseLib
+ BaseMemoryLib
+ HobLib
+ DebugLib
+
+[Guids]
+ gEfiAcpiVariableGuid ## CONSUMED
+
+[Ppis]
+ gEfiPeiSmmCommunicationPpiGuid ## PRODUCED
+ gPeiSmmAccessPpiGuid ## CONSUMED
+ gPeiSmmControlPpiGuid ## CONSUMED
+
+[Depex]
+ gPeiSmmAccessPpiGuid AND
+ gPeiSmmControlPpiGuid AND
+ gEfiPeiMasterBootModePpiGuid
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPrivate.h b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPrivate.h
new file mode 100644
index 0000000..7e22768
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPrivate.h
@@ -0,0 +1,56 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PiSmmCommunicationPrivate.h
+
+Abstract:
+
+ PiSmmCommunication private data structure
+
+**/
+
+#ifndef _SMM_COMMUNICATION_PRIVATE_H_
+#define _SMM_COMMUNICATION_PRIVATE_H_
+
+#pragma pack(push, 1)
+
+#define SMM_COMMUNICATION_SIGNATURE SIGNATURE_32 ('S','M','M','C')
+
+typedef struct {
+ UINT32 Signature;
+ UINT32 SwSmiNumber;
+ EFI_PHYSICAL_ADDRESS AcpiTableAddress;
+} EFI_SMM_COMMUNICATION_CONTEXT;
+
+#pragma pack(pop)
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.c b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.c
new file mode 100644
index 0000000..673732b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.c
@@ -0,0 +1,291 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PiSmmCommunicationSmm.c
+
+Abstract:
+
+ PiSmmCommunication SMM Driver.
+
+**/
+
+#include <PiSmm.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <Protocol/SmmCommunication.h>
+#include <Protocol/AcpiTable.h>
+#include <Ppi/SmmCommunication.h>
+#include <Guid/Acpi.h>
+
+#include "PiSmmCommunicationPrivate.h"
+
+EFI_SMM_COMMUNICATION_CONTEXT mSmmCommunicationContext = {
+ SMM_COMMUNICATION_SIGNATURE
+};
+
+EFI_SMM_COMMUNICATION_ACPI_TABLE mSmmCommunicationAcpiTable = {
+ EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE,
+ sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE),
+ 0x1, // Revision
+ 0x0, // Checksum
+ {0x0}, // OemId[6]
+ 0x0, // OemTableId
+ 0x0, // OemRevision
+ 0x0, // CreatorId
+ 0x0, // CreatorRevision
+ {0x0}, // Identifier
+ OFFSET_OF (EFI_SMM_COMMUNICATION_ACPI_TABLE, SwSmiNumber), // DataOffset
+ 0x0, // SwSmiNumber
+ 0x0 // BufferPtrAddress
+};
+
+/**
+ Set SMM communication context.
+**/
+VOID
+SetCommunicationContext (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gSmst->SmmInstallConfigurationTable (
+ gSmst,
+ &gEfiPeiSmmCommunicationPpiGuid,
+ &mSmmCommunicationContext,
+ sizeof(mSmmCommunicationContext)
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Get SMM communication ACPI table address.
+
+ @return SMM communication ACPI table address.
+**/
+EFI_PHYSICAL_ADDRESS
+GetSmmCommunicationAcpiTableAddress (
+ VOID
+ )
+{
+ EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
+ EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
+ EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
+ UINTN Index;
+ UINT32 *TableAddress;
+ UINT64 *XTableAddress;
+ UINTN TableCount;
+ EFI_SMM_COMMUNICATION_ACPI_TABLE *SmmAcpi;
+
+ Rsdp = NULL;
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) ||
+ CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid) ||
+ CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpiTableGuid) ) {
+ //
+ // A match was found.
+ //
+ Rsdp = (EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable;
+ break;
+ }
+ }
+
+ ASSERT (Rsdp != NULL);
+ if (Rsdp == NULL) {
+ return 0;
+ }
+
+ Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
+ TableCount = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32);
+ TableAddress = (UINT32 *)(Rsdt + 1);
+ for (Index = 0; Index < TableCount; Index++) {
+ SmmAcpi = (EFI_SMM_COMMUNICATION_ACPI_TABLE *)(UINTN)TableAddress[Index];
+ if (SmmAcpi == NULL) {
+ continue;
+ }
+ if ((SmmAcpi->UefiAcpiDataTable.Header.Signature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE) &&
+ (SmmAcpi->UefiAcpiDataTable.Header.Length == sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE)) &&
+ CompareGuid (&(SmmAcpi->UefiAcpiDataTable.Identifier), &gEfiSmmCommunicationProtocolGuid) ) {
+ return (EFI_PHYSICAL_ADDRESS)(UINTN)SmmAcpi;
+ }
+ }
+
+ if (Rsdp->Revision >= 2) {
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
+ TableCount = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);
+ XTableAddress = (UINT64 *)(Xsdt + 1);
+ for (Index = 0; Index < TableCount; Index++) {
+ SmmAcpi = (EFI_SMM_COMMUNICATION_ACPI_TABLE *)(UINTN)XTableAddress[Index];
+ if (SmmAcpi == NULL) {
+ continue;
+ }
+ if ((SmmAcpi->UefiAcpiDataTable.Header.Signature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE) &&
+ (SmmAcpi->UefiAcpiDataTable.Header.Length == sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE)) &&
+ CompareGuid (&(SmmAcpi->UefiAcpiDataTable.Identifier), &gEfiSmmCommunicationProtocolGuid) ) {
+ return (EFI_PHYSICAL_ADDRESS)(UINTN)SmmAcpi;
+ }
+ }
+ }
+
+ ASSERT(FALSE);
+ return 0;
+}
+
+/**
+ Dispatch function for a Software SMI handler.
+
+ @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param Context Points to an optional handler context which was specified when the
+ handler was registered.
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS Command is handled successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PiSmmCommunicationHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ EFI_SMM_COMMUNICATION_ACPI_TABLE *SmmCommunicationAcpiTable;
+ UINTN CommSize;
+ EFI_STATUS Status;
+ EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
+
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Enter\n"));
+
+ SmmCommunicationAcpiTable = (EFI_SMM_COMMUNICATION_ACPI_TABLE *)(UINTN)mSmmCommunicationContext.AcpiTableAddress;
+ CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)(UINTN)SmmCommunicationAcpiTable->BufferPtrAddress;
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader - %x\n", CommunicateHeader));
+ CommSize = (UINTN)CommunicateHeader->MessageLength;
+
+ //
+ // Call dispatch function
+ //
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Data - %x\n", &CommunicateHeader->Data[0]));
+ Status = gSmst->SmiManage (
+ &CommunicateHeader->HeaderGuid,
+ NULL,
+ &CommunicateHeader->Data[0],
+ &CommSize
+ );
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler %r\n", Status));
+ DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Exit\n"));
+
+ return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_INTERRUPT_PENDING;
+}
+
+/**
+ Entry Point for PI SMM communication SMM driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCEESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+EFIAPI
+PiSmmCommunicationSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SmmSwDispatch2;
+ EFI_SMM_SW_REGISTER_CONTEXT SmmSwDispatchContext;
+ EFI_HANDLE DispatchHandle;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
+ UINTN TableKey;
+
+ //
+ // Register software SMI handler
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ (VOID **)&SmmSwDispatch2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SmmSwDispatchContext.SwSmiInputValue = (UINTN)-1;
+ Status = SmmSwDispatch2->Register (
+ SmmSwDispatch2,
+ PiSmmCommunicationHandler,
+ &SmmSwDispatchContext,
+ &DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "SmmCommunication SwSmi: %x\n", (UINTN)SmmSwDispatchContext.SwSmiInputValue));
+
+ //
+ // Set ACPI table
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ mSmmCommunicationAcpiTable.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;
+ CopyMem (&mSmmCommunicationAcpiTable.UefiAcpiDataTable.Identifier, &gEfiSmmCommunicationProtocolGuid, sizeof(gEfiSmmCommunicationProtocolGuid));
+
+ Status = AcpiTableProtocol->InstallAcpiTable (
+ AcpiTableProtocol,
+ &mSmmCommunicationAcpiTable,
+ sizeof(mSmmCommunicationAcpiTable),
+ &TableKey
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Save context
+ //
+ mSmmCommunicationContext.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;
+ mSmmCommunicationContext.AcpiTableAddress = GetSmmCommunicationAcpiTableAddress ();
+ DEBUG ((EFI_D_INFO, "SmmCommunicationAcpiTable: %x\n", mSmmCommunicationContext.AcpiTableAddress));
+ SetCommunicationContext ();
+
+ return Status;
+}
diff --git a/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
new file mode 100644
index 0000000..6138fe5
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
@@ -0,0 +1,84 @@
+## @file
+# Component description file for PI SMM Communication SMM driver.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PiSmmCommunicationSmm
+ FILE_GUID = E21F35A8-42FF-4050-82D6-93F7CDFA7073
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = PiSmmCommunicationSmmEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ PiSmmCommunicationSmm.c
+ PiSmmCommunicationPrivate.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ SmmServicesTableLib
+ BaseLib
+ BaseMemoryLib
+ HobLib
+ DebugLib
+
+[Guids]
+ gEfiAcpi20TableGuid ## CONSUMED
+ gEfiAcpi10TableGuid ## CONSUMED
+ gEfiAcpiTableGuid ## CONSUMED
+
+[Ppis]
+ gEfiPeiSmmCommunicationPpiGuid ## CONSUMED
+
+[Protocols]
+ gEfiSmmSwDispatch2ProtocolGuid ## CONSUMED
+ gEfiSmmCommunicationProtocolGuid ## CONSUMED
+ gEfiAcpiTableProtocolGuid ## CONSUMED
+
+[Depex]
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiAcpiTableProtocolGuid
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuS3.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuS3.c
new file mode 100644
index 0000000..308ff45
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuS3.c
@@ -0,0 +1,454 @@
+/** @file
+
+ Code for Processor S3 restoration
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: CpuS3.c
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+
+typedef struct {
+ UINTN Lock;
+ VOID *StackStart;
+ UINTN StackSize;
+ VOID *ApFunction;
+ IA32_DESCRIPTOR GdtrProfile;
+ IA32_DESCRIPTOR IdtrProfile;
+ UINT32 BufferStart;
+ UINT32 Cr3;
+} MP_CPU_EXCHANGE_INFO;
+
+typedef struct {
+ UINT8 *RendezvousFunnelAddress;
+ UINTN PModeEntryOffset;
+ UINTN FlatJumpOffset;
+ UINTN Size;
+ UINTN LModeEntryOffset;
+ UINTN LongJumpOffset;
+} MP_ASSEMBLY_ADDRESS_MAP;
+
+/**
+ Get starting address and size of the rendezvous entry for APs.
+ Information for fixing a jump instruction in the code is also returned.
+
+ @param AddressMap Output buffer for address map information.
+**/
+VOID *
+EFIAPI
+AsmGetAddressMap (
+ MP_ASSEMBLY_ADDRESS_MAP *AddressMap
+ );
+
+#define LEGACY_REGION_SIZE (2 * 0x1000)
+#define LEGACY_REGION_BASE (0xA0000 - LEGACY_REGION_SIZE)
+
+ACPI_CPU_DATA mAcpiCpuData;
+UINT32 mNumberToFinish;
+MP_CPU_EXCHANGE_INFO *mExchangeInfo;
+BOOLEAN mRestoreSmmConfigurationInS3 = FALSE;
+VOID *mGdtForAp = NULL;
+VOID *mIdtForAp = NULL;
+VOID *mMachineCheckHandlerForAp = NULL;
+
+/**
+ Synch up the MTRR values for all processors.
+
+ @param MtrrTable Table holding fixed/variable MTRR values to be loaded.
+**/
+VOID
+EFIAPI
+LoadMtrrData (
+ EFI_PHYSICAL_ADDRESS MtrrTable
+ )
+/*++
+
+Routine Description:
+
+ Synch up the MTRR values for all processors.
+
+Arguments:
+
+Returns:
+ None
+
+--*/
+{
+ MTRR_SETTINGS *MtrrSettings;
+
+ MtrrSettings = (MTRR_SETTINGS *) (UINTN) MtrrTable;
+ MtrrSetAllMtrrs (MtrrSettings);
+}
+
+/**
+ Programs registers for the calling processor.
+
+ This function programs registers for the calling processor.
+
+ @param RegisterTable Pointer to register table of the running processor.
+
+**/
+VOID
+SetProcessorRegister (
+ CPU_REGISTER_TABLE *RegisterTable
+ )
+{
+ CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
+ UINTN Index;
+ UINTN Value;
+
+ //
+ // Traverse Register Table of this logical processor
+ //
+ RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
+ for (Index = 0; Index < RegisterTable->TableLength; Index++, RegisterTableEntry++) {
+ //
+ // Check the type of specified register
+ //
+ switch (RegisterTableEntry->RegisterType) {
+ //
+ // The specified register is Control Register
+ //
+ case ControlRegister:
+ switch (RegisterTableEntry->Index) {
+ case 0:
+ Value = AsmReadCr0 ();
+ Value = (UINTN) BitFieldWrite64 (
+ Value,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ (UINTN) RegisterTableEntry->Value
+ );
+ AsmWriteCr0 (Value);
+ break;
+ case 2:
+ Value = AsmReadCr2 ();
+ Value = (UINTN) BitFieldWrite64 (
+ Value,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ (UINTN) RegisterTableEntry->Value
+ );
+ AsmWriteCr2 (Value);
+ break;
+ case 3:
+ Value = AsmReadCr3 ();
+ Value = (UINTN) BitFieldWrite64 (
+ Value,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ (UINTN) RegisterTableEntry->Value
+ );
+ AsmWriteCr3 (Value);
+ break;
+ case 4:
+ Value = AsmReadCr4 ();
+ Value = (UINTN) BitFieldWrite64 (
+ Value,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ (UINTN) RegisterTableEntry->Value
+ );
+ AsmWriteCr4 (Value);
+ break;
+ default:
+ break;
+ }
+ break;
+ //
+ // The specified register is Model Specific Register
+ //
+ case Msr:
+ //
+ // If this function is called to restore register setting after INIT signal,
+ // there is no need to restore MSRs in register table.
+ //
+ if (RegisterTableEntry->ValidBitLength >= 64) {
+ //
+ // If length is not less than 64 bits, then directly write without reading
+ //
+ AsmWriteMsr64 (
+ RegisterTableEntry->Index,
+ RegisterTableEntry->Value
+ );
+ } else {
+ //
+ // Set the bit section according to bit start and length
+ //
+ AsmMsrBitFieldWrite64 (
+ RegisterTableEntry->Index,
+ RegisterTableEntry->ValidBitStart,
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
+ RegisterTableEntry->Value
+ );
+ }
+ break;
+ //
+ // Enable or disable cache
+ //
+ case CacheControl:
+ //
+ // If value of the entry is 0, then disable cache. Otherwise, enable cache.
+ //
+ if (RegisterTableEntry->Value == 0) {
+ AsmDisableCache ();
+ } else {
+ AsmEnableCache ();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ AP initialization before SMBASE relocation in the S3 boot path.
+**/
+VOID
+EarlyMPRendezvousProcedure (
+ VOID
+ )
+{
+ CPU_REGISTER_TABLE *RegisterTableList;
+ UINT32 InitApicId;
+ UINTN Index;
+
+ LoadMtrrData (mAcpiCpuData.MtrrTable);
+
+ //
+ // Find processor number for this CPU.
+ //
+ RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable;
+ InitApicId = GetInitialApicId ();
+ for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
+ if (RegisterTableList[Index].InitialApicId == InitApicId) {
+ SetProcessorRegister (&RegisterTableList[Index]);
+ break;
+ }
+ }
+
+ //
+ // Count down the number with lock mechanism.
+ //
+ InterlockedDecrement (&mNumberToFinish);
+}
+
+/**
+ AP initialization after SMBASE relocation in the S3 boot path.
+**/
+VOID
+MPRendezvousProcedure (
+ VOID
+ )
+{
+ CPU_REGISTER_TABLE *RegisterTableList;
+ UINT32 InitApicId;
+ UINTN Index;
+
+ ProgramVirtualWireMode ();
+ DisableLvtInterrupts ();
+
+ RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable;
+ InitApicId = GetInitialApicId ();
+ for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
+ if (RegisterTableList[Index].InitialApicId == InitApicId) {
+ SetProcessorRegister (&RegisterTableList[Index]);
+ break;
+ }
+ }
+
+ //
+ // Count down the number with lock mechanism.
+ //
+ InterlockedDecrement (&mNumberToFinish);
+}
+
+/**
+ Prepares startup vector for APs.
+
+ This function prepares startup vector for APs.
+
+ @param WorkingBuffer The address of the work buffer.
+**/
+VOID
+PrepareAPStartupVector (
+ EFI_PHYSICAL_ADDRESS WorkingBuffer
+ )
+{
+ EFI_PHYSICAL_ADDRESS StartupVector;
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ //
+ // Get the address map of startup code for AP,
+ // including code size, and offset of long jump instructions to redirect.
+ //
+ ZeroMem (&AddressMap, sizeof (AddressMap));
+ AsmGetAddressMap (&AddressMap);
+
+ StartupVector = WorkingBuffer;
+
+ //
+ // Copy AP startup code to startup vector, and then redirect the long jump
+ // instructions for mode switching.
+ //
+ CopyMem ((VOID *) (UINTN) StartupVector, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
+ *(UINT32 *) (UINTN) (StartupVector + AddressMap.FlatJumpOffset + 3) = (UINT32) (StartupVector + AddressMap.PModeEntryOffset);
+ if (AddressMap.LongJumpOffset != 0) {
+ *(UINT32 *) (UINTN) (StartupVector + AddressMap.LongJumpOffset + 2) = (UINT32) (StartupVector + AddressMap.LModeEntryOffset);
+ }
+
+ //
+ // Get the start address of exchange data between BSP and AP.
+ //
+ mExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (StartupVector + AddressMap.Size);
+ ZeroMem ((VOID *) mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));
+
+ CopyMem ((VOID *) (UINTN) &mExchangeInfo->GdtrProfile, (VOID *) (UINTN) mAcpiCpuData.GdtrProfile, sizeof (IA32_DESCRIPTOR));
+ CopyMem ((VOID *) (UINTN) &mExchangeInfo->IdtrProfile, (VOID *) (UINTN) mAcpiCpuData.IdtrProfile, sizeof (IA32_DESCRIPTOR));
+
+ //
+ // Copy AP's GDT, IDT and Machine Check handler from SMRAM to ACPI NVS memory
+ //
+ CopyMem ((VOID *) mExchangeInfo->GdtrProfile.Base, mGdtForAp, mExchangeInfo->GdtrProfile.Limit + 1);
+ CopyMem ((VOID *) mExchangeInfo->IdtrProfile.Base, mIdtForAp, mExchangeInfo->IdtrProfile.Limit + 1);
+ CopyMem ((VOID *)(UINTN) mAcpiCpuData.ApMachineCheckHandlerBase, mMachineCheckHandlerForAp, mAcpiCpuData.ApMachineCheckHandlerSize);
+
+ mExchangeInfo->StackStart = (VOID *) (UINTN) mAcpiCpuData.StackAddress;
+ mExchangeInfo->StackSize = mAcpiCpuData.StackSize;
+ mExchangeInfo->BufferStart = (UINT32) StartupVector;
+ mExchangeInfo->Cr3 = (UINT32) (AsmReadCr3 ());
+}
+
+/**
+ The function is invoked before SMBASE relocation in S3 path to restors CPU status.
+
+ The function is invoked before SMBASE relocation in S3 path. It does first time microcode load
+ and restores MTRRs for both BSP and APs.
+
+**/
+VOID
+EarlyInitializeCpu (
+ VOID
+ )
+{
+ CPU_REGISTER_TABLE *RegisterTableList;
+ UINT32 InitApicId;
+ UINTN Index;
+
+ LoadMtrrData (mAcpiCpuData.MtrrTable);
+
+ //
+ // Find processor number for this CPU.
+ //
+ RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable;
+ InitApicId = GetInitialApicId ();
+ for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
+ if (RegisterTableList[Index].InitialApicId == InitApicId) {
+ SetProcessorRegister (&RegisterTableList[Index]);
+ break;
+ }
+ }
+
+ ProgramVirtualWireMode ();
+
+ PrepareAPStartupVector (mAcpiCpuData.StartupVector);
+
+ mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;
+ mExchangeInfo->ApFunction = (VOID *) (UINTN) EarlyMPRendezvousProcedure;
+
+ //
+ // Send INIT IPI - SIPI to all APs
+ //
+ SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector);
+
+ while (mNumberToFinish > 0) {
+ CpuPause ();
+ }
+}
+
+/**
+ The function is invoked after SMBASE relocation in S3 path to restors CPU status.
+
+ The function is invoked after SMBASE relocation in S3 path. It restores configuration according to
+ data saved by normal boot path for both BSP and APs.
+
+**/
+VOID
+InitializeCpu (
+ VOID
+ )
+{
+ CPU_REGISTER_TABLE *RegisterTableList;
+ UINT32 InitApicId;
+ UINTN Index;
+
+ RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable;
+ InitApicId = GetInitialApicId ();
+ for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
+ if (RegisterTableList[Index].InitialApicId == InitApicId) {
+ SetProcessorRegister (&RegisterTableList[Index]);
+ break;
+ }
+ }
+
+ mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;
+ mExchangeInfo->ApFunction = (VOID *) (UINTN) MPRendezvousProcedure;
+
+ //
+ // Send INIT IPI - SIPI to all APs
+ //
+ SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector);
+
+ while (mNumberToFinish > 0) {
+ CpuPause ();
+ }
+}
+
+/**
+ Restore SMM Configuration.
+**/
+VOID
+RestoreSmmConfigurationInS3 (
+ VOID
+ )
+{
+ if (mRestoreSmmConfigurationInS3) {
+ //
+ // Configure SMM Code Access Check feature if available.
+ //
+ ConfigSmmCodeAccessCheck ();
+
+ mRestoreSmmConfigurationInS3 = FALSE;
+ }
+}
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuService.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuService.c
new file mode 100644
index 0000000..6c5c07d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuService.c
@@ -0,0 +1,500 @@
+/** @file
+ Implementation of SMM CPU Services Protocol.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+
+#define CPUID_EXTENDED_TOPOLOGY 0xb
+#define CPUID_CACHE_PARAMS 0x4
+#define CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID 0x0
+#define CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT 0x1
+#define CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE 0x2
+
+extern EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[];
+
+//
+// SMM CPU Service Protocol instance
+//
+EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService = {
+ SmmGetProcessorInfo,
+ SmmSwitchBsp,
+ SmmAddProcessor,
+ SmmRemoveProcessor,
+ SmmWhoAmI,
+ SmmRegisterExceptionHandler
+};
+
+/**
+ Get Package ID/Core ID/Thread ID of a processor.
+
+ APIC ID must be an initial APIC ID.
+
+ The algorithm below assumes the target system has symmetry across physical package boundaries
+ with respect to the number of logical processors per package, number of cores per package.
+
+ @param ApicId APIC ID of the target logical processor.
+ @param Location Returns the processor location information.
+**/
+VOID
+SmmGetProcessorLocation (
+ IN UINT32 ApicId,
+ OUT EFI_CPU_PHYSICAL_LOCATION *Location
+ )
+{
+ UINTN ThreadBits;
+ UINTN CoreBits;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+ UINT32 MaxCpuIdIndex;
+ UINT32 SubIndex;
+ UINTN LevelType;
+ UINT32 MaxLogicProcessorsPerPackage;
+ UINT32 MaxCoresPerPackage;
+
+ ASSERT (Location != NULL);
+
+ //
+ // Check if the processor is capable of supporting more than one logical processor.
+ //
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
+ ASSERT ((RegEdx & BIT28) != 0);
+
+ //
+ // Assume three-level mapping of APIC ID: Package:Core:SMT.
+ //
+
+ //
+ // Get the max index of basic CPUID
+ //
+ AsmCpuid (EFI_CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);
+
+ if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {
+ AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, &RegEax, &RegEbx, NULL, NULL);
+ if ((RegEbx & 0xffff) != 0) {
+ //
+ // x2APIC ID
+ //
+
+ ThreadBits = RegEax & 0x1f;
+
+ CoreBits = 0;
+ SubIndex = 1;
+ do {
+ AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, SubIndex, &RegEax, NULL, &RegEcx, NULL);
+ LevelType = (RegEcx >> 8) & 0xff;
+ if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {
+ CoreBits = (RegEax & 0x1f) - ThreadBits;
+ break;
+ }
+ SubIndex++;
+ } while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
+
+ Location->Thread = ApicId & ~((-1) << ThreadBits);
+ Location->Core = (ApicId >> ThreadBits) & ~((-1) << CoreBits);
+ Location->Package = (ApicId >> (ThreadBits+ CoreBits));
+ }
+ }
+ //
+ // xAPIC ID
+ //
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+ MaxLogicProcessorsPerPackage = (RegEbx >> 16) & 0xff;
+ if (MaxCpuIdIndex >= CPUID_CACHE_PARAMS) {
+ AsmCpuidEx (CPUID_CACHE_PARAMS, 0, &RegEax, NULL, NULL, NULL);
+ MaxCoresPerPackage = (RegEax >> 26) + 1;
+ } else {
+ MaxCoresPerPackage = 1;
+ }
+
+ ThreadBits = (UINTN) (HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);
+ CoreBits = (UINTN) (HighBitSet32 (MaxCoresPerPackage - 1) + 1);
+
+ Location->Thread = ApicId & ~((-1) << ThreadBits);
+ Location->Core = (ApicId >> ThreadBits) & ~((-1) << CoreBits);
+ Location->Package = (ApicId >> (ThreadBits+ CoreBits));
+}
+
+/**
+ Gets processor information on the requested processor at the instant this call is made.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
+ the requested processor is deposited.
+
+ @retval EFI_SUCCESS Processor information was returned.
+ @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
+ @retval EFI_NOT_FOUND The processor with the handle specified by
+ ProcessorNumber does not exist in the platform.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmGetProcessorInfo (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ )
+{
+ //
+ // Check parameter
+ //
+ if (ProcessorNumber >= mMaxNumberOfCpus || ProcessorInfoBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId == INVALID_APIC_ID) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Fill in processor information
+ //
+ CopyMem (ProcessorInfoBuffer, &gSmmCpuPrivate->ProcessorInfo[ProcessorNumber], sizeof (EFI_PROCESSOR_INFORMATION));
+ return EFI_SUCCESS;
+}
+
+/**
+ This service switches the requested AP to be the BSP since the next SMI.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
+
+ @retval EFI_SUCCESS BSP will be switched in next SMI.
+ @retval EFI_UNSUPPORTED Switching the BSP or a processor to be hot-removed is not supported.
+ @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
+**/
+EFI_STATUS
+EFIAPI
+SmmSwitchBsp (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber
+ )
+{
+ //
+ // Check parameter
+ //
+ if (ProcessorNumber >= mMaxNumberOfCpus) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId == INVALID_APIC_ID) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (gSmmCpuPrivate->Operation[ProcessorNumber] != SmmCpuNone ||
+ gSmst->CurrentlyExecutingCpu == ProcessorNumber) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Setting of the BSP for next SMI is pending until all SMI handlers are finished
+ //
+ gSmmCpuPrivate->Operation[ProcessorNumber] = SmmCpuSwitchBsp;
+ return EFI_SUCCESS;
+}
+
+/**
+ Notify that a processor was hot-added.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorId Local APIC ID of the hot-added processor.
+ @param[out] ProcessorNumber The handle number of the hot-added processor.
+
+ @retval EFI_SUCCESS The hot-addition of the specified processos was succesfully notified.
+ @retval EFI_UNSUPPORTED Hot addition of processor is not supported.
+ @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
+ @retval EFI_ALREADY_STARTED The processor is already online in the system.
+**/
+EFI_STATUS
+EFIAPI
+SmmAddProcessor (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINT64 ProcessorId,
+ OUT UINTN *ProcessorNumber
+ )
+{
+ UINTN Index;
+
+ if (!FeaturePcdGet (PcdCpuHotPlugSupport)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check parameter
+ //
+ if (ProcessorNumber == NULL || ProcessorId == INVALID_APIC_ID) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if the processor already exists
+ //
+
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ProcessorId) {
+ return EFI_ALREADY_STARTED;
+ }
+ }
+
+ //
+ // Check CPU hot plug data. The CPU RAS handler should have created the mapping
+ // of the APIC ID to SMBASE.
+ //
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ if (mCpuHotPlugData.ApicId[Index] == ProcessorId &&
+ gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == INVALID_APIC_ID) {
+ gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId = ProcessorId;
+ gSmmCpuPrivate->ProcessorInfo[Index].StatusFlag = 0;
+ SmmGetProcessorLocation ((UINT32)ProcessorId, &gSmmCpuPrivate->ProcessorInfo[Index].Location);
+
+ *ProcessorNumber = Index;
+ gSmmCpuPrivate->Operation[Index] = SmmCpuAdd;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Notify that a processor was hot-removed.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of the hot-added processor.
+
+ @retval EFI_SUCCESS The hot-removal of the specified processos was succesfully notified.
+ @retval EFI_UNSUPPORTED Hot removal of processor is not supported.
+ @retval EFI_UNSUPPORTED Hot removal of BSP is not supported.
+ @retval EFI_UNSUPPORTED Hot removal of a processor with pending hot-plug operation is not supported.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
+**/
+EFI_STATUS
+EFIAPI
+SmmRemoveProcessor (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber
+ )
+{
+ if (!FeaturePcdGet (PcdCpuHotPlugSupport)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check parameter
+ //
+ if (ProcessorNumber >= mMaxNumberOfCpus ||
+ gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId == INVALID_APIC_ID) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Can't remove BSP
+ //
+ if (ProcessorNumber == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (gSmmCpuPrivate->Operation[ProcessorNumber] != SmmCpuNone) {
+ return EFI_UNSUPPORTED;
+ }
+
+ gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId = INVALID_APIC_ID;
+ mCpuHotPlugData.ApicId[ProcessorNumber] = INVALID_APIC_ID;
+
+ //
+ // Removal of the processor from the CPU list is pending until all SMI handlers are finished
+ //
+ gSmmCpuPrivate->Operation[ProcessorNumber] = SmmCpuRemove;
+ return EFI_SUCCESS;
+}
+
+/**
+ This return the handle number for the calling processor.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[out] ProcessorNumber The handle number of currently executing processor.
+
+ @retval EFI_SUCCESS The current processor handle number was returned
+ in ProcessorNumber.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmWhoAmI (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ OUT UINTN *ProcessorNumber
+ )
+{
+ UINTN Index;
+ UINT64 ApicId;
+
+ //
+ // Check parameter
+ //
+ if (ProcessorNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ApicId = GetApicId ();
+
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) {
+ *ProcessorNumber = Index;
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // This should not happen
+ //
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Update the SMM CPU list per the pending operation.
+
+ This function is called after return from SMI handlers.
+**/
+VOID
+SmmCpuUpdate (
+ VOID
+ )
+{
+ UINTN Index;
+
+ //
+ // Handle pending BSP switch operations
+ //
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ if (gSmmCpuPrivate->Operation[Index] == SmmCpuSwitchBsp) {
+ gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
+ mSmmMpSyncData->SwitchBsp = TRUE;
+ mSmmMpSyncData->CandidateBsp[Index] = TRUE;
+ }
+ }
+
+ //
+ // Handle pending hot-add operations
+ //
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ if (gSmmCpuPrivate->Operation[Index] == SmmCpuAdd) {
+ gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
+ mNumberOfCpus++;
+ }
+ }
+
+ //
+ // Handle pending hot-remove operations
+ //
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ if (gSmmCpuPrivate->Operation[Index] == SmmCpuRemove) {
+ gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
+ mNumberOfCpus--;
+ }
+ }
+}
+
+/**
+ Register exception handler.
+
+ @param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
+ @param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
+ the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
+ of the UEFI 2.0 specification.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ If this parameter is NULL, then the handler will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmRegisterExceptionHandler (
+ IN EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (ExceptionType < 0 || ExceptionType >= EXCEPTION_VECTOR_NUMBER) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (InterruptHandler == NULL && mExternalVectorTable[ExceptionType] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterruptHandler != NULL && mExternalVectorTable[ExceptionType] != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mExternalVectorTable[ExceptionType] = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize SMM CPU Services.
+
+ It installs EFI SMM CPU Services Protocol.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+
+ @retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully.
+**/
+EFI_STATUS
+InitializeSmmCpuServices (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gEfiSmmCpuServiceProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mSmmCpuService
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuService.h b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuService.h
new file mode 100644
index 0000000..b33109a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/CpuService.h
@@ -0,0 +1,213 @@
+/** @file
+ Include file for SMM RAS Services protocol implementation.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef _CPU_SERVICE_H_
+#define _CPU_SERVICE_H_
+
+typedef enum {
+ SmmCpuNone,
+ SmmCpuAdd,
+ SmmCpuRemove,
+ SmmCpuSwitchBsp
+} SMM_CPU_OPERATION;
+
+
+//
+// SMM CPU Service Protocol function prototypes.
+//
+
+/**
+ Gets processor information on the requested processor at the instant this call is made.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
+ the requested processor is deposited.
+
+ @retval EFI_SUCCESS Processor information was returned.
+ @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
+ @retval EFI_NOT_FOUND The processor with the handle specified by
+ ProcessorNumber does not exist in the platform.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmGetProcessorInfo (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ );
+
+/**
+ This service switches the requested AP to be the BSP since the next SMI.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
+
+ @retval EFI_SUCCESS BSP will be switched in next SMI.
+ @retval EFI_UNSUPPORTED Switching the BSP or a processor to be hot-removed is not supported.
+ @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
+**/
+EFI_STATUS
+EFIAPI
+SmmSwitchBsp (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ Notify that a processor was hot-added.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorId Local APIC ID of the hot-added processor.
+ @param[out] ProcessorNumber The handle number of the hot-added processor.
+
+ @retval EFI_SUCCESS The hot-addition of the specified processos was succesfully notified.
+ @retval EFI_UNSUPPORTED Hot addition of processor is not supported.
+ @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
+ @retval EFI_ALREADY_STARTED The processor is already online in the system.
+**/
+EFI_STATUS
+EFIAPI
+SmmAddProcessor (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINT64 ProcessorId,
+ OUT UINTN *ProcessorNumber
+ );
+
+/**
+ Notify that a processor was hot-removed.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of the hot-added processor.
+
+ @retval EFI_SUCCESS The hot-removal of the specified processos was succesfully notified.
+ @retval EFI_UNSUPPORTED Hot removal of processor is not supported.
+ @retval EFI_UNSUPPORTED Hot removal of BSP is not supported.
+ @retval EFI_UNSUPPORTED Hot removal of a processor with pending hot-plug operation is not supported.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
+**/
+EFI_STATUS
+EFIAPI
+SmmRemoveProcessor (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN UINTN ProcessorNumber
+ );
+
+/**
+ This return the handle number for the calling processor.
+
+ @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
+ @param[out] ProcessorNumber The handle number of currently executing processor.
+
+ @retval EFI_SUCCESS The current processor handle number was returned
+ in ProcessorNumber.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmWhoAmI (
+ IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ OUT UINTN *ProcessorNumber
+ );
+
+/**
+ Register exception handler.
+
+ @param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
+ @param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
+ the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
+ of the UEFI 2.0 specification.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ If this parameter is NULL, then the handler will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmRegisterExceptionHandler (
+ IN EFI_SMM_CPU_SERVICE_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+//
+// Internal function prototypes
+//
+
+/**
+ Initializes the pointer to the external exception vector table.
+
+ @param VectorTable Address of the external exception vector table.
+
+**/
+VOID
+EFIAPI
+InitializeSmmExternalVectorTablePtr (
+ EFI_CPU_INTERRUPT_HANDLER *VectorTable
+ );
+
+/**
+ Update the SMM CPU list per the pending operation.
+
+ This function is called after return from SMI handlers.
+**/
+VOID
+SmmCpuUpdate (
+ VOID
+ );
+
+/**
+ Initialize SMM CPU Services.
+
+ It installs EFI SMM CPU Services Protocol.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+
+ @retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully.
+**/
+EFI_STATUS
+InitializeSmmCpuServices (
+ IN EFI_HANDLE Handle
+ );
+
+#endif
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.S b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.S
new file mode 100644
index 0000000..ad8d121
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.S
@@ -0,0 +1,186 @@
+#-------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+#
+# Module Name:
+#
+# MpFuncs.S
+#
+# Abstract:
+#
+# This is the assembly code for Multi-processor S3 support
+#
+#-------------------------------------------------------------------------------
+
+.equ VacantFlag, 0x0
+.equ NotVacantFlag, 0xff
+
+.equ LockLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+.equ StackStart, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x04
+.equ StackSize, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x08
+.equ RendezvousProc, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x0C
+.equ GdtrProfile, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x10
+.equ IdtrProfile, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x16
+.equ BufferStart, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x1C
+
+#-------------------------------------------------------------------------------------
+#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);
+
+ASM_GLOBAL ASM_PFX(RendezvousFunnelProc)
+ASM_PFX(RendezvousFunnelProc):
+RendezvousFunnelProcStart:
+
+# At this point CS = 0x(vv00) and ip= 0x0.
+
+ .byte 0x8c,0xc8 # mov ax, cs
+ .byte 0x8e,0xd8 # mov ds, ax
+ .byte 0x8e,0xc0 # mov es, ax
+ .byte 0x8e,0xd0 # mov ss, ax
+ .byte 0x33,0xc0 # xor ax, ax
+ .byte 0x8e,0xe0 # mov fs, ax
+ .byte 0x8e,0xe8 # mov gs, ax
+
+flat32Start:
+
+ .byte 0xBE
+ .word BufferStart
+ .byte 0x66,0x8B,0x14 # mov edx,dword ptr [si] ; EDX is keeping the start address of wakeup buffer
+
+ .byte 0xBE
+ .word GdtrProfile
+ .byte 0x66 # db 66h
+ .byte 0x2E,0xF,0x1,0x14 # lgdt fword ptr cs:[si]
+
+ .byte 0xBE
+ .word IdtrProfile
+ .byte 0x66 # db 66h
+ .byte 0x2E,0xF,0x1,0x1C # lidt fword ptr cs:[si]
+
+ .byte 0x33,0xC0 # xor ax, ax
+ .byte 0x8E,0xD8 # mov ds, ax
+
+ .byte 0xF,0x20,0xC0 # mov eax, cr0 ; Get control register 0
+ .byte 0x66,0x83,0xC8,0x1 # or eax, 000000001h ; Set PE bit (bit #0)
+ .byte 0xF,0x22,0xC0 # mov cr0, eax
+
+FLAT32_JUMP:
+
+ .byte 0x66,0x67,0xEA # far jump
+ .long 0x0 # 32-bit offset
+ .word 0x20 # 16-bit selector
+
+PMODE_ENTRY: # protected mode entry point
+
+ movw $0x8,%ax
+ .byte 0x66
+ movw %ax,%ds
+ .byte 0x66
+ movw %ax,%es
+ .byte 0x66
+ movw %ax,%fs
+ .byte 0x66
+ movw %ax,%gs
+ .byte 0x66
+ movw %ax,%ss # Flat mode setup.
+
+ movl %edx,%esi
+
+ movl %esi,%edi
+ addl $LockLocation, %edi
+ movb $NotVacantFlag, %al
+TestLock:
+ xchgb (%edi), %al
+ cmpb $NotVacantFlag, %al
+ jz TestLock
+
+ProgramStack:
+
+ movl %esi,%edi
+ addl $StackSize, %edi
+ movl (%edi),%eax
+ movl %esi,%edi
+ addl $StackStart, %edi
+ addl (%edi),%eax
+ movl %eax,%esp
+ movl %eax,(%edi)
+
+Releaselock:
+
+ movb $VacantFlag, %al
+ movl %esi,%edi
+ addl $LockLocation, %edi
+ xchgb (%edi), %al
+
+ #
+ # Call assembly function to initialize FPU.
+ #
+ lea ASM_PFX(InitializeFloatingPointUnits), %ebx
+ call *%ebx
+ #
+ # Call C Function
+ #
+ movl %esi,%edi
+ addl $RendezvousProc, %edi
+ movl (%edi),%eax
+
+ testl %eax,%eax
+ jz GoToSleep
+ call *%eax # Call C function
+
+GoToSleep:
+ cli
+ hlt
+ jmp GoToSleep
+
+RendezvousFunnelProcEnd:
+#-------------------------------------------------------------------------------------
+# AsmGetAddressMap (&AddressMap);
+#-------------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmGetAddressMap)
+ASM_PFX(AsmGetAddressMap):
+
+ pushal
+ movl %esp,%ebp
+
+ movl 0x24(%ebp), %ebx
+ movl $RendezvousFunnelProcStart, (%ebx)
+ movl $(PMODE_ENTRY - RendezvousFunnelProcStart), 0x4(%ebx)
+ movl $(FLAT32_JUMP - RendezvousFunnelProcStart), 0x8(%ebx)
+ movl $(RendezvousFunnelProcEnd - RendezvousFunnelProcStart), 0x0c(%ebx)
+
+ popal
+ ret
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.asm b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.asm
new file mode 100644
index 0000000..baf233b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.asm
@@ -0,0 +1,190 @@
+;-------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+;
+;
+; Module Name:
+;
+; MpFuncs.asm
+;
+; Abstract:
+;
+; This is the assembly code for Multi-processor S3 support
+;
+;-------------------------------------------------------------------------------
+
+.686p
+.model flat,C
+.code
+
+EXTERN InitializeFloatingPointUnits:PROC
+
+VacantFlag Equ 00h
+NotVacantFlag Equ 0ffh
+
+LockLocation equ RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+StackStart equ LockLocation + 4h
+StackSize equ LockLocation + 8h
+RendezvousProc equ LockLocation + 0Ch
+GdtrProfile equ LockLocation + 10h
+IdtrProfile equ LockLocation + 16h
+BufferStart equ LockLocation + 1Ch
+
+;-------------------------------------------------------------------------------------
+;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);
+
+RendezvousFunnelProc PROC near C PUBLIC
+RendezvousFunnelProcStart::
+
+; 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
+
+flat32Start::
+
+ db 0BEh
+ dw BufferStart ; mov si, BufferStart
+ db 66h, 8Bh, 14h ; mov edx,dword ptr [si] ; EDX is keeping the start address of wakeup buffer
+
+ db 0BEh
+ dw GdtrProfile ; mov si, GdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
+
+ db 0BEh
+ dw IdtrProfile ; mov si, IdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 1Ch ; lidt 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, 01h ; or eax, 000000001h ; Set PE bit (bit #0)
+ 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
+
+PMODE_ENTRY:: ; protected mode entry point
+
+ mov ax, 8h
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax ; Flat mode setup.
+
+ mov esi, edx
+
+ mov edi, esi
+ add edi, LockLocation
+ mov al, NotVacantFlag
+TestLock::
+ xchg byte ptr [edi], al
+ cmp al, NotVacantFlag
+ jz TestLock
+
+ProgramStack::
+
+ mov edi, esi
+ add edi, StackSize
+ mov eax, dword ptr [edi]
+ mov edi, esi
+ add edi, StackStart
+ add eax, dword ptr [edi]
+ mov esp, eax
+ mov dword ptr [edi], eax
+
+Releaselock::
+
+ mov al, VacantFlag
+ mov edi, esi
+ add edi, LockLocation
+ xchg byte ptr [edi], al
+
+ ;
+ ; Call assembly function to initialize FPU.
+ ;
+ mov ebx, InitializeFloatingPointUnits
+ call ebx
+ ;
+ ; Call C Function
+ ;
+ mov edi, esi
+ add edi, RendezvousProc
+ mov eax, dword ptr [edi]
+
+ test eax, eax
+ jz GoToSleep
+ call eax ; Call C function
+
+GoToSleep::
+ cli
+ hlt
+ jmp $-2
+
+RendezvousFunnelProc ENDP
+RendezvousFunnelProcEnd::
+;-------------------------------------------------------------------------------------
+; AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+AsmGetAddressMap PROC near C PUBLIC
+
+ pushad
+ mov ebp,esp
+
+ mov ebx, dword ptr [ebp+24h]
+ mov dword ptr [ebx], RendezvousFunnelProcStart
+ mov dword ptr [ebx+4h], PMODE_ENTRY - RendezvousFunnelProcStart
+ mov dword ptr [ebx+8h], FLAT32_JUMP - RendezvousFunnelProcStart
+ mov dword ptr [ebx+0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+
+ popad
+ ret
+
+AsmGetAddressMap ENDP
+
+END
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
new file mode 100644
index 0000000..7778731
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
@@ -0,0 +1,116 @@
+/** @file
+
+Page table manipulation functions for IA-32 processors
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+
+SPIN_LOCK mPFLock;
+
+/**
+ Create PageTable for SMM use.
+
+ @return PageTable Address
+
+**/
+UINT32
+SmmInitPageTable (
+ VOID
+ )
+{
+ //
+ // Initialize spin lock
+ //
+ InitializeSpinLock (&mPFLock);
+
+ //
+ // Register Smm Page Fault Handler
+ //
+ SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_PAGE_FAULT, SmiPFHandler);
+
+
+ return Gen4GPageTable (0);
+}
+
+/**
+ Page Fault handler for SMM use.
+
+**/
+VOID
+SmiDefaultPFHandler (
+ VOID
+ )
+{
+ CpuDeadLoop ();
+}
+
+/**
+ ThePage Fault handler wrapper for SMM use.
+
+ @param InterruptType Defines the type of interrupt or exception that
+ occurred on the processor.This parameter is processor architecture specific.
+ @param SystemContext A pointer to the processor context when
+ the interrupt occurred on the processor.
+**/
+VOID
+EFIAPI
+SmiPFHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINTN PFAddress;
+
+ ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
+
+ AcquireSpinLock (&mPFLock);
+
+ PFAddress = AsmReadCr2 ();
+
+ if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
+ (PFAddress >= mCpuHotPlugData.SmrrBase) &&
+ (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) {
+ DEBUG ((EFI_D_ERROR, "SMM stack overflow!\n"));
+ CpuDeadLoop ();
+ }
+
+ if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ SmmProfilePFHandler (
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->ExceptionData
+ );
+ } else {
+ SmiDefaultPFHandler ();
+ }
+
+ ReleaseSpinLock (&mPFLock);
+}
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/Semaphore.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/Semaphore.c
new file mode 100644
index 0000000..b714949
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/Semaphore.c
@@ -0,0 +1,78 @@
+/** @file
+ Semaphore mechanism to indicate to the BSP that an AP has exited SMM
+ after SMBASE relocation.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+
+UINTN mSmmRelocationOriginalAddress;
+BOOLEAN *mRebasedFlag;
+
+/**
+ Hook return address of SMM Save State so that semaphore code
+ can be executed immediately after AP exits SMM to indicate to
+ the BSP that an AP has exited SMM after SMBASE relocation.
+
+ @param CpuIndex The processor index.
+**/
+VOID
+SemaphoreHook (
+ IN UINTN CpuIndex
+ )
+{
+ EFI_SMM_CPU_STATE *CpuState;
+
+ mRebasedFlag = (BOOLEAN *) &mRebased[CpuIndex];
+
+ CpuState = (EFI_SMM_CPU_STATE *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_CPU_STATE_OFFSET);
+
+ //
+ // The offset of EIP/RIP is different depending on the SMMRevId
+ //
+ if (CpuState->x86.SMMRevId < SOCKET_LGA_775_SMM_MIN_REV_ID_x64) {
+ mSmmRelocationOriginalAddress = (UINTN) CpuState->x86._EIP;
+ CpuState->x86._EIP = (UINT32) (UINTN) &SmmRelocationSemaphoreComplete;
+ } else {
+ mSmmRelocationOriginalAddress = (UINTN) CpuState->x64._RIP;
+ CpuState->x64._RIP = (UINT64) (UINTN) &SmmRelocationSemaphoreComplete;
+ }
+
+ if (CpuState->x86.AutoHALTRestart & BIT0) {
+ //
+ // Clear the auto HALT restart flag so the RSM instruction returns
+ // program control to the instruction following the HLT instruction,
+ // actually returns to SmmRelocationSemaphoreComplete
+ //
+ CpuState->x86.AutoHALTRestart &= ~BIT0;
+ }
+}
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.S b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.S
new file mode 100644
index 0000000..f9b1fc2
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.S
@@ -0,0 +1,171 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# SmiEntry.S
+#
+# Abstract:
+#
+# Code template of the SMI handler for a particular processor
+#
+#------------------------------------------------------------------------------
+
+
+ASM_GLOBAL ASM_PFX(gcSmiHandlerTemplate)
+ASM_GLOBAL ASM_PFX(gcSmiHandlerSize)
+ASM_GLOBAL ASM_PFX(gSmiCr3)
+ASM_GLOBAL ASM_PFX(gcSmiHandlerOffset)
+ASM_GLOBAL ASM_PFX(gSmiStack)
+ASM_GLOBAL ASM_PFX(gSmbase)
+ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug))
+ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
+
+.equ DSC_OFFSET, 0xfb00
+.equ DSC_GDTPTR, 0x30
+.equ DSC_GDTSIZ, 0x38
+.equ DSC_CS, 14
+.equ DSC_DS, 16
+.equ DSC_SS, 18
+.equ DSC_OTHERSEG, 20
+
+.equ TSS_SEGMENT, 0x40
+
+ .data
+
+ ASM_PFX(gcSmiHandlerOffset): .word _SmiHandler - _SmiEntryPoint + 0x8000
+
+ .text
+
+ASM_PFX(gcSmiHandlerTemplate):
+
+_SmiEntryPoint:
+ .byte 0xbb # mov bx, imm16
+ .word _GdtDesc - _SmiEntryPoint + 0x8000
+ .byte 0x2e,0xa1 # mov ax, cs:[offset16]
+ .word DSC_OFFSET + DSC_GDTSIZ
+ decl %eax
+ movl %eax, %cs:(%edi) # mov cs:[bx], ax
+ .byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
+ .word DSC_OFFSET + DSC_GDTPTR
+ movw %ax, %cs:2(%edi)
+ movw %ax, %bp # ebp = GDT base
+ .byte 0x66
+ lgdt %cs:(%edi)
+ .byte 0x66,0xb8 # mov eax, imm32
+ASM_PFX(gSmiCr3): .space 4
+ movl %eax, %cr3
+ .byte 0x66
+ movl $0x020,%eax # as cr4.PGE is not set here, refresh cr3
+ movl %eax, %cr4 # in PreModifyMtrrs() to flush TLB.
+ .byte 0x2e,0xa1 # mov ax, cs:[offset16]
+ .word DSC_OFFSET + DSC_CS
+ movl %eax, %cs:-2(%edi)
+ .byte 0x66, 0xbf # mov edi, SMBASE
+ASM_PFX(gSmbase): .space 4
+ .byte 0x67
+ lea ((Start32bit - _SmiEntryPoint) + 0x8000)(%edi), %ax
+ movw %ax, %cs:-6(%edi)
+ movl %cr0, %ebx
+ .byte 0x66
+ andl $0x9ffafff3, %ebx
+ .byte 0x66
+ orl $0x80000023, %ebx
+ movl %ebx, %cr0
+ .byte 0x66,0xea
+ .space 4
+ .space 2
+_GdtDesc: .space 4
+ .space 2
+Start32bit:
+ leal DSC_OFFSET(%edi),%ebx
+ movw DSC_DS(%ebx),%ax
+ movl %eax,%ds
+ movw DSC_OTHERSEG(%ebx),%ax
+ movl %eax,%es
+ movl %eax,%fs
+ movl %eax,%gs
+ movw DSC_SS(%ebx),%ax
+ movl %eax,%ss
+
+ cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
+ jz L5
+
+# Load TSS
+ movb $0x89, (TSS_SEGMENT + 5)(%ebp) # clear busy flag
+
+ movl $TSS_SEGMENT, %eax
+ ltrw %ax
+L5:
+
+# jmp _SmiHandler # instruction is not needed
+
+_SmiHandler:
+ .byte 0xbc # mov esp, imm32
+ASM_PFX(gSmiStack): .space 4
+ cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug))
+ jz L3
+ call L1
+L1:
+ popl %ebp
+ movl $0x80000001, %eax
+ cpuid
+ btl $29, %edx # check cpuid to identify X64 or IA32
+ leal (0x7fc8 - (L1 - _SmiEntryPoint))(%ebp), %edi
+ leal 4(%edi), %esi
+ jnc L2
+ addl $4, %esi
+L2:
+ movl (%esi), %ecx
+ movl (%edi), %edx
+L7:
+ movl %ecx, %dr6
+ movl %edx, %dr7 # restore DR6 & DR7 before running C code
+L3:
+
+ pushl (%esp)
+
+ movl $ASM_PFX(SmiRendezvous), %eax
+ call *%eax
+ popl %ecx
+
+
+ cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug))
+ jz L4
+
+ movl %dr6, %ecx
+ movl %dr7, %edx
+ movl %ecx, (%esi)
+ movl %edx, (%edi)
+L4:
+ rsm
+
+ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.asm b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.asm
new file mode 100644
index 0000000..c20ace0
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.asm
@@ -0,0 +1,176 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; SmiEntry.asm
+;
+; Abstract:
+;
+; Code template of the SMI handler for a particular processor
+;
+;------------------------------------------------------------------------------
+
+ .686p
+ .model flat,C
+ .xmm
+
+DSC_OFFSET EQU 0fb00h
+DSC_GDTPTR EQU 30h
+DSC_GDTSIZ EQU 38h
+DSC_CS EQU 14
+DSC_DS EQU 16
+DSC_SS EQU 18
+DSC_OTHERSEG EQU 20
+
+TSS_SEGMENT EQU 40h
+
+SmiRendezvous PROTO C
+
+EXTERNDEF gcSmiHandlerTemplate:BYTE
+EXTERNDEF gcSmiHandlerSize:WORD
+EXTERNDEF gSmiCr3:DWORD
+EXTERNDEF gcSmiHandlerOffset:WORD
+EXTERNDEF gSmiStack:DWORD
+EXTERNDEF gSmbase:DWORD
+EXTERNDEF FeaturePcdGet (PcdCpuSmmDebug):BYTE
+EXTERNDEF FeaturePcdGet (PcdCpuSmmStackGuard):BYTE
+
+ .const
+
+gcSmiHandlerOffset DW _SmiHandler - _SmiEntryPoint + 8000h
+
+ .code
+
+gcSmiHandlerTemplate LABEL BYTE
+
+_SmiEntryPoint PROC
+ DB 0bbh ; mov bx, imm16
+ DW offset _GdtDesc - _SmiEntryPoint + 8000h
+ DB 2eh, 0a1h ; mov ax, cs:[offset16]
+ DW DSC_OFFSET + DSC_GDTSIZ
+ dec eax
+ mov cs:[edi], eax ; mov cs:[bx], ax
+ DB 66h, 2eh, 0a1h ; mov eax, cs:[offset16]
+ DW DSC_OFFSET + DSC_GDTPTR
+ mov cs:[edi + 2], ax ; mov cs:[bx + 2], eax
+ mov bp, ax ; ebp = GDT base
+ DB 66h
+ lgdt fword ptr cs:[edi] ; lgdt fword ptr cs:[bx]
+ DB 66h, 0b8h ; mov eax, imm32
+gSmiCr3 DD ?
+ mov cr3, eax
+ DB 66h
+ mov eax, 020h ; as cr4.PGE is not set here, refresh cr3
+ mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
+ DB 2eh, 0a1h ; mov ax, cs:[offset16]
+ DW DSC_OFFSET + DSC_CS
+ mov cs:[edi - 2], eax ; mov cs:[bx - 2], ax
+ DB 66h, 0bfh ; mov edi, SMBASE
+gSmbase DD ?
+ DB 67h
+ lea ax, [edi + (@32bit - _SmiEntryPoint) + 8000h]
+ mov cs:[edi - 6], ax ; mov cs:[bx - 6], eax
+ mov ebx, cr0
+ DB 66h
+ and ebx, 9ffafff3h
+ DB 66h
+ or ebx, 80000023h
+ mov cr0, ebx
+ DB 66h, 0eah
+ DD ?
+ DW ?
+_GdtDesc FWORD ?
+@32bit:
+ lea ebx, [edi + DSC_OFFSET]
+ mov ax, [ebx + DSC_DS]
+ mov ds, eax
+ mov ax, [ebx + DSC_OTHERSEG]
+ mov es, eax
+ mov fs, eax
+ mov gs, eax
+ mov ax, [ebx + DSC_SS]
+ mov ss, eax
+
+ cmp FeaturePcdGet (PcdCpuSmmStackGuard), 0
+ jz @F
+
+; Load TSS
+ mov byte ptr [ebp + TSS_SEGMENT + 5], 89h ; clear busy flag
+
+ mov eax, TSS_SEGMENT
+ ltr ax
+@@:
+; jmp _SmiHandler ; instruction is not needed
+_SmiEntryPoint ENDP
+
+_SmiHandler PROC
+ DB 0bch ; mov esp, imm32
+gSmiStack DD ?
+ cmp FeaturePcdGet (PcdCpuSmmDebug), 0
+ jz @3
+ call @1
+@1:
+ pop ebp
+ mov eax, 80000001h
+ cpuid
+ bt edx, 29 ; check cpuid to identify X64 or IA32
+ lea edi, [ebp - (@1 - _SmiEntryPoint) + 7fc8h]
+ lea esi, [edi + 4]
+ jnc @2
+ add esi, 4
+@2:
+ mov ecx, [esi]
+ mov edx, [edi]
+@5:
+ mov dr6, ecx
+ mov dr7, edx ; restore DR6 & DR7 before running C code
+@3:
+ mov ecx, [esp] ; CPU Index
+
+ push ecx
+ mov eax, SmiRendezvous
+ call eax
+ pop ecx
+
+ cmp FeaturePcdGet (PcdCpuSmmDebug), 0
+ jz @4
+
+ mov ecx, dr6
+ mov edx, dr7
+ mov [esi], ecx
+ mov [edi], edx
+@4:
+ rsm
+_SmiHandler ENDP
+
+gcSmiHandlerSize DW $ - _SmiEntryPoint
+
+ END
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiException.S b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiException.S
new file mode 100644
index 0000000..6390882
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiException.S
@@ -0,0 +1,1196 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# SmiException.S
+#
+# Abstract:
+#
+# Exception handlers used in SM mode
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(gSmiMtrrs)
+ASM_GLOBAL ASM_PFX(gcSmiIdtr)
+ASM_GLOBAL ASM_PFX(gcSmiGdtr)
+ASM_GLOBAL ASM_PFX(gcPsd)
+ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
+ASM_GLOBAL ASM_PFX(gSavedPageFaultIdtEntry)
+ASM_GLOBAL ASM_PFX(gSavedDebugExceptionIdtEntry)
+ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
+ASM_GLOBAL ASM_PFX(InitializeSmmExternalVectorTablePtr)
+
+ .data
+
+NullSeg: .quad 0
+ .quad 0 # reserved for future use
+CodeSeg32:
+ .word -1 # LimitLow
+ .word 0 # BaseLow
+ .byte 0 # BaseMid
+ .byte 0x9b
+ .byte 0xcf # LimitHigh
+ .byte 0 # BaseHigh
+DataSeg32:
+ .word -1 # LimitLow
+ .word 0 # BaseLow
+ .byte 0 # BaseMid
+ .byte 0x93
+ .byte 0xcf # LimitHigh
+ .byte 0 # BaseHigh
+ .quad 0 # reserved for future use
+CodeSeg16:
+ .word -1
+ .word 0
+ .byte 0
+ .byte 0x9b
+ .byte 0x8f
+ .byte 0
+DataSeg16:
+ .word -1
+ .word 0
+ .byte 0
+ .byte 0x93
+ .byte 0x8f
+ .byte 0
+CodeSeg64:
+ .word -1 # LimitLow
+ .word 0 # BaseLow
+ .byte 0 # BaseMid
+ .byte 0x9b
+ .byte 0xaf # LimitHigh
+ .byte 0 # BaseHigh
+.equ GDT_SIZE, .- NullSeg
+
+TssSeg:
+ .word TSS_DESC_SIZE # LimitLow
+ .word 0 # BaseLow
+ .byte 0 # BaseMid
+ .byte 0x89
+ .byte 0x80 # LimitHigh
+ .byte 0 # BaseHigh
+ExceptionTssSeg:
+ .word TSS_DESC_SIZE # LimitLow
+ .word 0 # BaseLow
+ .byte 0 # BaseMid
+ .byte 0x89
+ .byte 0x80 # LimitHigh
+ .byte 0 # BaseHigh
+
+.equ CODE_SEL, CodeSeg32 - NullSeg
+.equ DATA_SEL, DataSeg32 - NullSeg
+.equ TSS_SEL, TssSeg - NullSeg
+.equ EXCEPTION_TSS_SEL, ExceptionTssSeg - NullSeg
+
+# IA32 TSS fields
+.equ TSS_ESP0, 4
+.equ TSS_SS0, 8
+.equ TSS_ESP1, 12
+.equ TSS_SS1, 16
+.equ TSS_ESP2, 20
+.equ TSS_SS2, 24
+.equ TSS_CR3, 28
+.equ TSS_EIP, 32
+.equ TSS_EFLAGS, 36
+.equ TSS_EAX, 40
+.equ TSS_ECX, 44
+.equ TSS_EDX, 48
+.equ TSS_EBX, 52
+.equ TSS_ESP, 56
+.equ TSS_EBP, 60
+.equ TSS_ESI, 64
+.equ TSS_EDI, 68
+.equ TSS_ES, 72
+.equ TSS_CS, 76
+.equ TSS_SS, 80
+.equ TSS_DS, 84
+.equ TSS_FS, 88
+.equ TSS_GS, 92
+.equ TSS_LDT, 96
+
+# Create 2 TSS segments just after GDT
+TssDescriptor:
+ .word 0 # PreviousTaskLink
+ .word 0 # Reserved
+ .long 0 # ESP0
+ .word 0 # SS0
+ .word 0 # Reserved
+ .long 0 # ESP1
+ .word 0 # SS1
+ .word 0 # Reserved
+ .long 0 # ESP2
+ .word 0 # SS2
+ .word 0 # Reserved
+ .long 0 # CR3
+ .long 0 # EIP
+ .long 0 # EFLAGS
+ .long 0 # EAX
+ .long 0 # ECX
+ .long 0 # EDX
+ .long 0 # EBX
+ .long 0 # ESP
+ .long 0 # EBP
+ .long 0 # ESI
+ .long 0 # EDI
+ .word 0 # ES
+ .word 0 # Reserved
+ .word 0 # CS
+ .word 0 # Reserved
+ .word 0 # SS
+ .word 0 # Reserved
+ .word 0 # DS
+ .word 0 # Reserved
+ .word 0 # FS
+ .word 0 # Reserved
+ .word 0 # GS
+ .word 0 # Reserved
+ .word 0 # LDT Selector
+ .word 0 # Reserved
+ .word 0 # T
+ .word 0 # I/O Map Base
+.equ TSS_DESC_SIZE, . - TssDescriptor
+
+ExceptionTssDescriptor:
+ .word 0 # PreviousTaskLink
+ .word 0 # Reserved
+ .long 0 # ESP0
+ .word 0 # SS0
+ .word 0 # Reserved
+ .long 0 # ESP1
+ .word 0 # SS1
+ .word 0 # Reserved
+ .long 0 # ESP2
+ .word 0 # SS2
+ .word 0 # Reserved
+ .long 0 # CR3
+ .long PFHandlerEntry # EIP
+ .long 00000002 # EFLAGS
+ .long 0 # EAX
+ .long 0 # ECX
+ .long 0 # EDX
+ .long 0 # EBX
+ .long 0 # ESP
+ .long 0 # EBP
+ .long 0 # ESI
+ .long 0 # EDI
+ .word DATA_SEL # ES
+ .word 0 # Reserved
+ .word CODE_SEL # CS
+ .word 0 # Reserved
+ .word DATA_SEL # SS
+ .word 0 # Reserved
+ .word DATA_SEL # DS
+ .word 0 # Reserved
+ .word DATA_SEL # FS
+ .word 0 # Reserved
+ .word DATA_SEL # GS
+ .word 0 # Reserved
+ .word 0 # LDT Selector
+ .word 0 # Reserved
+ .word 0 # T
+ .word 0 # I/O Map Base
+
+ASM_PFX(gcPsd):
+ .ascii "PSDSIG "
+ .word PSD_SIZE
+ .word 2
+ .word 1 << 2
+ .word CODE_SEL
+ .word DATA_SEL
+ .word DATA_SEL
+ .word DATA_SEL
+ .word 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .quad 0
+ .long NullSeg
+ .long 0
+ .long GDT_SIZE
+ .long 0
+ .space 24, 0
+ .long ASM_PFX(gSmiMtrrs)
+ .long 0
+.equ PSD_SIZE, . - ASM_PFX(gcPsd)
+
+ASM_PFX(gcSmiGdtr): .word GDT_SIZE - 1
+ .long NullSeg
+
+ASM_PFX(gcSmiIdtr): .word IDT_SIZE - 1
+ .long _SmiIDT
+
+_SmiIDT:
+# The following segment repeats 32 times:
+# No. 1
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 2
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 3
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 4
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 5
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 6
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 7
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 8
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 9
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 10
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 11
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 12
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 13
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 14
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 15
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 16
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 17
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 18
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 19
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 20
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 21
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 22
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 23
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 24
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 25
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 26
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 27
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 28
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 29
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 30
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 31
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+# No. 32
+ .word 0 # Offset 0:15
+ .word CODE_SEL
+ .byte 0 # Unused
+ .byte 0x8e # Interrupt Gate, Present
+ .word 0 # Offset 16:31
+
+.equ IDT_SIZE, . - _SmiIDT
+
+TaskGateDescriptor:
+ .word 0 # Reserved
+ .word EXCEPTION_TSS_SEL # TSS Segment selector
+ .byte 0 # Reserved
+ .byte 0x85 # Task Gate, present, DPL = 0
+ .word 0 # Reserved
+
+# point to the external interrupt vector table
+
+ExternalVectorTablePtr: .long 0
+
+#
+# Saved IDT Entry for Page Fault
+#
+ASM_PFX(gSavedPageFaultIdtEntry):
+ .long 0
+ .long 0
+
+#
+# Saved IDT Entry for INT 1
+#
+ASM_PFX(gSavedDebugExceptionIdtEntry):
+ .long 0
+ .long 0
+
+ .text
+
+ASM_PFX(InitializeSmmExternalVectorTablePtr):
+ movl 4(%esp), %eax
+ movl %eax, ExternalVectorTablePtr
+ ret
+
+#------------------------------------------------------------------------------
+# Exception handlers
+#------------------------------------------------------------------------------
+_SmiExceptionHandlers:
+.equ IHDLRIDX, 0
+# The following segment repeats 8 times:
+# No. 1
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 2
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 3
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 4
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 5
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 6
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 7
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 8
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+ int $3
+.equ IHDLRIDX, IHDLRIDX + 1
+
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+
+# The following segment repeats 5 times:
+# No. 1
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+ int $3
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 2
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+ int $3
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 3
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+ int $3
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 4
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+ int $3
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 5
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+ int $3
+.equ IHDLRIDX, IHDLRIDX + 1
+
+# The following segment repeats 2 times:
+# No. 1
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 2
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+ int $3
+.equ IHDLRIDX, IHDLRIDX + 1
+
+# The following segment repeats 14 times:
+# No. 1
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 2
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 3
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 4
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 5
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 6
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 7
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 8
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 9
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 10
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 11
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 12
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 13
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+# No. 14
+ pushl %eax # dummy error code
+ pushl $IHDLRIDX
+ .byte 0xe9 # jmp disp32
+ .long _SmiExceptionEntryPoint - (. + 4)
+.equ IHDLRIDX, IHDLRIDX + 1
+
+
+#------------------------------------------------------------------------------
+# _SmiExceptionEntryPoint is the entry point for all exceptions
+#
+# Stack:
+#+---------------------+
+#+ EFlags +
+#+---------------------+
+#+ CS +
+#+---------------------+
+#+ EIP +
+#+---------------------+
+#+ Error Code +
+#+---------------------+
+#+ Vector Number +
+#+---------------------+
+#+ EBP +
+#+---------------------+ <-- EBP
+#
+# RSP set to odd multiple of 8 means ErrCode PRESENT
+#------------------------------------------------------------------------------
+_SmiExceptionEntryPoint:
+ pushl %ebp
+ movl %esp, %ebp
+
+
+ #
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ # is 16-byte aligned
+ #
+ andl $0xfffffff0, %esp
+ subl $12, %esp
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushl %ebx
+ leal (6*4)(%ebp), %ecx
+ pushl %ecx # ESP
+ pushl (%ebp) # EBP
+ pushl %esi
+ pushl %edi
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ movl %ss, %eax
+ pushl %eax
+ movzwl (4*4)(%ebp), %eax
+ pushl %eax
+ movl %ds, %eax
+ pushl %eax
+ movl %es, %eax
+ pushl %eax
+ movl %fs, %eax
+ pushl %eax
+ movl %gs, %eax
+ pushl %eax
+
+## UINT32 Eip;
+ movl (3*4)(%ebp), %eax
+ pushl %eax
+
+## UINT32 Gdtr[2], Idtr[2];
+ subl $8, %esp
+ sidt (%esp)
+ movl 2(%esp), %eax
+ xchgl (%esp), %eax
+ andl $0xffff, %eax
+ movl %eax, 4(%esp)
+
+ subl $8, %esp
+ sgdt (%esp)
+ movl 2(%esp), %eax
+ xchgl (%esp), %eax
+ andl $0xffff, %eax
+ movl %eax, 4(%esp)
+
+## UINT32 Ldtr, Tr;
+ xorl %eax, %eax
+ strw %ax
+ pushl %eax
+ sldtw %ax
+ pushl %eax
+
+## UINT32 EFlags;
+ movl (5*4)(%ebp), %eax
+ pushl %eax
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ movl %cr4, %eax
+ orl $0x208, %eax
+ movl %eax, %cr4
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ xorl %eax, %eax
+ pushl %eax
+ movl %cr0, %eax
+ pushl %eax
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movl %dr7, %eax
+ pushl %eax
+ movl %dr6, %eax
+ pushl %eax
+ movl %dr3, %eax
+ pushl %eax
+ movl %dr2, %eax
+ pushl %eax
+ movl %dr1, %eax
+ pushl %eax
+ movl %dr0, %eax
+ pushl %eax
+
+## FX_SAVE_STATE_IA32 FxSaveState;
+ subl $512, %esp
+ movl %esp, %edi
+ .byte 0x0f, 0xae, 0x07 #fxsave [edi]
+
+# UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+## UINT32 ExceptionData;
+ pushl (2*4)(%ebp)
+
+## call into exception handler
+ movl ExternalVectorTablePtr, %eax # get the interrupt vectors base
+ orl %eax, %eax # NULL?
+ jz nullExternalExceptionHandler
+
+ movl 4(%ebp), %ecx
+ movl (%eax, %ecx, 4), %eax
+ orl %eax, %eax # NULL?
+ jz nullExternalExceptionHandler
+
+## Prepare parameter and call
+ movl %esp, %edx
+ pushl %edx
+ movl (1*4)(%ebp), %edx
+ pushl %edx
+
+ #
+ # Call External Exception Handler
+ #
+ call *%eax
+ addl $8, %esp
+ jmp L4
+
+nullExternalExceptionHandler:
+# CpuDeadLoop() is the default exception handler since it preserves the processor
+# branch log.
+ call ASM_PFX(CpuDeadLoop)
+
+L4:
+## UINT32 ExceptionData;
+ addl $4, %esp
+
+## FX_SAVE_STATE_IA32 FxSaveState;
+ movl %esp, %esi
+ .byte 0xf, 0xae, 0xe # fxrstor [esi]
+ addl $512, %esp
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+## Skip restoration of DRx registers to support in-circuit emualators
+## or debuggers set breakpoint in interrupt/exception context
+ addl $4*6, %esp
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ popl %eax
+ movl %eax, %cr0
+ addl $4, %esp # not for Cr1
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, %cr3
+ popl %eax
+ movl %eax, %cr4
+
+## UINT32 EFlags;
+ popl (5*4)(%ebp)
+
+## UINT32 Ldtr, Tr;
+## UINT32 Gdtr[2], Idtr[2];
+## Best not let anyone mess with these particular registers...
+ addl $24, %esp
+
+## UINT32 Eip;
+ popl (3*4)(%ebp)
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+## NOTE - modified segment registers could hang the debugger... We
+## could attempt to insulate ourselves against this possibility,
+## but that poses risks as well.
+##
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popl (4*4)(%ebp)
+ popl %ss
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ popl %edi
+ popl %esi
+ addl $4, %esp # not for ebp
+ addl $4, %esp # not for esp
+ popl %ebx
+ popl %edx
+ popl %ecx
+ popl %eax
+
+ movl %ebp, %esp
+ popl %ebp
+
+# Set single step DB# if SMM profile is enabled and page fault exception happens
+ cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
+ jz Done
+# Check if this is page fault exception
+ cmpl $0xe, (%esp)
+ jnz L5
+# Enable TF bit after page fault handler runs
+ btsl $8, 16(%esp) # EFLAGS
+ jmp Done
+L5:
+# Check if this is INT 1 exception
+ cmpl $1, (%esp)
+ jnz Done
+# Clear TF bit after INT1 handler runs
+ btcl $8, 16(%esp) # EFLAGS
+Done:
+
+ addl $8, %esp # skip INT# & ErrCode
+Return:
+ iret
+#
+# Page Fault Exception Handler entry when SMM Stack Guard is enabled
+# Executiot starts here after a task switch
+#
+PFHandlerEntry:
+#
+# Get this processor's TSS
+#
+ subl $8, %esp
+ sgdt 2(%esp)
+ movl 4(%esp), %eax # GDT base
+ addl $8, %esp
+ movl (TSS_SEL+2)(%eax), %ecx
+ shll $8, %ecx
+ movb (TSS_SEL+7)(%eax), %cl
+ rorl $8, %ecx # ecx = TSS base
+
+ movl %esp, %ebp
+
+ #
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ # is 16-byte aligned
+ #
+ andl $0xfffffff0, %esp
+ subl $12, %esp
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pushl TSS_EAX(%ecx)
+ pushl TSS_ECX(%ecx)
+ pushl TSS_EDX(%ecx)
+ pushl TSS_EBX(%ecx)
+ pushl TSS_ESP(%ecx)
+ pushl TSS_EBP(%ecx)
+ pushl TSS_ESI(%ecx)
+ pushl TSS_EDI(%ecx)
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ movzwl TSS_SS(%ecx), %eax
+ pushl %eax
+ movzwl TSS_CS(%ecx), %eax
+ pushl %eax
+ movzwl TSS_DS(%ecx), %eax
+ pushl %eax
+ movzwl TSS_ES(%ecx), %eax
+ pushl %eax
+ movzwl TSS_FS(%ecx), %eax
+ pushl %eax
+ movzwl TSS_GS(%ecx), %eax
+ pushl %eax
+
+## UINT32 Eip;
+ pushl TSS_EIP(%ecx)
+
+## UINT32 Gdtr[2], Idtr[2];
+ subl $8, %esp
+ sidt (%esp)
+ movl 2(%esp), %eax
+ xchgl (%esp), %eax
+ andl $0xFFFF, %eax
+ movl %eax, 4(%esp)
+
+ subl $8, %esp
+ sgdt (%esp)
+ movl 2(%esp), %eax
+ xchgl (%esp), %eax
+ andl $0xFFFF, %eax
+ movl %eax, 4(%esp)
+
+## UINT32 Ldtr, Tr;
+ movl TSS_SEL, %eax
+ pushl %eax
+ movzwl TSS_LDT(%ecx), %eax
+ pushl %eax
+
+## UINT32 EFlags;
+ pushl TSS_EFLAGS(%ecx)
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ movl %cr4, %eax
+ orl $0x208, %eax
+ movl %eax, %cr4
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ xorl %eax, %eax
+ pushl %eax
+ movl %cr0, %eax
+ pushl %eax
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movl %dr7, %eax
+ pushl %eax
+ movl %dr6, %eax
+ pushl %eax
+ movl %dr3, %eax
+ pushl %eax
+ movl %dr2, %eax
+ pushl %eax
+ movl %dr1, %eax
+ pushl %eax
+ movl %dr0, %eax
+ pushl %eax
+
+## FX_SAVE_STATE_IA32 FxSaveState;
+ subl $512, %esp
+ movl %esp, %edi
+ .byte 0x0f, 0xae, 0x07 #fxsave [edi]
+
+# UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+## UINT32 ExceptionData;
+ pushl (%ebp)
+
+## call into exception handler
+ movl ExternalVectorTablePtr, %eax # get the interrupt vectors base
+ orl %eax, %eax # NULL?
+ jz nullExternalExceptionHandler
+
+ movl %ecx, %ebx
+ mov $14, %ecx
+ movl (%eax, %ecx, 4), %eax
+ orl %eax, %eax # NULL?
+ jz nullExternalExceptionHandler
+
+## Prepare parameter and call
+ movl %esp, %edx
+ pushl %edx
+ movl $14, %edx
+ pushl %edx
+
+ #
+ # Call External Exception Handler
+ #
+ call *%eax
+ addl $8, %esp
+
+ movl %ebx, %ecx
+## UINT32 ExceptionData;
+ addl $4, %esp
+
+## FX_SAVE_STATE_IA32 FxSaveState;
+ movl %esp, %esi
+ .byte 0xf, 0xae, 0xe # fxrstor [esi]
+ addl $512, %esp
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+## Skip restoration of DRx registers to support in-circuit emualators
+## or debuggers set breakpoint in interrupt/exception context
+ addl $4*6, %esp
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ popl %eax
+ movl %eax, %cr0
+ addl $4, %esp # not for Cr1
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, TSS_CR3(%ecx)
+ popl %eax
+ movl %eax, %cr4
+
+## UINT32 EFlags;
+ popl TSS_EFLAGS(%ecx)
+
+## UINT32 Ldtr, Tr;
+## UINT32 Gdtr[2], Idtr[2];
+## Best not let anyone mess with these particular registers...
+ addl $24, %esp
+
+## UINT32 Eip;
+ popl TSS_EIP(%ecx)
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+## NOTE - modified segment registers could hang the debugger... We
+## could attempt to insulate ourselves against this possibility,
+## but that poses risks as well.
+##
+ popl %eax
+ movw %ax, TSS_GS(%ecx)
+ popl %eax
+ movw %ax, TSS_FS(%ecx)
+ popl %eax
+ movw %ax, TSS_ES(%ecx)
+ popl %eax
+ movw %ax, TSS_DS(%ecx)
+ popl %eax
+ movw %ax, TSS_CS(%ecx)
+ popl %eax
+ movw %ax, TSS_SS(%ecx)
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ popl TSS_EDI(%ecx)
+ popl TSS_ESI(%ecx)
+ addl $4, %esp # not for ebp
+ addl $4, %esp # not for esp
+ popl TSS_EBX(%ecx)
+ popl TSS_EDX(%ecx)
+ popl TSS_ECX(%ecx)
+ popl TSS_EAX(%ecx)
+
+ movl %ebp, %esp
+
+# Set single step DB# if SMM profile is enabled and page fault exception happens
+ cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
+ jz Done2
+# Enable TF bit after page fault handler runs
+ btsl $8, TSS_EFLAGS(%ecx) # EFLAGS
+
+Done2:
+
+ addl 4, %esp # skip ErrCode
+
+ jmp Return
+
+ASM_GLOBAL ASM_PFX(InitializeIDT)
+ASM_PFX(InitializeIDT):
+ pushl %ebx
+ lea _SmiIDT - 8, %edx
+# push IDT_SIZE / 8
+ .byte 0x68 # push /id
+ .long IDT_SIZE / 8
+ lea _SmiExceptionHandlers - 8, %ebx
+ popl %ecx
+L1:
+ leal (%ebx,%ecx,8),%eax
+ movw %ax,(%edx,%ecx,8)
+ shrl $16,%eax
+ movw %ax, 6(%edx, %ecx, 8)
+ loop L1
+
+ cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
+ jz L2
+
+#
+# If SMM Stack Guard feature is enabled, the Page Fault Exception entry in IDT
+# is a Task Gate Descriptor so that when a Page Fault Exception occurrs,
+# the processors can use a known good stack in case stack ran out.
+#
+ leal _SmiIDT + 14 * 8, %ebx
+ leal TaskGateDescriptor, %edx
+ movl (%edx), %eax
+ movl %eax, (%ebx)
+ movl 4(%edx), %eax
+ movl %eax, 4(%ebx)
+
+L2:
+#
+# Save Page Fault IDT entry in gPageFaultIdtEntry
+#
+ leal _SmiIDT + 14 * 8, %ebx
+ leal ASM_PFX(gSavedPageFaultIdtEntry), %edx
+ movl (%ebx), %eax
+ movl %eax, (%edx)
+ movl 4(%ebx), %eax
+ movl %eax, 4(%edx)
+
+ cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
+ jz L3
+
+#
+# Save INT 1 IDT entry in gSavedDebugExceptionIdtEntry
+#
+ leal _SmiIDT + 1 * 8, %ebx
+ leal ASM_PFX(gSavedDebugExceptionIdtEntry), %edx
+ movl (%ebx), %eax
+ movl %eax, (%edx)
+ movl 4(%ebx), %eax
+ movl %eax, 4(%edx)
+
+L3:
+ popl %ebx
+ ret
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiException.asm b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiException.asm
new file mode 100644
index 0000000..5476265
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmiException.asm
@@ -0,0 +1,883 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; SmiException.asm
+;
+; Abstract:
+;
+; Exception handlers used in SM mode
+;
+;------------------------------------------------------------------------------
+
+ .686p
+ .model flat,C
+
+CpuDeadLoop PROTO C
+
+EXTERNDEF gSmiMtrrs:QWORD
+EXTERNDEF gcSmiIdtr:FWORD
+EXTERNDEF gcSmiGdtr:FWORD
+EXTERNDEF gcPsd:BYTE
+EXTERNDEF FeaturePcdGet (PcdCpuSmmStackGuard):BYTE
+EXTERNDEF gSavedPageFaultIdtEntry:DWORD
+EXTERNDEF gSavedDebugExceptionIdtEntry:DWORD
+EXTERNDEF FeaturePcdGet (PcdCpuSmmProfileEnable):BYTE
+
+
+ .data
+
+NullSeg DQ 0 ; reserved by architecture
+ DQ 0 ; reserved for future use
+CodeSeg32 LABEL QWORD
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 9bh
+ DB 0cfh ; LimitHigh
+ DB 0 ; BaseHigh
+DataSeg32 LABEL QWORD
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 93h
+ DB 0cfh ; LimitHigh
+ DB 0 ; BaseHigh
+ DQ 0 ; reserved for future use
+CodeSeg16 LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 9bh
+ DB 8fh
+ DB 0
+DataSeg16 LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 93h
+ DB 8fh
+ DB 0
+CodeSeg64 LABEL QWORD
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 9bh
+ DB 0afh ; LimitHigh
+ DB 0 ; BaseHigh
+GDT_SIZE = $ - offset NullSeg
+
+TssSeg LABEL QWORD
+ DW TSS_DESC_SIZE ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 89h
+ DB 080h ; LimitHigh
+ DB 0 ; BaseHigh
+ExceptionTssSeg LABEL QWORD
+ DW TSS_DESC_SIZE ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 89h
+ DB 080h ; LimitHigh
+ DB 0 ; BaseHigh
+
+CODE_SEL = offset CodeSeg32 - offset NullSeg
+DATA_SEL = offset DataSeg32 - offset NullSeg
+TSS_SEL = offset TssSeg - offset NullSeg
+EXCEPTION_TSS_SEL = offset ExceptionTssSeg - offset NullSeg
+
+IA32_TSS STRUC
+ DW ?
+ DW ?
+ ESP0 DD ?
+ SS0 DW ?
+ DW ?
+ ESP1 DD ?
+ SS1 DW ?
+ DW ?
+ ESP2 DD ?
+ SS2 DW ?
+ DW ?
+ _CR3 DD ?
+ EIP DD ?
+ EFLAGS DD ?
+ _EAX DD ?
+ _ECX DD ?
+ _EDX DD ?
+ _EBX DD ?
+ _ESP DD ?
+ _EBP DD ?
+ _ESI DD ?
+ _EDI DD ?
+ _ES DW ?
+ DW ?
+ _CS DW ?
+ DW ?
+ _SS DW ?
+ DW ?
+ _DS DW ?
+ DW ?
+ _FS DW ?
+ DW ?
+ _GS DW ?
+ DW ?
+ LDT DW ?
+ DW ?
+ DW ?
+ DW ?
+IA32_TSS ENDS
+
+; Create 2 TSS segments just after GDT
+TssDescriptor LABEL BYTE
+ DW 0 ; PreviousTaskLink
+ DW 0 ; Reserved
+ DD 0 ; ESP0
+ DW 0 ; SS0
+ DW 0 ; Reserved
+ DD 0 ; ESP1
+ DW 0 ; SS1
+ DW 0 ; Reserved
+ DD 0 ; ESP2
+ DW 0 ; SS2
+ DW 0 ; Reserved
+ DD 0 ; CR3
+ DD 0 ; EIP
+ DD 0 ; EFLAGS
+ DD 0 ; EAX
+ DD 0 ; ECX
+ DD 0 ; EDX
+ DD 0 ; EBX
+ DD 0 ; ESP
+ DD 0 ; EBP
+ DD 0 ; ESI
+ DD 0 ; EDI
+ DW 0 ; ES
+ DW 0 ; Reserved
+ DW 0 ; CS
+ DW 0 ; Reserved
+ DW 0 ; SS
+ DW 0 ; Reserved
+ DW 0 ; DS
+ DW 0 ; Reserved
+ DW 0 ; FS
+ DW 0 ; Reserved
+ DW 0 ; GS
+ DW 0 ; Reserved
+ DW 0 ; LDT Selector
+ DW 0 ; Reserved
+ DW 0 ; T
+ DW 0 ; I/O Map Base
+TSS_DESC_SIZE = $ - offset TssDescriptor
+
+ExceptionTssDescriptor LABEL BYTE
+ DW 0 ; PreviousTaskLink
+ DW 0 ; Reserved
+ DD 0 ; ESP0
+ DW 0 ; SS0
+ DW 0 ; Reserved
+ DD 0 ; ESP1
+ DW 0 ; SS1
+ DW 0 ; Reserved
+ DD 0 ; ESP2
+ DW 0 ; SS2
+ DW 0 ; Reserved
+ DD 0 ; CR3
+ DD offset PFHandlerEntry ; EIP
+ DD 00000002 ; EFLAGS
+ DD 0 ; EAX
+ DD 0 ; ECX
+ DD 0 ; EDX
+ DD 0 ; EBX
+ DD 0 ; ESP
+ DD 0 ; EBP
+ DD 0 ; ESI
+ DD 0 ; EDI
+ DW DATA_SEL ; ES
+ DW 0 ; Reserved
+ DW CODE_SEL ; CS
+ DW 0 ; Reserved
+ DW DATA_SEL ; SS
+ DW 0 ; Reserved
+ DW DATA_SEL ; DS
+ DW 0 ; Reserved
+ DW DATA_SEL ; FS
+ DW 0 ; Reserved
+ DW DATA_SEL ; GS
+ DW 0 ; Reserved
+ DW 0 ; LDT Selector
+ DW 0 ; Reserved
+ DW 0 ; T
+ DW 0 ; I/O Map Base
+
+gcPsd LABEL BYTE
+ DB 'PSDSIG '
+ DW PSD_SIZE
+ DW 2
+ DW 1 SHL 2
+ DW CODE_SEL
+ DW DATA_SEL
+ DW DATA_SEL
+ DW DATA_SEL
+ DW 0
+ DQ 0
+ DQ 0
+ DQ 0
+ DQ offset NullSeg
+ DD GDT_SIZE
+ DD 0
+ DB 24 dup (0)
+ DQ offset gSmiMtrrs
+PSD_SIZE = $ - offset gcPsd
+
+gcSmiGdtr LABEL FWORD
+ DW GDT_SIZE - 1
+ DD offset NullSeg
+
+gcSmiIdtr LABEL FWORD
+ DW IDT_SIZE - 1
+ DD offset _SmiIDT
+
+_SmiIDT LABEL QWORD
+REPEAT 32
+ DW 0 ; Offset 0:15
+ DW CODE_SEL ; Segment selector
+ DB 0 ; Unused
+ DB 8eh ; Interrupt Gate, Present
+ DW 0 ; Offset 16:31
+ ENDM
+IDT_SIZE = $ - offset _SmiIDT
+
+TaskGateDescriptor LABEL DWORD
+ DW 0 ; Reserved
+ DW EXCEPTION_TSS_SEL ; TSS Segment selector
+ DB 0 ; Reserved
+ DB 85h ; Task Gate, present, DPL = 0
+ DW 0 ; Reserved
+
+;
+; point to the external interrupt vector table
+;
+ExternalVectorTablePtr DWORD 0
+
+;
+; Saved IDT Entry for Page Fault
+;
+gSavedPageFaultIdtEntry LABEL DWORD
+ DD 0
+ DD 0
+
+;
+; Saved IDT Entry for INT 1
+;
+gSavedDebugExceptionIdtEntry LABEL DWORD
+ DD 0
+ DD 0
+
+
+ .code
+
+InitializeSmmExternalVectorTablePtr PROC PUBLIC
+ mov eax, [esp+4]
+ mov ExternalVectorTablePtr, eax
+ ret
+InitializeSmmExternalVectorTablePtr ENDP
+
+;------------------------------------------------------------------------------
+; Exception handlers
+;------------------------------------------------------------------------------
+_SmiExceptionHandlers PROC
+IHDLRIDX = 0
+REPEAT 8 ; INT0 ~ INT7
+ push eax ; dummy error code
+ push IHDLRIDX
+ DB 0e9h ; jmp disp32
+ DD _SmiExceptionEntryPoint - ($ + 4)
+IHDLRIDX = IHDLRIDX + 1
+ ENDM
+REPEAT 1 ; INT8
+ push IHDLRIDX
+ DB 0e9h ; jmp disp32
+ DD _SmiExceptionEntryPoint - ($ + 4)
+ int 3
+IHDLRIDX = IHDLRIDX + 1
+ ENDM
+REPEAT 1 ; INT9
+ push eax ; dummy error code
+ push IHDLRIDX
+ DB 0e9h ; jmp disp32
+ DD _SmiExceptionEntryPoint - ($ + 4)
+IHDLRIDX = IHDLRIDX + 1
+ ENDM
+REPEAT 5 ; INT10 ~ INT14
+ push IHDLRIDX
+ DB 0e9h ; jmp disp32
+ DD _SmiExceptionEntryPoint - ($ + 4)
+ int 3
+IHDLRIDX = IHDLRIDX + 1
+ ENDM
+REPEAT 2 ; INT15 ~ INT16
+ push eax ; dummy error code
+ push IHDLRIDX
+ DB 0e9h ; jmp disp32
+ DD _SmiExceptionEntryPoint - ($ + 4)
+IHDLRIDX = IHDLRIDX + 1
+ ENDM
+REPEAT 1 ; INT17
+ push IHDLRIDX
+ DB 0e9h ; jmp disp32
+ DD _SmiExceptionEntryPoint - ($ + 4)
+ int 3
+IHDLRIDX = IHDLRIDX + 1
+ ENDM
+REPEAT 14 ; INT18 ~ INT31
+ push eax ; dummy error code
+ push IHDLRIDX
+ DB 0e9h ; jmp disp32
+ DD _SmiExceptionEntryPoint - ($ + 4)
+IHDLRIDX = IHDLRIDX + 1
+ ENDM
+_SmiExceptionHandlers ENDP
+
+;------------------------------------------------------------------------------
+; _SmiExceptionEntryPoint is the entry point for all exceptions
+;
+;
+; Stack:
+; +---------------------+
+; + EFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + EIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+; + EBP +
+; +---------------------+ <-- EBP
+;
+;
+;------------------------------------------------------------------------------
+_SmiExceptionEntryPoint PROC
+
+
+ push ebp
+ mov ebp, esp
+
+
+ ;
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ ; is 16-byte aligned
+ ;
+ and esp, 0fffffff0h
+ sub esp, 12
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ push eax
+ push ecx
+ push edx
+ push ebx
+ lea ecx, [ebp + 6 * 4]
+ push ecx ; ESP
+ push dword ptr [ebp] ; EBP
+ push esi
+ push edi
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ mov eax, ss
+ push eax
+ movzx eax, word ptr [ebp + 4 * 4]
+ push eax
+ mov eax, ds
+ push eax
+ mov eax, es
+ push eax
+ mov eax, fs
+ push eax
+ mov eax, gs
+ push eax
+
+;; UINT32 Eip;
+ mov eax, [ebp + 3 * 4]
+ push eax
+
+;; UINT32 Gdtr[2], Idtr[2];
+ sub esp, 8
+ sidt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ mov [esp+4], eax
+
+ sub esp, 8
+ sgdt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ mov [esp+4], eax
+
+;; UINT32 Ldtr, Tr;
+ xor eax, eax
+ str ax
+ push eax
+ sldt ax
+ push eax
+
+;; UINT32 EFlags;
+ mov eax, [ebp + 5 * 4]
+ push eax
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ mov eax, cr4
+ or eax, 208h
+ mov cr4, eax
+ push eax
+ mov eax, cr3
+ push eax
+ mov eax, cr2
+ push eax
+ xor eax, eax
+ push eax
+ mov eax, cr0
+ push eax
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov eax, dr7
+ push eax
+ mov eax, dr6
+ push eax
+ mov eax, dr3
+ push eax
+ mov eax, dr2
+ push eax
+ mov eax, dr1
+ push eax
+ mov eax, dr0
+ push eax
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ sub esp, 512
+ mov edi, esp
+ db 0fh, 0aeh, 07h ;fxsave [edi]
+
+; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push dword ptr [ebp + 2 * 4]
+
+;; call into exception handler
+ mov eax, ExternalVectorTablePtr ; get the interrupt vectors base
+ or eax, eax ; NULL?
+ jz nullExternalExceptionHandler
+
+ mov ecx, [ebp + 4]
+ mov eax, [eax + ecx * 4]
+ or eax, eax ; NULL?
+ jz nullExternalExceptionHandler
+
+;; Prepare parameter and call
+ mov edx, esp
+ push edx
+ mov edx, dword ptr [ebp + 1 * 4]
+ push edx
+
+ ;
+ ; Call External Exception Handler
+ ;
+ call eax
+ add esp, 8
+ jmp @F
+
+nullExternalExceptionHandler:
+; CpuDeadLoop() is the default exception handler since it preserves the processor
+; branch log.
+ call CpuDeadLoop
+
+@@:
+;; UINT32 ExceptionData;
+ add esp, 4
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ mov esi, esp
+ db 0fh, 0aeh, 0eh ; fxrstor [esi]
+ add esp, 512
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add esp, 4 * 6
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop eax
+ mov cr0, eax
+ add esp, 4 ; not for Cr1
+ pop eax
+ mov cr2, eax
+ pop eax
+ mov cr3, eax
+ pop eax
+ mov cr4, eax
+
+;; UINT32 EFlags;
+ pop dword ptr [ebp + 5 * 4]
+
+;; UINT32 Ldtr, Tr;
+;; UINT32 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add esp, 24
+
+;; UINT32 Eip;
+ pop dword ptr [ebp + 3 * 4]
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+;; NOTE - modified segment registers could hang the debugger... We
+;; could attempt to insulate ourselves against this possibility,
+;; but that poses risks as well.
+;;
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ pop dword ptr [ebp + 4 * 4]
+ pop ss
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pop edi
+ pop esi
+ add esp, 4 ; not for ebp
+ add esp, 4 ; not for esp
+ pop ebx
+ pop edx
+ pop ecx
+ pop eax
+
+ mov esp, ebp
+ pop ebp
+
+; Set single step DB# if SMM profile is enabled and page fault exception happens
+ cmp FeaturePcdGet (PcdCpuSmmProfileEnable), 0
+ jz @Done
+; Check if this is page fault exception
+ cmp dword ptr [esp], 0eh
+ jnz @F
+; Enable TF bit after page fault handler runs
+ bts dword ptr [esp + 16], 8 ; EFLAGS
+ jmp @Done
+@@:
+; Check if this is INT 1 exception
+ cmp dword ptr [esp], 1
+ jnz @Done
+; Clear TF bit after INT1 handler runs
+ btc dword ptr [esp + 16], 8 ; EFLAGS
+@Done:
+
+ add esp, 8 ; skip INT# & ErrCode
+Return:
+ iretd
+;
+; Page Fault Exception Handler entry when SMM Stack Guard is enabled
+; Executiot starts here after a task switch
+;
+PFHandlerEntry::
+;
+; Get this processor's TSS
+;
+ sub esp, 8
+ sgdt [esp + 2]
+ mov eax, [esp + 4] ; GDT base
+ add esp, 8
+ mov ecx, [eax + TSS_SEL + 2]
+ shl ecx, 8
+ mov cl, [eax + TSS_SEL + 7]
+ ror ecx, 8 ; ecx = TSS base
+
+ mov ebp, esp
+
+ ;
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ ; is 16-byte aligned
+ ;
+ and esp, 0fffffff0h
+ sub esp, 12
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ push (IA32_TSS ptr [ecx])._EAX
+ push (IA32_TSS ptr [ecx])._ECX
+ push (IA32_TSS ptr [ecx])._EDX
+ push (IA32_TSS ptr [ecx])._EBX
+ push (IA32_TSS ptr [ecx])._ESP
+ push (IA32_TSS ptr [ecx])._EBP
+ push (IA32_TSS ptr [ecx])._ESI
+ push (IA32_TSS ptr [ecx])._EDI
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ movzx eax, (IA32_TSS ptr [ecx])._SS
+ push eax
+ movzx eax, (IA32_TSS ptr [ecx])._CS
+ push eax
+ movzx eax, (IA32_TSS ptr [ecx])._DS
+ push eax
+ movzx eax, (IA32_TSS ptr [ecx])._ES
+ push eax
+ movzx eax, (IA32_TSS ptr [ecx])._FS
+ push eax
+ movzx eax, (IA32_TSS ptr [ecx])._GS
+ push eax
+
+;; UINT32 Eip;
+ push (IA32_TSS ptr [ecx]).EIP
+
+;; UINT32 Gdtr[2], Idtr[2];
+ sub esp, 8
+ sidt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ mov [esp+4], eax
+
+ sub esp, 8
+ sgdt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ mov [esp+4], eax
+
+;; UINT32 Ldtr, Tr;
+ mov eax, TSS_SEL
+ push eax
+ movzx eax, (IA32_TSS ptr [ecx]).LDT
+ push eax
+
+;; UINT32 EFlags;
+ push (IA32_TSS ptr [ecx]).EFLAGS
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ mov eax, cr4
+ or eax, 208h
+ mov cr4, eax
+ push eax
+ mov eax, cr3
+ push eax
+ mov eax, cr2
+ push eax
+ xor eax, eax
+ push eax
+ mov eax, cr0
+ push eax
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov eax, dr7
+ push eax
+ mov eax, dr6
+ push eax
+ mov eax, dr3
+ push eax
+ mov eax, dr2
+ push eax
+ mov eax, dr1
+ push eax
+ mov eax, dr0
+ push eax
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ sub esp, 512
+ mov edi, esp
+ db 0fh, 0aeh, 07h ;fxsave [edi]
+
+; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+;; UINT32 ExceptionData;
+ push dword ptr [ebp]
+
+;; call into exception handler
+ mov eax, ExternalVectorTablePtr ; get the interrupt vectors base
+ or eax, eax ; NULL?
+ jz nullExternalExceptionHandler
+
+ mov ebx, ecx
+ mov ecx, 14
+ mov eax, [eax + ecx * 4]
+ or eax, eax ; NULL?
+ jz nullExternalExceptionHandler
+
+;; Prepare parameter and call
+ mov edx, esp
+ push edx
+ mov edx, 14
+ push edx
+
+ ;
+ ; Call External Exception Handler
+ ;
+ call eax
+ add esp, 8
+
+ mov ecx, ebx
+;; UINT32 ExceptionData;
+ add esp, 4
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ mov esi, esp
+ db 0fh, 0aeh, 0eh ; fxrstor [esi]
+ add esp, 512
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+;; Skip restoration of DRx registers to support in-circuit emualators
+;; or debuggers set breakpoint in interrupt/exception context
+ add esp, 4 * 6
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop eax
+ mov cr0, eax
+ add esp, 4 ; not for Cr1
+ pop eax
+ mov cr2, eax
+ pop eax
+ mov (IA32_TSS ptr [ecx])._CR3, eax
+ pop eax
+ mov cr4, eax
+
+;; UINT32 EFlags;
+ pop (IA32_TSS ptr [ecx]).EFLAGS
+
+;; UINT32 Ldtr, Tr;
+;; UINT32 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add esp, 24
+
+;; UINT32 Eip;
+ pop (IA32_TSS ptr [ecx]).EIP
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+;; NOTE - modified segment registers could hang the debugger... We
+;; could attempt to insulate ourselves against this possibility,
+;; but that poses risks as well.
+;;
+ pop eax
+ mov (IA32_TSS ptr [ecx])._GS, ax
+ pop eax
+ mov (IA32_TSS ptr [ecx])._FS, ax
+ pop eax
+ mov (IA32_TSS ptr [ecx])._ES, ax
+ pop eax
+ mov (IA32_TSS ptr [ecx])._DS, ax
+ pop eax
+ mov (IA32_TSS ptr [ecx])._CS, ax
+ pop eax
+ mov (IA32_TSS ptr [ecx])._SS, ax
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pop (IA32_TSS ptr [ecx])._EDI
+ pop (IA32_TSS ptr [ecx])._ESI
+ add esp, 4 ; not for ebp
+ add esp, 4 ; not for esp
+ pop (IA32_TSS ptr [ecx])._EBX
+ pop (IA32_TSS ptr [ecx])._EDX
+ pop (IA32_TSS ptr [ecx])._ECX
+ pop (IA32_TSS ptr [ecx])._EAX
+
+ mov esp, ebp
+
+; Set single step DB# if SMM profile is enabled and page fault exception happens
+ cmp FeaturePcdGet (PcdCpuSmmProfileEnable), 0
+ jz @Done2
+; Enable TF bit after page fault handler runs
+ bts (IA32_TSS ptr [ecx]).EFLAGS, 8 ; EFLAGS
+
+@Done2:
+
+ add esp, 4 ; skip ErrCode
+
+ jmp Return
+_SmiExceptionEntryPoint ENDP
+
+InitializeIDT PROC USES ebx
+ lea edx, _SmiIDT - 8
+; push IDT_SIZE / 8
+ DB 68h ; push /id
+ DD IDT_SIZE / 8
+ lea ebx, _SmiExceptionHandlers - 8
+ pop ecx
+@@:
+ lea eax, [ebx + ecx*8]
+ mov [edx + ecx*8], ax
+ shr eax, 16
+ mov [edx + ecx*8 + 6], ax
+ loop @B
+
+ cmp FeaturePcdGet (PcdCpuSmmStackGuard), 0
+ jz @F
+
+;
+; If SMM Stack Guard feature is enabled, the Page Fault Exception entry in IDT
+; is a Task Gate Descriptor so that when a Page Fault Exception occurrs,
+; the processors can use a known good stack in case stack is ran out.
+;
+ lea ebx, _SmiIDT + 14 * 8
+ lea edx, TaskGateDescriptor
+ mov eax, [edx]
+ mov [ebx], eax
+ mov eax, [edx + 4]
+ mov [ebx + 4], eax
+
+@@:
+;
+; Save Page Fault IDT entry in gPageFaultIdtEntry
+;
+ lea ebx, _SmiIDT + 14 * 8
+ lea edx, gSavedPageFaultIdtEntry
+ mov eax, [ebx]
+ mov [edx], eax
+ mov eax, [ebx + 4]
+ mov [edx + 4], eax
+
+ cmp FeaturePcdGet (PcdCpuSmmProfileEnable), 0
+ jz @F
+
+;
+; Save INT 1 IDT entry in gSavedDebugExceptionIdtEntry
+;
+ lea ebx, _SmiIDT + 1 * 8
+ lea edx, gSavedDebugExceptionIdtEntry
+ mov eax, [ebx]
+ mov [edx], eax
+ mov eax, [ebx + 4]
+ mov [edx + 4], eax
+
+@@:
+ ret
+InitializeIDT ENDP
+
+ END
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmInit.S b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmInit.S
new file mode 100644
index 0000000..1a663e3
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmInit.S
@@ -0,0 +1,122 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# SmmInit.S
+#
+# Abstract:
+#
+# Functions for relocating SMBASE's for all processors
+#
+# Notes:
+#
+#------------------------------------------------------------------------------
+
+
+ASM_GLOBAL ASM_PFX(gSmmCr0)
+ASM_GLOBAL ASM_PFX(gSmmCr3)
+ASM_GLOBAL ASM_PFX(gSmmCr4)
+ASM_GLOBAL ASM_PFX(gcSmmInitTemplate)
+ASM_GLOBAL ASM_PFX(gcSmmInitSize)
+ASM_GLOBAL ASM_PFX(gSmmJmpAddr)
+ASM_GLOBAL ASM_PFX(SmmRelocationSemaphoreComplete)
+ASM_GLOBAL ASM_PFX(gSmmInitStack)
+
+ .data
+
+NullSeg: .quad 0
+DataSeg32:
+ .word -1 # LimitLow
+ .word 0 # BaseLow
+ .byte 0 # BaseMid
+ .byte 0x93
+ .byte 0xcf # LimitHigh
+ .byte 0 # BaseHigh
+CodeSeg32:
+ .word -1 # LimitLow
+ .word 0 # BaseLow
+ .byte 0 # BaseMid
+ .byte 0x9b
+ .byte 0xcf # LimitHigh
+ .byte 0 # BaseHigh
+.equ GDT_SIZE, . - NullSeg
+
+ .text
+
+GdtDesc:
+ .word GDT_SIZE
+ .long NullSeg
+
+SmmStartup:
+ .byte 0x66,0xb8
+ASM_PFX(gSmmCr3): .space 4
+ movl %eax, %cr3
+ .byte 0x67,0x66
+ lgdt %cs:(GdtDesc - SmmStartup)(%ebp)
+ .byte 0x66,0xb8
+ASM_PFX(gSmmCr4): .space 4
+ movl %eax, %cr4
+ .byte 0x66,0xb8
+ASM_PFX(gSmmCr0): .space 4
+ .byte 0xbf,8,0 # mov di, 8
+ movl %eax, %cr0
+ .byte 0x66,0xea # jmp far [ptr48]
+ASM_PFX(gSmmJmpAddr): .long Start32bit
+ .word 0x10
+Start32bit:
+ movl %edi,%ds
+ movl %edi,%es
+ movl %edi,%fs
+ movl %edi,%gs
+ movl %edi,%ss
+ .byte 0xbc # mov esp, imm32
+ASM_PFX(gSmmInitStack): .space 4
+ call ASM_PFX(SmmInitHandler)
+ rsm
+
+ASM_PFX(gcSmmInitTemplate):
+
+_SmmInitTemplate:
+ .byte 0x66
+ movl $SmmStartup, %ebp
+ .byte 0x66, 0x81, 0xed, 0, 0, 3, 0 # sub ebp, 0x30000
+ jmp *%bp # jmp ebp actually
+
+ASM_PFX(gcSmmInitSize): .word . - ASM_PFX(gcSmmInitTemplate)
+
+
+ASM_PFX(SmmRelocationSemaphoreComplete):
+ pushl %eax
+ movl ASM_PFX(mRebasedFlag), %eax
+ movb $1, (%eax)
+ popl %eax
+ jmp *ASM_PFX(mSmmRelocationOriginalAddress)
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmInit.asm b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmInit.asm
new file mode 100644
index 0000000..51dbfe3
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmInit.asm
@@ -0,0 +1,132 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; SmmInit.Asm
+;
+; Abstract:
+;
+; Functions for relocating SMBASE's for all processors
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ .686p
+ .xmm
+ .model flat,C
+
+SmmInitHandler PROTO C
+
+EXTERNDEF C gSmmCr0:DWORD
+EXTERNDEF C gSmmCr3:DWORD
+EXTERNDEF C gSmmCr4:DWORD
+EXTERNDEF C gcSmmInitTemplate:BYTE
+EXTERNDEF C gcSmmInitSize:WORD
+EXTERNDEF C gSmmJmpAddr:QWORD
+EXTERNDEF C mRebasedFlag:PTR BYTE
+EXTERNDEF C mSmmRelocationOriginalAddress:DWORD
+EXTERNDEF C gSmmInitStack:DWORD
+
+ .data
+
+NullSeg DQ 0 ; reserved by architecture
+DataSeg32 LABEL QWORD
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 93h
+ DB 0cfh ; LimitHigh
+ DB 0 ; BaseHigh
+CodeSeg32 LABEL QWORD
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 9bh
+ DB 0cfh ; LimitHigh
+ DB 0 ; BaseHigh
+GDT_SIZE = $ - offset NullSeg
+
+ .code
+
+GdtDesc LABEL FWORD
+ DW GDT_SIZE
+ DD offset NullSeg
+
+SmmStartup PROC
+ DB 66h, 0b8h
+gSmmCr3 DD ?
+ mov cr3, eax
+ DB 67h, 66h
+ lgdt fword ptr cs:[ebp + (offset GdtDesc - SmmStartup)]
+ DB 66h, 0b8h
+gSmmCr4 DD ?
+ mov cr4, eax
+ DB 66h, 0b8h
+gSmmCr0 DD ?
+ DB 0bfh, 8, 0 ; mov di, 8
+ mov cr0, eax
+ DB 66h, 0eah ; jmp far [ptr48]
+gSmmJmpAddr LABEL QWORD
+ DD @32bit
+ DW 10h
+@32bit:
+ mov ds, edi
+ mov es, edi
+ mov fs, edi
+ mov gs, edi
+ mov ss, edi
+ DB 0bch ; mov esp, imm32
+gSmmInitStack DD ?
+ call SmmInitHandler
+ rsm
+SmmStartup ENDP
+
+gcSmmInitTemplate LABEL BYTE
+
+_SmmInitTemplate PROC
+ DB 66h
+ mov ebp, SmmStartup
+ DB 66h, 81h, 0edh, 00h, 00h, 03h, 00 ; sub ebp, 30000h
+ jmp bp ; jmp ebp actually
+_SmmInitTemplate ENDP
+
+gcSmmInitSize DW $ - gcSmmInitTemplate
+
+SmmRelocationSemaphoreComplete PROC
+ push eax
+ mov eax, mRebasedFlag
+ mov byte ptr [eax], 1
+ pop eax
+ jmp [mSmmRelocationOriginalAddress]
+SmmRelocationSemaphoreComplete ENDP
+
+ END
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c
new file mode 100644
index 0000000..2a0ad04
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c
@@ -0,0 +1,84 @@
+/** @file
+ IA-32 processor specific functions to enable SMM profile.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+#include "SmmProfileInternal.h"
+
+/**
+ Create SMM page table for S3 path.
+
+**/
+VOID
+InitSmmS3Cr3 (
+ VOID
+ )
+{
+ mSmmS3ResumeState->SmmS3Cr3 = Gen4GPageTable (0);
+
+ return ;
+}
+
+/**
+ Allocate pages for creating 4KB-page based on 2MB-page when page fault happens.
+ 32-bit firmware does not need it.
+
+**/
+VOID
+InitPagesForPFHandler (
+ VOID
+ )
+{
+}
+
+/**
+ Update page table to map the memory correctly in order to make the instruction
+ which caused page fault execute successfully. And it also save the original page
+ table to be restored in single-step exception. 32-bit firmware does not need it.
+
+ @param PageTable PageTable Address.
+ @param PFAddress The memory address which caused page fault exception.
+ @param CpuIndex The index of the processor.
+ @param ErrorCode The Error code of exception.
+ @param IsValidPFAddress The flag indicates if SMM profile data need be added.
+
+**/
+VOID
+RestorePageTableAbove4G (
+ UINT64 *PageTable,
+ UINT64 PFAddress,
+ UINTN CpuIndex,
+ UINTN ErrorCode,
+ BOOLEAN *IsValidPFAddress
+ )
+{
+}
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.h b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.h
new file mode 100644
index 0000000..0cc3077
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.h
@@ -0,0 +1,116 @@
+/** @file
+ IA-32 processor specific header file.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SMM_PROFILE_ARCH_H_
+#define _SMM_PROFILE_ARCH_H_
+
+#pragma pack (1)
+
+typedef struct _MSR_DS_AREA_STRUCT {
+ UINT32 BTSBufferBase;
+ UINT32 BTSIndex;
+ UINT32 BTSAbsoluteMaximum;
+ UINT32 BTSInterruptThreshold;
+ UINT32 PEBSBufferBase;
+ UINT32 PEBSIndex;
+ UINT32 PEBSAbsoluteMaximum;
+ UINT32 PEBSInterruptThreshold;
+ UINT32 PEBSCounterReset[4];
+ UINT32 Reserved;
+} MSR_DS_AREA_STRUCT;
+
+typedef struct _BRANCH_TRACE_RECORD {
+ UINT32 LastBranchFrom;
+ UINT32 LastBranchTo;
+ UINT32 Rsvd0 : 4;
+ UINT32 BranchPredicted : 1;
+ UINT32 Rsvd1 : 27;
+} BRANCH_TRACE_RECORD;
+
+typedef struct _PEBS_RECORD {
+ UINT32 Eflags;
+ UINT32 LinearIP;
+ UINT32 Eax;
+ UINT32 Ebx;
+ UINT32 Ecx;
+ UINT32 Edx;
+ UINT32 Esi;
+ UINT32 Edi;
+ UINT32 Ebp;
+ UINT32 Esp;
+} PEBS_RECORD;
+
+#pragma pack ()
+
+#define PHYSICAL_ADDRESS_MASK ((1ull << 32) - SIZE_4KB)
+
+/**
+ Update page table to map the memory correctly in order to make the instruction
+ which caused page fault execute successfully. And it also save the original page
+ table to be restored in single-step exception. 32-bit firmware does not need it.
+
+ @param PageTable PageTable Address.
+ @param PFAddress The memory address which caused page fault exception.
+ @param CpuIndex The index of the processor.
+ @param ErrorCode The Error code of exception.
+ @param IsValidPFAddress The flag indicates if SMM profile data need be added.
+
+**/
+VOID
+RestorePageTableAbove4G (
+ UINT64 *PageTable,
+ UINT64 PFAddress,
+ UINTN CpuIndex,
+ UINTN ErrorCode,
+ BOOLEAN *IsValidPFAddress
+ );
+
+/**
+ Create SMM page table for S3 path.
+
+**/
+VOID
+InitSmmS3Cr3 (
+ VOID
+ );
+
+/**
+ Allocate pages for creating 4KB-page based on 2MB-page when page fault happens.
+
+**/
+VOID
+InitPagesForPFHandler (
+ VOID
+ );
+
+#endif // _SMM_PROFILE_ARCH_H_
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/MpService.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/MpService.c
new file mode 100644
index 0000000..12406ed
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/MpService.c
@@ -0,0 +1,1813 @@
+/** @file
+SMM MP service inplementation
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+
+//
+// Slots for all MTRR( FIXED MTRR + VARIABLE MTRR + MTRR_LIB_IA32_MTRR_DEF_TYPE)
+//
+UINT64 gSmiMtrrs[MTRR_NUMBER_OF_FIXED_MTRR + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
+UINT64 gPhyMask;
+SMM_DISPATCHER_MP_SYNC_DATA *mSmmMpSyncData = NULL;
+BOOLEAN mExceptionHandlerReady = FALSE;
+SPIN_LOCK mIdtTableLock;
+
+/**
+ Performs an atomic compare exchange operation to get semaphore.
+ The compare exchange operation must be performed using
+ MP safe mechanisms.
+
+ @param Sem IN: 32-bit unsigned integer
+ OUT: original integer - 1
+ @return Orignal integer - 1
+
+**/
+UINT32
+WaitForSemaphore (
+ IN OUT volatile UINT32 *Sem
+ )
+{
+ UINT32 Value;
+
+ do {
+ Value = *Sem;
+ } while (Value == 0 ||
+ InterlockedCompareExchange32 (
+ (UINT32*)Sem,
+ Value,
+ Value - 1
+ ) != Value);
+ return Value - 1;
+}
+
+
+/**
+ Performs an atomic compare exchange operation to release semaphore.
+ The compare exchange operation must be performed using
+ MP safe mechanisms.
+
+ @param Sem IN: 32-bit unsigned integer
+ OUT: original integer + 1
+ @return Orignal integer + 1
+
+**/
+UINT32
+ReleaseSemaphore (
+ IN OUT volatile UINT32 *Sem
+ )
+{
+ UINT32 Value;
+
+ do {
+ Value = *Sem;
+ } while (Value + 1 != 0 &&
+ InterlockedCompareExchange32 (
+ (UINT32*)Sem,
+ Value,
+ Value + 1
+ ) != Value);
+ return Value + 1;
+}
+
+/**
+ Performs an atomic compare exchange operation to lock semaphore.
+ The compare exchange operation must be performed using
+ MP safe mechanisms.
+
+ @param Sem IN: 32-bit unsigned integer
+ OUT: -1
+ @return Orignal integer
+
+**/
+UINT32
+LockdownSemaphore (
+ IN OUT volatile UINT32 *Sem
+ )
+{
+ UINT32 Value;
+
+ do {
+ Value = *Sem;
+ } while (InterlockedCompareExchange32 (
+ (UINT32*)Sem,
+ Value, (UINT32)-1
+ ) != Value);
+ return Value;
+}
+
+/**
+ Wait all APs to performs an atomic compare exchange operation to release semaphore.
+
+ @param NumberOfAPs AP number
+
+**/
+VOID
+WaitForAllAPs (
+ IN UINTN NumberOfAPs
+ )
+{
+ UINTN BspIndex;
+
+ BspIndex = mSmmMpSyncData->BspIndex;
+ while (NumberOfAPs-- > 0) {
+ WaitForSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
+ }
+}
+
+/**
+ Performs an atomic compare exchange operation to release semaphore
+ for each AP.
+
+**/
+VOID
+ReleaseAllAPs (
+ VOID
+ )
+{
+ UINTN Index;
+ UINTN BspIndex;
+
+ BspIndex = mSmmMpSyncData->BspIndex;
+ for (Index = mMaxNumberOfCpus; Index-- > 0;) {
+ if (Index != BspIndex && mSmmMpSyncData->CpuData[Index].Present) {
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[Index].Run);
+ }
+ }
+}
+
+/**
+ Checks if all CPUs (with certain exceptions) have checked in for this SMI run
+
+ @param Exceptions CPU Arrival exception flags.
+
+ @retval TRUE if all CPUs the have checked in.
+ @retval FALSE if at least one Normal AP hasn't checked in.
+
+**/
+BOOLEAN
+AllCpusInSmmWithExceptions (
+ SMM_CPU_ARRIVAL_EXCEPTIONS Exceptions
+ )
+{
+ UINTN Index;
+ SMM_CPU_SYNC_FEATURE *SyncFeature;
+ SMM_CPU_SYNC_FEATURE *SmmSyncFeatures;
+ SMM_CPU_DATA_BLOCK *CpuData;
+ EFI_PROCESSOR_INFORMATION *ProcessorInfo;
+
+ ASSERT (mSmmMpSyncData->Counter <= mNumberOfCpus);
+
+ if (mSmmMpSyncData->Counter == mNumberOfCpus) {
+ return TRUE;
+ }
+
+ CpuData = mSmmMpSyncData->CpuData;
+ ProcessorInfo = gSmmCpuPrivate->ProcessorInfo;
+ SmmSyncFeatures = gSmmCpuPrivate->SmmSyncFeature;
+ for (Index = mMaxNumberOfCpus; Index-- > 0;) {
+ if (!CpuData[Index].Present && ProcessorInfo[Index].ProcessorId != INVALID_APIC_ID) {
+ SyncFeature = &(SmmSyncFeatures[Index]);
+ if (((Exceptions & ARRIVAL_EXCEPTION_DELAYED) != 0) && SyncFeature->DelayIndicationSupported) {
+ continue;
+ }
+ if (((Exceptions & ARRIVAL_EXCEPTION_BLOCKED) != 0) && SyncFeature->BlockIndicationSupported) {
+ continue;
+ }
+ if (((Exceptions & ARRIVAL_EXCEPTION_SMI_DISABLED) != 0) && SyncFeature->TargetedSmiSupported) {
+ continue;
+ }
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Given timeout constraint, wait for all APs to arrive, and insure when this function returns, no AP will execute normal mode code before
+ entering SMM, except SMI disabled APs.
+
+**/
+VOID
+SmmWaitForApArrival (
+ VOID
+ )
+{
+ UINT64 Timer;
+ UINTN Index;
+
+ ASSERT (mSmmMpSyncData->Counter <= mNumberOfCpus);
+
+ //
+ // Platform implementor should choose a timeout value appropriately:
+ // - The timeout value should balance the SMM time constrains and the likelihood that delayed CPUs are excluded in the SMM run. Note
+ // the SMI Handlers must ALWAYS take into account the cases that not all APs are available in an SMI run.
+ // - The timeout value must, in the case of 2nd timeout, be at least long enough to give time for all APs to receive the SMI IPI
+ // and either enter SMM or buffer the SMI, to insure there is no CPU running normal mode code when SMI handling starts. This will
+ // be TRUE even if a blocked CPU is brought out of the blocked state by a normal mode CPU (before the normal mode CPU received the
+ // SMI IPI), because with a buffered SMI, and CPU will enter SMM immediately after it is brought out of the blocked state.
+ // - The timeout value must be longer than longest possible IO operation in the system
+ //
+
+ //
+ // Sync with APs 1st timeout
+ //
+ for (Timer = StartSyncTimer ();
+ !IsSyncTimerTimeout (Timer) &&
+ !AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED );
+ ) {
+ CpuPause ();
+ }
+
+ //
+ // Not all APs have arrived, so we need 2nd round of timeout. IPIs should be sent to ALL none present APs,
+ // because:
+ // a) Delayed AP may have just come out of the delayed state. Blocked AP may have just been brought out of blocked state by some AP running
+ // normal mode code. These APs need to be guaranteed to have an SMI pending to insure that once they are out of delayed / blocked state, they
+ // enter SMI immediately without executing instructions in normal mode. Note traditional flow requires there are no APs doing normal mode
+ // work while SMI handling is on-going.
+ // b) As a consequence of SMI IPI sending, (spurious) SMI may occur after this SMM run.
+ // c) ** NOTE **: Use SMI disabling feature VERY CAREFULLY (if at all) for traditional flow, because a processor in SMI-disabled state
+ // will execute normal mode code, which breaks the traditional SMI handlers' assumption that no APs are doing normal
+ // mode work while SMI handling is on-going.
+ // d) We don't add code to check SMI disabling status to skip sending IPI to SMI disabled APs, because:
+ // - In traditional flow, SMI disabling is discouraged.
+ // - In relaxed flow, CheckApArrival() will check SMI disabling status before calling this function.
+ // In both cases, adding SMI-disabling checking code increases overhead.
+ //
+ if (mSmmMpSyncData->Counter < mNumberOfCpus) {
+ //
+ // Send SMI IPIs to bring outside processors in
+ //
+ for (Index = mMaxNumberOfCpus; Index-- > 0;) {
+ if (!mSmmMpSyncData->CpuData[Index].Present && gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId != INVALID_APIC_ID) {
+ SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId);
+ }
+ }
+
+ //
+ // Sync with APs 2nd timeout.
+ //
+ for (Timer = StartSyncTimer ();
+ !IsSyncTimerTimeout (Timer) &&
+ !AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED );
+ ) {
+ CpuPause ();
+ }
+ }
+
+ return;
+}
+
+
+/**
+ Replace OS MTRR's with SMI MTRR's.
+
+ @param CpuIndex Processor Index
+
+**/
+VOID
+ReplaceOSMtrrs (
+ IN UINTN CpuIndex
+ )
+{
+ PROCESSOR_SMM_DESCRIPTOR *Psd;
+ UINT64 *SmiMtrrs;
+ MTRR_SETTINGS *BiosMtrr;
+
+ Psd = (PROCESSOR_SMM_DESCRIPTOR*)(mCpuHotPlugData.SmBase[CpuIndex] + SMM_PSD_OFFSET);
+ SmiMtrrs = (UINT64*)(UINTN)Psd->MtrrBaseMaskPtr;
+
+ DisableSmrr ();
+
+ //
+ // Replace all MTRRs registers
+ //
+ BiosMtrr = (MTRR_SETTINGS*)SmiMtrrs;
+ MtrrSetAllMtrrs(BiosMtrr);
+}
+
+/**
+ SMI handler for BSP.
+
+ @param CpuIndex BSP processor Index
+ @param SyncMode SMM MP sync mode
+
+**/
+VOID
+BSPHandler (
+ IN UINTN CpuIndex,
+ IN SMM_CPU_SYNC_MODE SyncMode
+ )
+{
+ UINTN Index;
+ MTRR_SETTINGS Mtrrs;
+ UINTN ApCount;
+ BOOLEAN ClearTopLevelSmiResult;
+ UINTN PresentCount;
+
+ ASSERT (CpuIndex == mSmmMpSyncData->BspIndex);
+ ApCount = 0;
+
+ //
+ // Flag BSP's presence
+ //
+ mSmmMpSyncData->InsideSmm = TRUE;
+
+ //
+ // Initialize Debug Agent to start source level debug in BSP handler
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_ENTER_SMI, NULL, NULL);
+
+ //
+ // Mark this processor's presence
+ //
+ mSmmMpSyncData->CpuData[CpuIndex].Present = TRUE;
+
+ //
+ // Clear platform top level SMI status bit before calling SMI handlers. If
+ // we cleared it after SMI handlers are run, we would miss the SMI that
+ // occurs after SMI handlers are done and before SMI status bit is cleared.
+ //
+ ClearTopLevelSmiResult = ClearTopLevelSmiStatus();
+ ASSERT (ClearTopLevelSmiResult == TRUE);
+
+ //
+ // Set running processor index
+ //
+ gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu = CpuIndex;
+
+ //
+ // If Traditional Sync Mode or need to configure MTRRs: gather all available APs.
+ // To-Do: make NeedConfigureMtrrs a PCD?
+ //
+ if (SyncMode == SmmCpuSyncModeTradition || NeedConfigureMtrrs()) {
+
+ //
+ // Wait for APs to arrive
+ //
+ SmmWaitForApArrival();
+
+ //
+ // Lock the counter down and retrieve the number of APs
+ //
+ mSmmMpSyncData->AllCpusInSync = TRUE;
+ ApCount = LockdownSemaphore (&mSmmMpSyncData->Counter) - 1;
+
+ //
+ // Wait for all APs to get ready for programming MTRRs
+ //
+ WaitForAllAPs (ApCount);
+
+ if (NeedConfigureMtrrs()) {
+ //
+ // Signal all APs it's time for backup MTRRs
+ //
+ ReleaseAllAPs ();
+
+ //
+ // WaitForSemaphore() may wait for ever if an AP happens to enter SMM at
+ // exactly this point. Please make sure PcdCpuSmmMaxSyncLoops has been set
+ // to a large enough value to avoid this situation.
+ // Note: For HT capable CPUs, threads within a core share the same set of MTRRs.
+ // We do the backup first and then set MTRR to avoid race condition for threads
+ // in the same core.
+ //
+ MtrrGetAllMtrrs(&Mtrrs);
+
+ //
+ // Wait for all APs to complete their MTRR saving
+ //
+ WaitForAllAPs (ApCount);
+
+ //
+ // Let all processors program SMM MTRRs together
+ //
+ ReleaseAllAPs ();
+
+ //
+ // WaitForSemaphore() may wait for ever if an AP happens to enter SMM at
+ // exactly this point. Please make sure PcdCpuSmmMaxSyncLoops has been set
+ // to a large enough value to avoid this situation.
+ //
+ ReplaceOSMtrrs (CpuIndex);
+
+ //
+ // Wait for all APs to complete their MTRR programming
+ //
+ WaitForAllAPs (ApCount);
+ }
+ }
+
+ //
+ // The BUSY lock is initialized to Acquired state
+ //
+ AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
+
+ //
+ // Special handlement for S3 boot path.
+ //
+ RestoreSmmConfigurationInS3 ();
+
+ //
+ // Invoke SMM Foundation EntryPoint with the processor information context.
+ //
+ gSmmCpuPrivate->SmmCoreEntry (&gSmmCpuPrivate->SmmCoreEntryContext);
+
+ //
+ // Make sure all APs have completed their pending none-block tasks
+ //
+ for (Index = mMaxNumberOfCpus; Index-- > 0;) {
+ if (Index != CpuIndex && mSmmMpSyncData->CpuData[Index].Present) {
+ AcquireSpinLock (&mSmmMpSyncData->CpuData[Index].Busy);
+ ReleaseSpinLock (&mSmmMpSyncData->CpuData[Index].Busy);;
+ }
+ }
+
+ //
+ // Set the EOS bit before SMI resume.
+ //
+ // BUGBUG: The following is a chipset specific action from a CPU module.
+ //
+ ClearSmi();
+
+ //
+ // If Relaxed-AP Sync Mode: gather all available APs after BSP SMM handlers are done, and
+ // make those APs to exit SMI synchronously. APs which arrive later will be excluded and
+ // will run through freely.
+ //
+ if (SyncMode != SmmCpuSyncModeTradition && !NeedConfigureMtrrs()) {
+
+ //
+ // Lock the counter down and retrieve the number of APs
+ //
+ mSmmMpSyncData->AllCpusInSync = TRUE;
+ ApCount = LockdownSemaphore (&mSmmMpSyncData->Counter) - 1;
+ //
+ // Make sure all APs have their Present flag set
+ //
+ while (TRUE) {
+ PresentCount = 0;
+ for (Index = mMaxNumberOfCpus; Index-- > 0;) {
+ if (mSmmMpSyncData->CpuData[Index].Present) {
+ PresentCount ++;
+ }
+ }
+ if (PresentCount > ApCount) {
+ break;
+ }
+ }
+ }
+
+ //
+ // Notify all APs to exit
+ //
+ mSmmMpSyncData->InsideSmm = FALSE;
+ ReleaseAllAPs ();
+
+ //
+ // Wait for all APs to complete their pending tasks
+ //
+ WaitForAllAPs (ApCount);
+
+ //
+ // Set the effective Sync Mode for next SMI run.
+ // Note this setting must be performed in the window where no APs can check in.
+ //
+ mSmmMpSyncData->EffectiveSyncMode = mSmmMpSyncData->SyncModeToBeSet;
+
+ if (NeedConfigureMtrrs()) {
+ //
+ // Signal APs to restore MTRRs
+ //
+ ReleaseAllAPs ();
+
+ //
+ // Restore OS MTRRs
+ //
+ ReenableSmrr ();
+ MtrrSetAllMtrrs(&Mtrrs);
+
+ //
+ // Wait for all APs to complete MTRR programming
+ //
+ WaitForAllAPs (ApCount);
+ }
+
+ //
+ // Stop source level debug in BSP handler, the code below will not be
+ // debugged.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_EXIT_SMI, NULL, NULL);
+
+ //
+ // Signal APs to Reset states/semaphore for this processor
+ //
+ ReleaseAllAPs ();
+
+ //
+ // Perform pending operations for hot-plug
+ //
+ SmmCpuUpdate ();
+
+ //
+ // Clear the Present flag of BSP
+ //
+ mSmmMpSyncData->CpuData[CpuIndex].Present = FALSE;
+
+ //
+ // Gather APs to exit SMM synchronously. Note the Present flag is cleared by now but
+ // WaitForAllAps does not depend on the Present flag.
+ //
+ WaitForAllAPs (ApCount);
+
+ //
+ // Reset BspIndex to -1, meaning BSP has not been elected.
+ //
+ if (FeaturePcdGet (PcdCpuSmmEnableBspElection)) {
+ mSmmMpSyncData->BspIndex = (UINT32)-1;
+ }
+
+ //
+ // Allow APs to check in from this point on
+ //
+ mSmmMpSyncData->Counter = 0;
+ mSmmMpSyncData->AllCpusInSync = FALSE;
+}
+
+/**
+ SMI handler for AP.
+
+ @param CpuIndex AP processor Index.
+ @param ValidSmi Indicates that current SMI is a valid SMI or not.
+ @param SyncMode SMM MP sync mode.
+
+**/
+VOID
+APHandler (
+ IN UINTN CpuIndex,
+ IN BOOLEAN ValidSmi,
+ IN SMM_CPU_SYNC_MODE SyncMode
+ )
+{
+ UINT64 Timer;
+ UINTN BspIndex;
+ MTRR_SETTINGS Mtrrs;
+
+ //
+ // Timeout BSP
+ //
+ for (Timer = StartSyncTimer ();
+ !IsSyncTimerTimeout (Timer) &&
+ !mSmmMpSyncData->InsideSmm;
+ ) {
+ CpuPause ();
+ }
+
+ if (!mSmmMpSyncData->InsideSmm) {
+ //
+ // BSP timeout in the first round
+ //
+ if (mSmmMpSyncData->BspIndex != -1) {
+ //
+ // BSP Index is known
+ //
+ BspIndex = mSmmMpSyncData->BspIndex;
+ ASSERT (CpuIndex != BspIndex);
+
+ //
+ // Send SMI IPI to bring BSP in
+ //
+ SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[BspIndex].ProcessorId);
+
+ //
+ // Now clock BSP for the 2nd time
+ //
+ for (Timer = StartSyncTimer ();
+ !IsSyncTimerTimeout (Timer) &&
+ !mSmmMpSyncData->InsideSmm;
+ ) {
+ CpuPause ();
+ }
+
+ if (!mSmmMpSyncData->InsideSmm) {
+ //
+ // Give up since BSP is unable to enter SMM
+ // and signal the completion of this AP
+ WaitForSemaphore (&mSmmMpSyncData->Counter);
+ return;
+ }
+ } else {
+ //
+ // Don't know BSP index. Give up without sending IPI to BSP.
+ //
+ WaitForSemaphore (&mSmmMpSyncData->Counter);
+ return;
+ }
+ }
+
+ //
+ // BSP is available
+ //
+ BspIndex = mSmmMpSyncData->BspIndex;
+ ASSERT (CpuIndex != BspIndex);
+
+ //
+ // Mark this processor's presence
+ //
+ mSmmMpSyncData->CpuData[CpuIndex].Present = TRUE;
+
+ if (SyncMode == SmmCpuSyncModeTradition || NeedConfigureMtrrs()) {
+ //
+ // Notify BSP of arrival at this point
+ //
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
+ }
+
+ if (NeedConfigureMtrrs()) {
+ //
+ // Wait for the signal from BSP to backup MTRRs
+ //
+ WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);
+
+ //
+ // Backup OS MTRRs
+ //
+ MtrrGetAllMtrrs(&Mtrrs);
+
+ //
+ // Signal BSP the completion of this AP
+ //
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
+
+ //
+ // Wait for BSP's signal to program MTRRs
+ //
+ WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);
+
+ //
+ // Replace OS MTRRs with SMI MTRRs
+ //
+ ReplaceOSMtrrs (CpuIndex);
+
+ //
+ // Signal BSP the completion of this AP
+ //
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
+ }
+
+ while (TRUE) {
+ //
+ // Wait for something to happen
+ //
+ WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);
+
+ //
+ // Check if BSP wants to exit SMM
+ //
+ if (!mSmmMpSyncData->InsideSmm) {
+ break;
+ }
+
+ //
+ // BUSY should be acquired by SmmStartupThisAp()
+ //
+ ASSERT (
+ !AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy)
+ );
+
+ //
+ // Invoke the scheduled procedure
+ //
+ (*mSmmMpSyncData->CpuData[CpuIndex].Procedure) (
+ (VOID*)mSmmMpSyncData->CpuData[CpuIndex].Parameter
+ );
+
+ //
+ // Release BUSY
+ //
+ ReleaseSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
+ }
+
+ if (NeedConfigureMtrrs()) {
+ //
+ // Notify BSP the readiness of this AP to program MTRRs
+ //
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
+
+ //
+ // Wait for the signal from BSP to program MTRRs
+ //
+ WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);
+
+ //
+ // Restore OS MTRRs
+ //
+ ReenableSmrr ();
+ MtrrSetAllMtrrs(&Mtrrs);
+ }
+
+ //
+ // Notify BSP the readiness of this AP to Reset states/semaphore for this processor
+ //
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
+
+ //
+ // Wait for the signal from BSP to Reset states/semaphore for this processor
+ //
+ WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);
+
+ //
+ // Reset states/semaphore for this processor
+ //
+ mSmmMpSyncData->CpuData[CpuIndex].Present = FALSE;
+
+ //
+ // Notify BSP the readiness of this AP to exit SMM
+ //
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
+
+}
+
+/**
+ Create 4G PageTable in SMRAM.
+
+ @param ExtraPages Additional page numbers besides for 4G memory
+ @return PageTable Address
+
+**/
+UINT32
+Gen4GPageTable (
+ IN UINTN ExtraPages
+ )
+{
+ VOID *PageTable;
+ UINTN Index;
+ UINT64 *Pte;
+ UINTN PagesNeeded;
+ UINTN Low2MBoundary;
+ UINTN High2MBoundary;
+ UINTN Pages;
+ UINTN GuardPage;
+ UINT64 *Pdpte;
+ UINTN PageIndex;
+ UINTN PageAddress;
+
+ Low2MBoundary = 0;
+ High2MBoundary = 0;
+ PagesNeeded = 0;
+ if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+ //
+ // Add one more page for known good stack, then find the lower 2MB aligned address.
+ //
+ Low2MBoundary = (mSmmStackArrayBase + EFI_PAGE_SIZE) & ~(SIZE_2MB-1);
+ //
+ // Add two more pages for known good stack and stack guard page,
+ // then find the lower 2MB aligned address.
+ //
+ High2MBoundary = (mSmmStackArrayEnd - mSmmStackSize + EFI_PAGE_SIZE * 2) & ~(SIZE_2MB-1);
+ PagesNeeded = ((High2MBoundary - Low2MBoundary) / SIZE_2MB) + 1;
+ }
+ //
+ // Allocate the page table
+ //
+ PageTable = AllocatePages (ExtraPages + 5 + PagesNeeded);
+ ASSERT (PageTable != NULL);
+
+ PageTable = (VOID *)((UINTN)PageTable + EFI_PAGES_TO_SIZE (ExtraPages));
+ Pte = (UINT64*)PageTable;
+
+ //
+ // Zero out all page table entries first
+ //
+ ZeroMem (Pte, EFI_PAGES_TO_SIZE (1));
+
+ //
+ // Set Page Directory Pointers
+ //
+ for (Index = 0; Index < 4; Index++) {
+ Pte[Index] = (UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1) + IA32_PG_P;
+ }
+ Pte += EFI_PAGE_SIZE / sizeof (*Pte);
+
+ //
+ // Fill in Page Directory Entries
+ //
+ for (Index = 0; Index < EFI_PAGE_SIZE * 4 / sizeof (*Pte); Index++) {
+ Pte[Index] = (Index << 21) + IA32_PG_PS + IA32_PG_RW + IA32_PG_P;
+ }
+
+ if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+ Pages = (UINTN)PageTable + EFI_PAGES_TO_SIZE (5);
+ GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE;
+ Pdpte = (UINT64*)PageTable;
+ for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) {
+ Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~(EFI_PAGE_SIZE - 1));
+ Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages + IA32_PG_RW + IA32_PG_P;
+ //
+ // Fill in Page Table Entries
+ //
+ Pte = (UINT64*)Pages;
+ PageAddress = PageIndex;
+ for (Index = 0; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) {
+ if (PageAddress == GuardPage) {
+ //
+ // Mark the guard page as non-present
+ //
+ Pte[Index] = PageAddress;
+ GuardPage += mSmmStackSize;
+ if (GuardPage > mSmmStackArrayEnd) {
+ GuardPage = 0;
+ }
+ } else {
+ Pte[Index] = PageAddress + IA32_PG_RW + IA32_PG_P;
+ }
+ PageAddress+= EFI_PAGE_SIZE;
+ }
+ Pages += EFI_PAGE_SIZE;
+ }
+ }
+
+ return (UINT32)(UINTN)PageTable;
+}
+
+/**
+ Set memory cache ability.
+
+ @param PageTable PageTable Address
+ @param Address Memory Address to change cache ability
+ @param Cacheability Cache ability to set
+
+**/
+VOID
+SetCacheability (
+ IN UINT64 *PageTable,
+ IN UINTN Address,
+ IN UINT8 Cacheability
+ )
+{
+ UINTN PTIndex;
+ VOID *NewPageTableAddress;
+ UINT64 *NewPageTable;
+ UINTN Index;
+
+ ASSERT ((Address & EFI_PAGE_MASK) == 0);
+
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ PTIndex = (UINTN)RShiftU64 (Address, 39) & 0x1ff;
+ ASSERT (PageTable[PTIndex] & IA32_PG_P);
+ PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask);
+ }
+
+ PTIndex = (UINTN)RShiftU64 (Address, 30) & 0x1ff;
+ ASSERT (PageTable[PTIndex] & IA32_PG_P);
+ PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask);
+
+ //
+ // A perfect implementation should check the original cacheability with the
+ // one being set, and break a 2M page entry into pieces only when they
+ // disagreed.
+ //
+ PTIndex = (UINTN)RShiftU64 (Address, 21) & 0x1ff;
+ if ((PageTable[PTIndex] & IA32_PG_PS) != 0) {
+ //
+ // Allocate a page from SMRAM
+ //
+ NewPageTableAddress = AllocatePages (1);
+ ASSERT (NewPageTableAddress != NULL);
+
+ NewPageTable = (UINT64 *)NewPageTableAddress;
+
+ for (Index = 0; Index < 0x200; Index++) {
+ NewPageTable[Index] = PageTable[PTIndex];
+ if ((NewPageTable[Index] & IA32_PG_PAT_2M) != 0) {
+ NewPageTable[Index] &= ~IA32_PG_PAT_2M;
+ NewPageTable[Index] |= IA32_PG_PAT_4K;
+ }
+ else {
+ NewPageTable[Index] &= ~IA32_PG_PAT_4K;
+ }
+ NewPageTable[Index] |= Index << EFI_PAGE_SHIFT;
+ }
+
+ PageTable[PTIndex] = ((UINTN)NewPageTableAddress & gPhyMask) | IA32_PG_P;
+ }
+
+ ASSERT (PageTable[PTIndex] & IA32_PG_P);
+ PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask);
+
+ PTIndex = (UINTN)RShiftU64 (Address, 12) & 0x1ff;
+ ASSERT (PageTable[PTIndex] & IA32_PG_P);
+ PageTable[PTIndex] &= ~(IA32_PG_PAT_4K | IA32_PG_CD | IA32_PG_WT);
+ PageTable[PTIndex] |= Cacheability;
+}
+
+
+/**
+ Schedule a procedure to run on the specified CPU.
+
+ @param Procedure The address of the procedure to run
+ @param CpuIndex Target CPU Index
+ @param ProcArguments The parameter to pass to the procedure
+
+ @retval EFI_INVALID_PARAMETER CpuNumber not valid
+ @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
+ @retval EFI_SUCCESS The procedure has been successfully scheduled
+
+**/
+EFI_STATUS
+EFIAPI
+SmmStartupThisAp (
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN CpuIndex,
+ IN OUT VOID *ProcArguments OPTIONAL
+ )
+{
+ if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus ||
+ CpuIndex == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu ||
+ !mSmmMpSyncData->CpuData[CpuIndex].Present ||
+ gSmmCpuPrivate->Operation[CpuIndex] == SmmCpuRemove ||
+ !AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;
+ mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);
+
+ if (FeaturePcdGet (PcdCpuSmmBlockStartupThisAp)) {
+ AcquireSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
+ ReleaseSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Schedule a procedure to run on the specified CPU in a blocking fashion.
+
+ @param Procedure The address of the procedure to run
+ @param CpuIndex Target CPU Index
+ @param ProcArguments The parameter to pass to the procedure
+
+ @retval EFI_INVALID_PARAMETER CpuNumber not valid
+ @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
+ @retval EFI_SUCCESS The procedure has been successfully scheduled
+
+**/
+EFI_STATUS
+EFIAPI
+SmmBlockingStartupThisAp (
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN CpuIndex,
+ IN OUT VOID *ProcArguments OPTIONAL
+ )
+{
+ if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus ||
+ CpuIndex == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu ||
+ !mSmmMpSyncData->CpuData[CpuIndex].Present ||
+ gSmmCpuPrivate->Operation[CpuIndex] == SmmCpuRemove ||
+ !AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;
+ mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;
+ ReleaseSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);
+
+ AcquireSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
+ ReleaseSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ C function for SMI entry, each processor comes here upon SMI trigger.
+
+ @param CpuIndex Cpu Index
+
+**/
+VOID
+EFIAPI
+SmiRendezvous (
+ IN UINTN CpuIndex
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN ValidSmi;
+ BOOLEAN IsBsp;
+ BOOLEAN BspInProgress;
+ UINTN Index;
+
+ //
+ // Enable exception table by load IDTR
+ //
+ AsmWriteIdtr (&gcSmiIdtr);
+ if (!mExceptionHandlerReady) {
+ //
+ // If the default CPU exception handlers were not ready
+ //
+ AcquireSpinLock (&mIdtTableLock);
+ if (!mExceptionHandlerReady) {
+
+ //
+ // Update the IDT entry to handle Page Fault exception
+ //
+ CopyMem (
+ ((IA32_IDT_GATE_DESCRIPTOR *) (gcSmiIdtr.Base + sizeof (IA32_IDT_GATE_DESCRIPTOR) * 14)),
+ &gSavedPageFaultIdtEntry,
+ sizeof (IA32_IDT_GATE_DESCRIPTOR));
+ //
+ // Update the IDT entry to handle debug exception library for smm profile
+ //
+ if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ CopyMem (
+ ((IA32_IDT_GATE_DESCRIPTOR *) (gcSmiIdtr.Base + sizeof (IA32_IDT_GATE_DESCRIPTOR) * 1)),
+ &gSavedDebugExceptionIdtEntry,
+ sizeof (IA32_IDT_GATE_DESCRIPTOR));
+ }
+ //
+ // Set CPU exception handlers ready flag
+ //
+ mExceptionHandlerReady = TRUE;
+ }
+ ReleaseSpinLock (&mIdtTableLock);
+ }
+
+ //
+ // Enable XMM instructions & exceptions
+ //
+ AsmWriteCr4 (AsmReadCr4 () | 0x600);
+
+ //
+ // Perform CPU specific entry hooks
+ //
+ SmmRendezvousEntry (CpuIndex);
+
+ //
+ // Determine if this is a valid Smi
+ //
+ ValidSmi = PlatformValidSmi();
+
+ //
+ // Determine if BSP has been already in progress. Note this must be checked after
+ // ValidSmi because BSP may clear a valid SMI source after checking in.
+ //
+ BspInProgress = mSmmMpSyncData->InsideSmm;
+
+ if (!BspInProgress && !ValidSmi) {
+ //
+ // If we reach here, it means when we sampled the ValidSmi flag, SMI status had not
+ // been cleared by BSP in a new SMI run (so we have a truly invalid SMI), or SMI
+ // status had been cleared by BSP and an existing SMI run has almost ended. (Note
+ // we sampled ValidSmi flag BEFORE judging BSP-in-progress status.) In both cases, there
+ // is nothing we need to do.
+ //
+ goto Exit;
+ } else {
+ //
+ // Signal presence of this processor
+ //
+ if (ReleaseSemaphore (&mSmmMpSyncData->Counter) == 0) {
+ //
+ // BSP has already ended the synchronization, so QUIT!!!
+ //
+
+ //
+ // Wait for BSP's signal to finish SMI
+ //
+ while (mSmmMpSyncData->AllCpusInSync) {
+ CpuPause ();
+ }
+ goto Exit;
+ } else {
+
+ //
+ // The BUSY lock is initialized to Released state.
+ // This needs to be done early enough to be ready for BSP's SmmStartupThisAp() call.
+ // E.g., with Relaxed AP flow, SmmStartupThisAp() may be called immediately
+ // after AP's present flag is detected.
+ //
+ InitializeSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
+ }
+
+ if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ ActivateSmmProfile (CpuIndex);
+ }
+
+ if (BspInProgress) {
+ //
+ // BSP has been elected. Follow AP path, regardless of ValidSmi flag
+ // as BSP may have cleared the SMI status
+ //
+ APHandler (CpuIndex, ValidSmi, mSmmMpSyncData->EffectiveSyncMode);
+ } else {
+ //
+ // We have a valid SMI
+ //
+
+ //
+ // Elect BSP
+ //
+ IsBsp = FALSE;
+ if (FeaturePcdGet (PcdCpuSmmEnableBspElection)) {
+ if (!mSmmMpSyncData->SwitchBsp || mSmmMpSyncData->CandidateBsp[CpuIndex]) {
+ //
+ // Call platform hook to do BSP election
+ //
+ Status = PlatformSmmBspElection (&IsBsp);
+ if (EFI_SUCCESS == Status) {
+ //
+ // Platform hook determines successfully
+ //
+ if (IsBsp) {
+ mSmmMpSyncData->BspIndex = (UINT32)CpuIndex;
+ }
+ } else {
+ //
+ // Platform hook fails to determine, use default BSP election method
+ //
+ InterlockedCompareExchange32 (
+ (UINT32*)&mSmmMpSyncData->BspIndex,
+ (UINT32)-1,
+ (UINT32)CpuIndex
+ );
+ }
+ }
+ }
+
+ //
+ // "mSmmMpSyncData->BspIndex == CpuIndex" means this is the BSP
+ //
+ if (mSmmMpSyncData->BspIndex == CpuIndex) {
+
+ //
+ // Clear last request for SwitchBsp.
+ //
+ if (mSmmMpSyncData->SwitchBsp) {
+ mSmmMpSyncData->SwitchBsp = FALSE;
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ mSmmMpSyncData->CandidateBsp[Index] = FALSE;
+ }
+ }
+
+ if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ SmmProfileRecordSmiNum ();
+ }
+
+ //
+ // BSP Handler is always called with a ValidSmi == TRUE
+ //
+ BSPHandler (CpuIndex, mSmmMpSyncData->EffectiveSyncMode);
+
+ } else {
+ APHandler (CpuIndex, ValidSmi, mSmmMpSyncData->EffectiveSyncMode);
+ }
+ }
+
+ ASSERT (mSmmMpSyncData->CpuData[CpuIndex].Run == 0);
+
+ //
+ // Wait for BSP's signal to exit SMI
+ //
+ while (mSmmMpSyncData->AllCpusInSync) {
+ CpuPause ();
+ }
+ }
+
+Exit:
+ SmmRendezvousExit (CpuIndex);
+ PlatformSmmExitProcessing ();
+}
+
+
+/**
+ Initialize un-cacheable data.
+
+**/
+VOID
+EFIAPI
+InitializeMpSyncData (
+ VOID
+ )
+{
+ if (mSmmMpSyncData != NULL) {
+ ZeroMem (mSmmMpSyncData, sizeof (*mSmmMpSyncData));
+ if (FeaturePcdGet (PcdCpuSmmEnableBspElection)) {
+ //
+ // Enable BSP election by setting BspIndex to -1
+ //
+ mSmmMpSyncData->BspIndex = (UINT32)-1;
+ }
+ mSmmMpSyncData->SyncModeToBeSet = SmmCpuSyncModeTradition;
+ mSmmMpSyncData->EffectiveSyncMode = SmmCpuSyncModeTradition;
+ }
+}
+
+/**
+ Initialize global data for MP synchronization.
+
+ @param ImageHandle File Image Handle.
+ @param Stacks Base address of SMI stack buffer for all processors.
+ @param StackSize Stack size for each processor in SMM.
+
+**/
+VOID
+InitializeMpServiceData (
+ IN EFI_HANDLE ImageHandle,
+ IN VOID *Stacks,
+ IN UINTN StackSize
+ )
+{
+ UINTN Index;
+ MTRR_SETTINGS *Mtrr;
+ PROCESSOR_SMM_DESCRIPTOR *Psd;
+ UINTN GdtTssTableSize;
+ UINT8 *GdtTssTables;
+ IA32_SEGMENT_DESCRIPTOR *GdtDescriptor;
+ UINTN TssBase;
+
+ //
+ // Initialize physical address mask
+ // NOTE: Physical memory above virtual address limit is not supported !!!
+ //
+ AsmCpuid (0x80000008, (UINT32*)&Index, NULL, NULL, NULL);
+ gPhyMask = LShiftU64 (1, (UINT8)Index) - 1;
+ gPhyMask &= (1ull << 48) - EFI_PAGE_SIZE;
+
+ InitializeSmmMtrrManager ();
+ //
+ // Create page tables
+ //
+ gSmiCr3 = SmmInitPageTable ();
+
+ //
+ // Initialize spin lock for setting up CPU exception handler
+ //
+ InitializeSpinLock (&mIdtTableLock);
+
+ //
+ // Initialize SMM startup code & PROCESSOR_SMM_DESCRIPTOR structures
+ //
+ gSmiStack = (UINTN)Stacks + StackSize - sizeof (UINTN);
+
+ //
+ // The Smi Handler of CPU[i] and PSD of CPU[i+x] are in the same SMM_CPU_INTERVAL,
+ // and they cannot overlap.
+ //
+ ASSERT (gcSmiHandlerSize + 0x10000 - SMM_PSD_OFFSET < SMM_CPU_INTERVAL);
+ ASSERT (SMM_HANDLER_OFFSET % SMM_CPU_INTERVAL == 0);
+
+ GdtTssTables = NULL;
+ GdtTssTableSize = 0;
+ //
+ // For X64 SMM, we allocate separate GDT/TSS for each CPUs to avoid TSS load contention
+ // on each SMI entry.
+ //
+ if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64)) {
+ GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE + 7) & ~7; // 8 bytes aligned
+ GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
+ ASSERT (GdtTssTables != NULL);
+
+ for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {
+ CopyMem (GdtTssTables + GdtTssTableSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE);
+ if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+ //
+ // Setup top of known good stack as IST1 for each processor.
+ //
+ *(UINTN *)(GdtTssTables + GdtTssTableSize * Index + gcSmiGdtr.Limit + 1 + TSS_X64_IST1_OFFSET) = (mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize);
+ }
+ }
+ } else if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+
+ //
+ // For IA32 SMM, if SMM Stack Guard feature is enabled, we use 2 TSS.
+ // in this case, we allocate separate GDT/TSS for each CPUs to avoid TSS load contention
+ // on each SMI entry.
+ //
+
+ //
+ // Enlarge GDT to contain 2 TSS descriptors
+ //
+ gcSmiGdtr.Limit += (UINT16)(2 * sizeof (IA32_SEGMENT_DESCRIPTOR));
+
+ GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE * 2 + 7) & ~7; // 8 bytes aligned
+ GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
+ ASSERT (GdtTssTables != NULL);
+
+ for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {
+ CopyMem (GdtTssTables + GdtTssTableSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE * 2);
+ //
+ // Fixup TSS descriptors
+ //
+ TssBase = (UINTN)(GdtTssTables + GdtTssTableSize * Index + gcSmiGdtr.Limit + 1);
+ GdtDescriptor = (IA32_SEGMENT_DESCRIPTOR *)(TssBase) - 2;
+ GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;
+ GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);
+ GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);
+
+ TssBase += TSS_SIZE;
+ GdtDescriptor++;
+ GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;
+ GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);
+ GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);
+ //
+ // Fixup TSS segments
+ //
+ // ESP as known good stack
+ //
+ *(UINTN *)(TssBase + TSS_IA32_ESP_OFFSET) = mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize;
+ *(UINT32 *)(TssBase + TSS_IA32_CR3_OFFSET) = gSmiCr3;
+ }
+ }
+
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ *(UINTN*)gSmiStack = Index;
+ gSmbase = (UINT32)mCpuHotPlugData.SmBase[Index];
+ CopyMem (
+ (VOID*)(UINTN)(mCpuHotPlugData.SmBase[Index] + SMM_HANDLER_OFFSET),
+ (VOID*)gcSmiHandlerTemplate,
+ gcSmiHandlerSize
+ );
+
+ Psd = (PROCESSOR_SMM_DESCRIPTOR*)(VOID*)(UINTN)(mCpuHotPlugData.SmBase[Index] + SMM_PSD_OFFSET);
+ CopyMem (Psd, &gcPsd, sizeof (gcPsd));
+ if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64)) {
+ //
+ // For X64 SMM, set GDT to the copy allocated above.
+ //
+ Psd->SmmGdtPtr = (UINT64)(UINTN)(GdtTssTables + GdtTssTableSize * Index);
+ } else if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+ //
+ // For IA32 SMM, if SMM Stack Guard feature is enabled, set GDT to the copy allocated above.
+ //
+ Psd->SmmGdtPtr = (UINT64)(UINTN)(GdtTssTables + GdtTssTableSize * Index);
+ Psd->SmmGdtSize = gcSmiGdtr.Limit + 1;
+ }
+
+ gSmiStack += StackSize;
+ }
+
+ //
+ // Initialize mSmmMpSyncData
+ //
+ mSmmMpSyncData = (SMM_DISPATCHER_MP_SYNC_DATA*) AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*mSmmMpSyncData)));
+ ASSERT (mSmmMpSyncData != NULL);
+ InitializeMpSyncData ();
+
+ if (FeaturePcdGet (PcdCpuSmmUncacheCpuSyncData)) {
+ //
+ // mSmmMpSyncData should resides in un-cached RAM
+ //
+ SetCacheability ((UINT64*)(UINTN)gSmiCr3, (UINTN)mSmmMpSyncData, IA32_PG_CD);
+ }
+
+ //
+ // Record current MTRR settings
+ //
+ ZeroMem(gSmiMtrrs, sizeof (gSmiMtrrs));
+ Mtrr = (MTRR_SETTINGS*)gSmiMtrrs;
+ MtrrGetAllMtrrs (Mtrr);
+
+}
+
+/**
+
+ Register the SMM Foundation entry point.
+
+ @param This Pointer to EFI_SMM_CONFIGURATION_PROTOCOL instance
+ @param SmmEntryPoint SMM Foundation EntryPoint
+
+ @retval EFI_SUCCESS Successfully to register SMM foundation entry point
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterSmmEntry (
+ IN CONST EFI_SMM_CONFIGURATION_PROTOCOL *This,
+ IN EFI_SMM_ENTRY_POINT SmmEntryPoint
+ )
+{
+ //
+ // Record SMM Foundation EntryPoint, later invoke it on SMI entry vector.
+ //
+ gSmmCpuPrivate->SmmCoreEntry = SmmEntryPoint;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set SMM synchronization mode starting from the next SMI run.
+
+ @param SyncMode The SMM synchronization mode to be set and effective from the next SMI run.
+
+ @retval EFI_SUCCESS The function completes successfully.
+ @retval EFI_INVALID_PARAMETER SynMode is not valid.
+
+**/
+EFI_STATUS
+SmmSyncSetModeWorker (
+ IN SMM_CPU_SYNC_MODE SyncMode
+ )
+{
+ if (SyncMode >= SmmCpuSyncModeMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Sync Mode effective from next SMI run
+ //
+ mSmmMpSyncData->SyncModeToBeSet = SyncMode;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get current effective SMM synchronization mode.
+
+ @param SyncMode Output parameter. The current effective SMM synchronization mode.
+
+ @retval EFI_SUCCESS The SMM synchronization mode has been retrieved successfully.
+ @retval EFI_INVALID_PARAMETER SyncMode is NULL.
+
+**/
+EFI_STATUS
+SmmSyncGetModeWorker (
+ OUT SMM_CPU_SYNC_MODE *SyncMode
+ )
+{
+ if (SyncMode == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *SyncMode = mSmmMpSyncData->EffectiveSyncMode;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Given timeout constraint, wait for all APs to arrive. If this function returns EFI_SUCCESS, then
+ no AP will execute normal mode code before entering SMM, so it is safe to access shared hardware resource
+ between SMM and normal mode. Note if there are SMI disabled APs, this function will return EFI_NOT_READY.
+
+
+ @retval EFI_SUCCESS No AP will execute normal mode code before entering SMM, so it is safe to access
+ shared hardware resource between SMM and normal mode
+ @retval EFI_NOT_READY One or more CPUs may still execute normal mode code
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+
+**/
+EFI_STATUS
+SmmCpuSyncCheckApArrivalWorker (
+ VOID
+ )
+{
+ UINTN Index;
+ SMM_CPU_SYNC_FEATURE *SyncFeature;
+ SMM_CPU_SYNC_FEATURE *SmmSyncFeatures;
+ SMM_CPU_DATA_BLOCK *CpuData;
+ EFI_PROCESSOR_INFORMATION *ProcessorInfo;
+
+ ASSERT (mSmmMpSyncData->Counter <= mNumberOfCpus);
+
+ if (mSmmMpSyncData->Counter == mNumberOfCpus) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check if there are any SMI Disabled APs
+ //
+ CpuData = mSmmMpSyncData->CpuData;
+ ProcessorInfo = gSmmCpuPrivate->ProcessorInfo;
+ SmmSyncFeatures = gSmmCpuPrivate->SmmSyncFeature;
+ for (Index = mMaxNumberOfCpus; Index-- > 0;) {
+ if (ProcessorInfo[Index].ProcessorId != INVALID_APIC_ID) {
+ SyncFeature = &(SmmSyncFeatures[Index]);
+ if (SyncFeature->TargetedSmiSupported) {
+ return EFI_NOT_READY;
+ }
+ }
+ }
+
+ //
+ // Wait for APs to arrive
+ //
+ SmmWaitForApArrival();
+
+ //
+ // If there are CPUs in SMI Disabled Statue, we return EFI_NOT_READY because this is not a safe environment for accessing shared
+ // hardware resource between SMM and normal mode.
+ //
+ if (AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED)) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_READY;
+ }
+}
+
+
+/**
+ Given timeout constraint, wait for all APs to arrive. If this function returns EFI_SUCCESS, then
+ no AP will execute normal mode code before entering SMM, so it is safe to access shared hardware resource
+ between SMM and normal mode. Note if there are SMI disabled APs, this function will return EFI_NOT_READY.
+
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS No AP will execute normal mode code before entering SMM, so it is safe to access
+ shared hardware resource between SMM and normal mode
+ @retval EFI_NOT_READY One or more CPUs may still execute normal mode code
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSyncCheckApArrival (
+ IN SMM_CPU_SYNC_PROTOCOL *This
+ )
+{
+ return SmmCpuSyncCheckApArrivalWorker();
+}
+
+/**
+ Given timeout constraint, wait for all APs to arrive, and insure if this function returns EFI_SUCCESS, then
+ no AP will execute normal mode code before entering SMM, so it is safe to access shared hardware resource
+ between SMM and normal mode. Note if there are SMI disabled APs, this function will return EFI_NOT_READY.
+
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS No AP will execute normal mode code before entering SMM, so it is safe to access
+ shared hardware resource between SMM and normal mode
+ @retval EFI_NOT_READY One or more CPUs may still execute normal mode code
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2CheckApArrival (
+ IN SMM_CPU_SYNC2_PROTOCOL *This
+ )
+{
+ return SmmCpuSyncCheckApArrivalWorker();
+}
+
+
+/**
+ Set SMM synchronization mode starting from the next SMI run.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode The SMM synchronization mode to be set and effective from the next SMI run.
+
+ @retval EFI_SUCCESS The function completes successfully.
+ @retval EFI_INVALID_PARAMETER SynMode is not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSyncSetMode (
+ IN SMM_CPU_SYNC_PROTOCOL *This,
+ IN SMM_CPU_SYNC_MODE SyncMode
+ )
+{
+ return SmmSyncSetModeWorker(SyncMode);
+}
+
+/**
+ Set SMM synchronization mode starting from the next SMI run.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode The SMM synchronization mode to be set and effective from the next SMI run.
+
+ @retval EFI_SUCCESS The function completes successfully.
+ @retval EFI_INVALID_PARAMETER SynMode is not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2SetMode (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN SMM_CPU_SYNC_MODE SyncMode
+ )
+{
+ return SmmSyncSetModeWorker(SyncMode);
+}
+
+
+/**
+ Get current effective SMM synchronization mode.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode Output parameter. The current effective SMM synchronization mode.
+
+ @retval EFI_SUCCESS The SMM synchronization mode has been retrieved successfully.
+ @retval EFI_INVALID_PARAMETER SyncMode is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSyncGetMode (
+ IN SMM_CPU_SYNC_PROTOCOL *This,
+ OUT SMM_CPU_SYNC_MODE *SyncMode
+ )
+{
+ return SmmSyncGetModeWorker(SyncMode);
+}
+
+/**
+ Get current effective SMM synchronization mode.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode Output parameter. The current effective SMM synchronization mode.
+
+ @retval EFI_SUCCESS The SMM synchronization mode has been retrieved successfully.
+ @retval EFI_INVALID_PARAMETER SyncMode is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2GetMode (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ OUT SMM_CPU_SYNC_MODE *SyncMode
+ )
+{
+ return SmmSyncGetModeWorker(SyncMode);
+}
+
+
+/**
+ Checks CPU SMM synchronization state
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param CpuIndex Index of the CPU for which the state is to be retrieved.
+ @param CpuState The state of the CPU
+
+ @retval EFI_SUCCESS Returns EFI_SUCCESS if the CPU's state is retrieved.
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid or CpuState is NULL
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2CheckCpuState (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex,
+ OUT SMM_CPU_SYNC2_CPU_STATE *CpuState
+ )
+{
+ SMM_CPU_SYNC_FEATURE *SyncFeature;
+
+ if (CpuIndex >= mMaxNumberOfCpus) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId == INVALID_APIC_ID) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (CpuState == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *CpuState = SmmCpuSync2StateNormal;
+ SyncFeature = &(gSmmCpuPrivate->SmmSyncFeature[CpuIndex]);
+
+ if (SyncFeature->DelayIndicationSupported) {
+ *CpuState = SmmCpuSync2StateDelayed;
+ } else if (SyncFeature->BlockIndicationSupported) {
+ *CpuState = SmmCpuSync2StateBlocked;
+ } else if (SyncFeature->TargetedSmiSupported) {
+ *CpuState = SmmCpuSync2StateDisabled;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Change CPU's SMM enabling state.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param CpuIndex Index of the CPU to enable / disable SMM
+ @param Enable If TRUE, enable SMM; if FALSE disable SMM
+
+ @retval EFI_SUCCESS The CPU's SMM enabling state is changed.
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+ @retval EFI_UNSUPPORTED Returns EFI_UNSUPPORTED the CPU does not support dynamically enabling / disabling SMI
+ @retval EFI_DEVICE_ERROR Error occured in changing SMM enabling state.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2ChangeSmmEnabling (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex,
+ IN BOOLEAN Enable
+ )
+{
+ SMM_CPU_SYNC_FEATURE *SyncFeature;
+
+ if (CpuIndex >= mMaxNumberOfCpus) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId == INVALID_APIC_ID) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SyncFeature = &(gSmmCpuPrivate->SmmSyncFeature[CpuIndex]);
+
+ if (!SyncFeature->TargetedSmiSupported) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // IA32FamilyCpuBasePkg not supporting dynamically enabling / disabling SMM.
+ // May require platform lib for this functionality.
+ //
+
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Send SMI IPI to a specific CPU.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param CpuIndex Index of the CPU to send SMI to.
+
+ @retval EFI_SUCCESS The SMI IPI is sent successfully.
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+ @retval EFI_DEVICE_ERROR Error occured in sending SMI IPI.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2SendSmi (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex
+ )
+{
+ if (CpuIndex >= mMaxNumberOfCpus) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId == INVALID_APIC_ID) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Send SMI IPI to all CPUs excluding self
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The SMI IPI is sent successfully.
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+ @retval EFI_DEVICE_ERROR Error occured in sending SMI IPI.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2SendSmiAllExcludingSelf (
+ IN SMM_CPU_SYNC2_PROTOCOL *This
+ )
+{
+ SendSmiIpiAllExcludingSelf();
+ return EFI_SUCCESS;
+}
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
new file mode 100755
index 0000000..703330a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
@@ -0,0 +1,1530 @@
+/** @file
+ Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+
+//
+// SMM CPU Private Data structure that contains SMM Configuration Protocol
+// along its supporting fields.
+//
+SMM_CPU_PRIVATE_DATA mSmmCpuPrivateData = {
+ SMM_CPU_PRIVATE_DATA_SIGNATURE, // Signature
+ NULL, // SmmCpuHandle
+ { 0 }, // ProcessorInfo array
+ { SmmCpuNone }, // Operation array
+ { 0 }, // CpuSaveStateSize array
+ { NULL }, // CpuSaveState array
+ { 0 }, // TstateMsr array
+ { 0 }, // SmmSyncFeature array
+ { 0 }, // SmmReservedSmramRegion
+ {
+ SmmStartupThisAp, // SmmCoreEntryContext.SmmStartupThisAp
+ 0, // SmmCoreEntryContext.CurrentlyExecutingCpu
+ 0, // SmmCoreEntryContext.NumberOfCpus
+ mSmmCpuPrivateData.CpuSaveStateSize, // SmmCoreEntryContext.CpuSaveStateSize
+ mSmmCpuPrivateData.CpuSaveState // SmmCoreEntryContext.CpuSaveStateSize
+ },
+ NULL, // SmmCoreEntry
+ {
+ mSmmCpuPrivateData.SmmReservedSmramRegion, // SmmConfiguration.SmramReservedRegions
+ RegisterSmmEntry // SmmConfiguration.RegisterSmmEntry
+ },
+};
+
+CPU_HOT_PLUG_DATA mCpuHotPlugData = {
+ { 0 }, // SmBases array
+ { 0 }, // APIC ID array
+ 0, // SmrrBase
+ 0 // SmrrSize
+};
+
+//
+// Global pointer used to access mSmmCpuPrivateData from outside and inside SMM
+//
+SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate = &mSmmCpuPrivateData;
+
+//
+// SMM Reloc variables
+//
+volatile BOOLEAN mRebased[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+volatile BOOLEAN mIsBsp;
+
+///
+/// Handle for the SMM CPU Protocol
+///
+EFI_HANDLE mSmmCpuHandle = NULL;
+
+///
+/// SMM CPU Protocol instance
+///
+EFI_SMM_CPU_PROTOCOL mSmmCpu = {
+ SmmReadSaveState,
+ SmmWriteSaveState
+};
+
+EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[EXCEPTION_VECTOR_NUMBER];
+
+///
+/// SMM CPU Sync Protocol instance
+///
+SMM_CPU_SYNC_PROTOCOL mSmmCpuSync = {
+ SmmCpuSyncCheckApArrival,
+ SmmCpuSyncSetMode,
+ SmmCpuSyncGetMode
+};
+
+///
+/// SMM CPU Sync2 Protocol instance
+///
+SMM_CPU_SYNC2_PROTOCOL mSmmCpuSync2 = {
+ SmmCpuSync2CheckApArrival,
+ SmmCpuSync2SetMode,
+ SmmCpuSync2GetMode,
+ SmmCpuSync2CheckCpuState,
+ SmmCpuSync2ChangeSmmEnabling,
+ SmmCpuSync2SendSmi,
+ SmmCpuSync2SendSmiAllExcludingSelf
+};
+
+///
+/// SMM CPU Save State Protocol instance
+///
+EFI_SMM_CPU_SAVE_STATE_PROTOCOL mSmmCpuSaveState = {
+ (EFI_SMM_CPU_STATE **)mSmmCpuPrivateData.CpuSaveState
+};
+
+//
+// SMM stack information
+//
+UINTN mSmmStackArrayBase;
+UINTN mSmmStackArrayEnd;
+UINTN mSmmStackSize;
+
+//
+// Pointer to structure used during S3 Resume
+//
+SMM_S3_RESUME_STATE *mSmmS3ResumeState = NULL;
+
+UINTN mMaxNumberOfCpus = 1;
+UINTN mNumberOfCpus = 1;
+
+///
+/// Macro used to simplfy the lookup table entries of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
+///
+#define SMM_CPU_OFFSET(Field) OFFSET_OF (EFI_SMM_CPU_STATE, Field)
+
+///
+/// Macro used to simplfy the lookup table entries of type CPU_SMM_SAVE_STATE_REGISTER_RANGE
+///
+#define SMM_REGISTER_RANGE(Start, End) { Start, End, End - Start + 1 }
+
+///
+/// Table used by GetRegisterIndex() to convert an EFI_SMM_SAVE_STATE_REGISTER
+/// value to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
+///
+CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE mSmmCpuRegisterRanges[] = {
+ SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_GDTBASE, EFI_SMM_SAVE_STATE_REGISTER_LDTINFO),
+ SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_ES, EFI_SMM_SAVE_STATE_REGISTER_RIP),
+ SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_RFLAGS, EFI_SMM_SAVE_STATE_REGISTER_CR4),
+ { (EFI_SMM_SAVE_STATE_REGISTER)0, (EFI_SMM_SAVE_STATE_REGISTER)0, 0 }
+};
+
+///
+/// Lookup table used to retrieve the widths and offsets associated with each
+/// supported EFI_SMM_SAVE_STATE_REGISTER value
+///
+CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY mSmmCpuWidthOffset[] = {
+ {0, 0, 0, 0, 0, FALSE}, // Reserved
+
+ //
+ // Internally defined CPU Save State Registers. Not defined in PI SMM CPU Protocol.
+ //
+ {4, 4, SMM_CPU_OFFSET (x86.SMMRevId) , SMM_CPU_OFFSET (x64.SMMRevId) , 0 , FALSE}, // SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX = 1
+ {4, 4, SMM_CPU_OFFSET (x86.IOMisc) , SMM_CPU_OFFSET (x64.IOMisc) , 0 , FALSE}, // SMM_SAVE_STATE_REGISTER_IOMISC_INDEX = 2
+ {4, 8, SMM_CPU_OFFSET (x86.IOMemAddr) , SMM_CPU_OFFSET (x64.IOMemAddr) , SMM_CPU_OFFSET (x64.IOMemAddr) + 4, FALSE}, // SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX = 3
+
+ //
+ // CPU Save State registers defined in PI SMM CPU Protocol.
+ //
+ {0, 8, 0 , SMM_CPU_OFFSET (x64.GdtBaseLoDword) , SMM_CPU_OFFSET (x64.GdtBaseHiDword), FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_GDTBASE = 4
+ {0, 8, 0 , SMM_CPU_OFFSET (x64.IdtBaseLoDword) , SMM_CPU_OFFSET (x64.IdtBaseHiDword), FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_IDTBASE = 5
+ {0, 8, 0 , SMM_CPU_OFFSET (x64.LdtBaseLoDword) , SMM_CPU_OFFSET (x64.LdtBaseHiDword), FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTBASE = 6
+ {0, 4, 0 , SMM_CPU_OFFSET (x64.GdtLimit) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT = 7
+ {0, 4, 0 , SMM_CPU_OFFSET (x64.IdtLimit) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT = 8
+ {0, 4, 0 , SMM_CPU_OFFSET (x64.LdtLimit) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT = 9
+ {0, 4, 0 , SMM_CPU_OFFSET (x64.LdtInfo) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTINFO = 10
+
+ {4, 4, SMM_CPU_OFFSET (x86._ES) , SMM_CPU_OFFSET (x64._ES) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_ES = 20
+ {4, 4, SMM_CPU_OFFSET (x86._CS) , SMM_CPU_OFFSET (x64._CS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CS = 21
+ {4, 4, SMM_CPU_OFFSET (x86._SS) , SMM_CPU_OFFSET (x64._SS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_SS = 22
+ {4, 4, SMM_CPU_OFFSET (x86._DS) , SMM_CPU_OFFSET (x64._DS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_DS = 23
+ {4, 4, SMM_CPU_OFFSET (x86._FS) , SMM_CPU_OFFSET (x64._FS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_FS = 24
+ {4, 4, SMM_CPU_OFFSET (x86._GS) , SMM_CPU_OFFSET (x64._GS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_GS = 25
+ {0, 4, 0 , SMM_CPU_OFFSET (x64._LDTR) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL = 26
+ {4, 4, SMM_CPU_OFFSET (x86._TR) , SMM_CPU_OFFSET (x64._TR) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_TR_SEL = 27
+ {4, 8, SMM_CPU_OFFSET (x86._DR7) , SMM_CPU_OFFSET (x64._DR7) , SMM_CPU_OFFSET (x64._DR7) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_DR7 = 28
+ {4, 8, SMM_CPU_OFFSET (x86._DR6) , SMM_CPU_OFFSET (x64._DR6) , SMM_CPU_OFFSET (x64._DR6) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_DR6 = 29
+ {0, 8, 0 , SMM_CPU_OFFSET (x64._R8) , SMM_CPU_OFFSET (x64._R8) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R8 = 30
+ {0, 8, 0 , SMM_CPU_OFFSET (x64._R9) , SMM_CPU_OFFSET (x64._R9) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R9 = 31
+ {0, 8, 0 , SMM_CPU_OFFSET (x64._R10) , SMM_CPU_OFFSET (x64._R10) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R10 = 32
+ {0, 8, 0 , SMM_CPU_OFFSET (x64._R11) , SMM_CPU_OFFSET (x64._R11) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R11 = 33
+ {0, 8, 0 , SMM_CPU_OFFSET (x64._R12) , SMM_CPU_OFFSET (x64._R12) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R12 = 34
+ {0, 8, 0 , SMM_CPU_OFFSET (x64._R13) , SMM_CPU_OFFSET (x64._R13) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R13 = 35
+ {0, 8, 0 , SMM_CPU_OFFSET (x64._R14) , SMM_CPU_OFFSET (x64._R14) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R14 = 36
+ {0, 8, 0 , SMM_CPU_OFFSET (x64._R15) , SMM_CPU_OFFSET (x64._R15) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R15 = 37
+ {4, 8, SMM_CPU_OFFSET (x86._EAX) , SMM_CPU_OFFSET (x64._RAX) , SMM_CPU_OFFSET (x64._RAX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RAX = 38
+ {4, 8, SMM_CPU_OFFSET (x86._EBX) , SMM_CPU_OFFSET (x64._RBX) , SMM_CPU_OFFSET (x64._RBX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RBX = 39
+ {4, 8, SMM_CPU_OFFSET (x86._ECX) , SMM_CPU_OFFSET (x64._RCX) , SMM_CPU_OFFSET (x64._RCX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RCX = 40
+ {4, 8, SMM_CPU_OFFSET (x86._EDX) , SMM_CPU_OFFSET (x64._RDX) , SMM_CPU_OFFSET (x64._RDX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RDX = 41
+ {4, 8, SMM_CPU_OFFSET (x86._ESP) , SMM_CPU_OFFSET (x64._RSP) , SMM_CPU_OFFSET (x64._RSP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RSP = 42
+ {4, 8, SMM_CPU_OFFSET (x86._EBP) , SMM_CPU_OFFSET (x64._RBP) , SMM_CPU_OFFSET (x64._RBP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RBP = 43
+ {4, 8, SMM_CPU_OFFSET (x86._ESI) , SMM_CPU_OFFSET (x64._RSI) , SMM_CPU_OFFSET (x64._RSI) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RSI = 44
+ {4, 8, SMM_CPU_OFFSET (x86._EDI) , SMM_CPU_OFFSET (x64._RDI) , SMM_CPU_OFFSET (x64._RDI) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RDI = 45
+ {4, 8, SMM_CPU_OFFSET (x86._EIP) , SMM_CPU_OFFSET (x64._RIP) , SMM_CPU_OFFSET (x64._RIP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RIP = 46
+
+ {4, 8, SMM_CPU_OFFSET (x86._EFLAGS) , SMM_CPU_OFFSET (x64._RFLAGS) , SMM_CPU_OFFSET (x64._RFLAGS) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RFLAGS = 51
+ {4, 8, SMM_CPU_OFFSET (x86._CR0) , SMM_CPU_OFFSET (x64._CR0) , SMM_CPU_OFFSET (x64._CR0) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CR0 = 52
+ {4, 8, SMM_CPU_OFFSET (x86._CR3) , SMM_CPU_OFFSET (x64._CR3) , SMM_CPU_OFFSET (x64._CR3) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CR3 = 53
+ {0, 4, 0 , SMM_CPU_OFFSET (x64._CR4) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CR4 = 54
+};
+
+///
+/// Lookup table for the IOMisc width information
+///
+CONST CPU_SMM_SAVE_STATE_IO_WIDTH mSmmCpuIoWidth[] = {
+ { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 0
+ { 1, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // SMM_IO_LENGTH_BYTE = 1
+ { 2, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16 }, // SMM_IO_LENGTH_WORD = 2
+ { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 3
+ { 4, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32 }, // SMM_IO_LENGTH_DWORD = 4
+ { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 5
+ { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 6
+ { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 } // Undefined = 7
+};
+
+///
+/// Lookup table for the IOMisc type information
+///
+CONST EFI_SMM_SAVE_STATE_IO_TYPE mSmmCpuIoType[] = {
+ EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT, // SMM_IO_TYPE_OUT_DX = 0
+ EFI_SMM_SAVE_STATE_IO_TYPE_INPUT, // SMM_IO_TYPE_IN_DX = 1
+ EFI_SMM_SAVE_STATE_IO_TYPE_STRING, // SMM_IO_TYPE_OUTS = 2
+ EFI_SMM_SAVE_STATE_IO_TYPE_STRING, // SMM_IO_TYPE_INS = 3
+ (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 4
+ (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 5
+ EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_OUTS = 6
+ EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_INS = 7
+ EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT, // SMM_IO_TYPE_OUT_IMMEDIATE = 8
+ EFI_SMM_SAVE_STATE_IO_TYPE_INPUT, // SMM_IO_TYPE_OUT_IMMEDIATE = 9
+ (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 10
+ (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 11
+ (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 12
+ (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 13
+ (EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 14
+ (EFI_SMM_SAVE_STATE_IO_TYPE)0 // Undefined = 15
+};
+
+/**
+ Read information from the CPU save state.
+
+ @param Register Specifies the CPU register to read form the save state.
+
+ @retval 0 Register is not valid
+ @retval >0 Index into mSmmCpuWidthOffset[] associated with Register
+
+**/
+UINTN
+GetRegisterIndex (
+ IN EFI_SMM_SAVE_STATE_REGISTER Register
+ )
+{
+ UINTN Index;
+ UINTN Offset;
+
+ for (Index = 0, Offset = SMM_SAVE_STATE_REGISTER_MAX_INDEX; mSmmCpuRegisterRanges[Index].Length != 0; Index++) {
+ if (Register >= mSmmCpuRegisterRanges[Index].Start && Register <= mSmmCpuRegisterRanges[Index].End) {
+ return Register - mSmmCpuRegisterRanges[Index].Start + Offset;
+ }
+ Offset += mSmmCpuRegisterRanges[Index].Length;
+ }
+ return 0;
+}
+
+/**
+ Read a CPU Save State register on the target processor.
+
+ This function abstracts the differences that whether the CPU Save State register is in the IA32 Cpu Save State Map
+ or x64 Cpu Save State Map or a CPU Save State MSR.
+
+ This function supports reading a CPU Save State register in SMBase relocation handler.
+
+ @param[in] CpuIndex Specifies the zero-based index of the CPU save state.
+ @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.
+ @param[in] Width The number of bytes to read from the CPU save state.
+ @param[out] Buffer Upon return, this holds the CPU register value read from the save state.
+
+ @retval EFI_SUCCESS The register was read from Save State.
+ @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
+ @retval EFI_INVALID_PARAMTER This or Buffer is NULL.
+ @retval EFI_UNSUPPORTED The register has no corresponding MSR.
+
+**/
+EFI_STATUS
+ReadSaveStateRegister (
+ IN UINTN CpuIndex,
+ IN UINTN RegisterIndex,
+ IN UINTN Width,
+ OUT VOID *Buffer
+ )
+{
+ UINT32 SmmRevId;
+ EFI_SMM_CPU_STATE *CpuSaveState;
+
+ CpuSaveState = NULL;
+
+ //
+ // Get SMMRevId first.
+ //
+ CpuSaveState = gSmst->CpuSaveState[CpuIndex];
+ ASSERT (CpuSaveState != NULL);
+ SmmRevId = CpuSaveState->x86.SMMRevId;
+
+ if (RegisterIndex == SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX) {
+ *(UINT32 *)Buffer = SmmRevId;
+ return EFI_SUCCESS;
+ }
+
+ if (SmmRevId < SOCKET_LGA_775_SMM_MIN_REV_ID_x64) {
+ //
+ // If 32-bit mode width is zero, then the specified register can not be accessed
+ //
+ if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
+ //
+ if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Write return buffer
+ //
+ CopyMem(Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Width);
+ } else {
+ //
+ // If 64-bit mode width is zero, then the specified register can not be accessed
+ //
+ if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
+ //
+ if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Write lower 32-bits of return buffer
+ //
+ CopyMem(Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, MIN (4, Width));
+ if (Width >= 4) {
+ //
+ // Write upper 32-bits of return buffer
+ //
+ CopyMem((UINT8 *)Buffer + 4, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Write value to a CPU Save State register on the target processor.
+
+ This function abstracts the differences that whether the CPU Save State register is in the IA32 Cpu Save State Map
+ or x64 Cpu Save State Map or a CPU Save State MSR.
+
+ This function supports writing a CPU Save State register in SMBase relocation handler.
+
+ @param[in] CpuIndex Specifies the zero-based index of the CPU save state.
+ @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.
+ @param[in] Width The number of bytes to read from the CPU save state.
+ @param[in] Buffer Upon entry, this holds the new CPU register value.
+
+ @retval EFI_SUCCESS The register was written to Save State.
+ @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
+ @retval EFI_INVALID_PARAMTER ProcessorIndex or Width is not correct.
+ @retval EFI_UNSUPPORTED The register is read-only, cannot be written, or has no corresponding MSR.
+
+**/
+EFI_STATUS
+WriteSaveStateRegister (
+ IN UINTN CpuIndex,
+ IN UINTN RegisterIndex,
+ IN UINTN Width,
+ IN CONST VOID *Buffer
+ )
+{
+ UINT32 SmmRevId;
+ EFI_SMM_CPU_STATE *CpuSaveState;
+
+ CpuSaveState = NULL;
+
+ //
+ // Do not write non-writeable SaveState.
+ //
+ if (!mSmmCpuWidthOffset[RegisterIndex].Writeable) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get SMMRevId first.
+ //
+ CpuSaveState = gSmst->CpuSaveState[CpuIndex];
+ ASSERT (CpuSaveState != NULL);
+ SmmRevId = CpuSaveState->x86.SMMRevId;
+
+ //
+ // Check CPU mode
+ //
+ if (SmmRevId < SOCKET_LGA_775_SMM_MIN_REV_ID_x64) {
+ //
+ // If 32-bit mode width is zero, then the specified register can not be accessed
+ //
+ if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
+ //
+ if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Write SMM State register
+ //
+ CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Buffer, Width);
+ } else {
+ //
+ // If 64-bit mode width is zero, then the specified register can not be accessed
+ //
+ if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
+ //
+ if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Write lower 32-bits of SMM State register
+ //
+ CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4, Width));
+ if (Width >= 4) {
+ //
+ // Write upper 32-bits of SMM State register
+ //
+ CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width - 4);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Read information from the CPU save state.
+
+ @param This EFI_SMM_CPU_PROTOCOL instance
+ @param Width The number of bytes to read from the CPU save state.
+ @param Register Specifies the CPU register to read form the save state.
+ @param CpuIndex Specifies the zero-based index of the CPU save state.
+ @param Buffer Upon return, this holds the CPU register value read from the save state.
+
+ @retval EFI_SUCCESS The register was read from Save State
+ @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
+ @retval EFI_INVALID_PARAMTER This or Buffer is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmReadSaveState (
+ IN CONST EFI_SMM_CPU_PROTOCOL *This,
+ IN UINTN Width,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN CpuIndex,
+ OUT VOID *Buffer
+ )
+{
+ UINT32 SmmRevId;
+ SOCKET_LGA_775_SMM_CPU_STATE_IOMISC IoMisc;
+ EFI_SMM_SAVE_STATE_IO_INFO *IoInfo;
+ UINTN RegisterIndex;
+ VOID *IoMemAddr;
+
+ //
+ // Retrieve pointer to the specified CPU's SMM Save State buffer
+ //
+ if ((CpuIndex >= gSmst->NumberOfCpus) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check for special EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID
+ //
+ if (Register == EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID) {
+ //
+ // The pseudo-register only supports the 64-bit size specified by Width.
+ //
+ if (Width != sizeof (UINT64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // If the processor is in SMM at the time the SMI occurred,
+ // the pseudo register value for EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID is returned in Buffer.
+ // Otherwise, EFI_NOT_FOUND is returned.
+ //
+ if (mSmmMpSyncData->CpuData[CpuIndex].Present) {
+ *(UINT64 *)Buffer = gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (!mSmmMpSyncData->CpuData[CpuIndex].Present) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA
+ //
+ if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
+ //
+ // Only byte access is supported for this register
+ //
+ if (Width != 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ReadSaveStateRegister (CpuIndex, SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX, sizeof (SmmRevId), &SmmRevId);
+
+ if ((SmmRevId < SOCKET_LGA_775_SMM_MIN_REV_ID_x64)) {
+ *(UINT8 *)Buffer = EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;
+ } else {
+ *(UINT8 *)Buffer = EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check for special EFI_SMM_SAVE_STATE_REGISTER_IO
+ //
+ if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
+ ReadSaveStateRegister (CpuIndex, SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX, sizeof (SmmRevId), &SmmRevId);
+
+ //
+ // See if the CPU supports the IOMisc register in the save state
+ //
+ if (SmmRevId < SOCKET_LGA_775_SMM_MIN_REV_ID_IOMISC) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the IOMisc register value
+ //
+ ReadSaveStateRegister (CpuIndex, SMM_SAVE_STATE_REGISTER_IOMISC_INDEX, sizeof (IoMisc.Uint32), &IoMisc.Uint32);
+
+ //
+ // Check for the SMI_FLAG in IOMisc
+ //
+ if (IoMisc.Bits.SmiFlag == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Compute index for the I/O Length and I/O Type lookup tables
+ //
+ if (mSmmCpuIoWidth[IoMisc.Bits.Length].Width == 0 || mSmmCpuIoType[IoMisc.Bits.Type] == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Zero the IoInfo structure that will be returned in Buffer
+ //
+ IoInfo = (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer;
+ ZeroMem (IoInfo, sizeof (EFI_SMM_SAVE_STATE_IO_INFO));
+
+ //
+ // Use lookup tables to help fill in all the fields of the IoInfo structure
+ //
+ IoInfo->IoPort = (UINT16)IoMisc.Bits.Port;
+ IoInfo->IoWidth = mSmmCpuIoWidth[IoMisc.Bits.Length].IoWidth;
+ IoInfo->IoType = mSmmCpuIoType[IoMisc.Bits.Type];
+ if (IoInfo->IoType == EFI_SMM_SAVE_STATE_IO_TYPE_INPUT || IoInfo->IoType == EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT) {
+ ReadSaveStateRegister (CpuIndex, GetRegisterIndex (EFI_SMM_SAVE_STATE_REGISTER_RAX), mSmmCpuIoWidth[IoMisc.Bits.Length].Width, &IoInfo->IoData);
+ } else {
+ ReadSaveStateRegister (CpuIndex, SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX, sizeof (IoMemAddr), &IoMemAddr);
+ CopyMem (&IoInfo->IoData, IoMemAddr, mSmmCpuIoWidth[IoMisc.Bits.Length].Width);
+ }
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Convert Register to a register lookup table index
+ //
+ RegisterIndex = GetRegisterIndex (Register);
+ if (RegisterIndex == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ return ReadSaveStateRegister (CpuIndex, RegisterIndex, Width, Buffer);
+}
+
+/**
+ Write data to the CPU save state.
+
+ @param This EFI_SMM_CPU_PROTOCOL instance
+ @param Width The number of bytes to read from the CPU save state.
+ @param Register Specifies the CPU register to write to the save state.
+ @param CpuIndex Specifies the zero-based index of the CPU save state
+ @param Buffer Upon entry, this holds the new CPU register value.
+
+ @retval EFI_SUCCESS The register was written from Save State
+ @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
+ @retval EFI_INVALID_PARAMTER ProcessorIndex or Width is not correct
+
+**/
+EFI_STATUS
+EFIAPI
+SmmWriteSaveState (
+ IN CONST EFI_SMM_CPU_PROTOCOL *This,
+ IN UINTN Width,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN CpuIndex,
+ IN CONST VOID *Buffer
+ )
+{
+ UINTN RegisterIndex;
+
+ //
+ // Retrieve pointer to the specified CPU's SMM Save State buffer
+ //
+ if ((CpuIndex >= gSmst->NumberOfCpus) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Writes to EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID are ignored
+ //
+ if (Register == EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID) {
+ return EFI_SUCCESS;
+ }
+
+ if (!mSmmMpSyncData->CpuData[CpuIndex].Present) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ignored
+ //
+ if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Writes to EFI_SMM_SAVE_STATE_REGISTER_IO are not supported
+ //
+ if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Convert Register to a register lookup table index
+ //
+ RegisterIndex = GetRegisterIndex (Register);
+ if (RegisterIndex == 0) {
+ //
+ // If Register is not valie, then return EFI_NOT_FOUND
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ return WriteSaveStateRegister (CpuIndex, RegisterIndex, Width, Buffer);
+}
+
+
+/**
+ C function for SMI handler. To change all processor's SMMBase Register.
+
+**/
+VOID
+EFIAPI
+SmmInitHandler (
+ VOID
+ )
+{
+ UINT32 ApicId;
+ UINTN Index;
+ IA32_DESCRIPTOR X64Idtr;
+ IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
+
+ //
+ // Set up X64 IDT table
+ //
+ ZeroMem (IdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * EXCEPTION_VECTOR_NUMBER);
+ X64Idtr.Base = (UINTN) IdtEntryTable;
+ X64Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * EXCEPTION_VECTOR_NUMBER - 1);
+ AsmWriteIdtr ((IA32_DESCRIPTOR *) &X64Idtr);
+
+
+ ApicId = GetApicId ();
+
+ ASSERT (mNumberOfCpus <= FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber));
+
+ for (Index = 0; Index < mNumberOfCpus; Index++) {
+ if (ApicId == (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {
+ SmmInitiFeatures (Index, mCpuHotPlugData.SmrrBase, mCpuHotPlugData.SmrrSize, (UINT32)mCpuHotPlugData.SmBase[Index], mIsBsp);
+
+ if (!mIsBsp) {
+ SemaphoreHook (Index);
+ } else {
+ //
+ // BSP rebase is already done above.
+ // Initialize private data during S3 resume
+ //
+ InitializeMpSyncData ();
+ }
+ PlatformSmmExitProcessing ();
+ return;
+ }
+ }
+ ASSERT (FALSE);
+}
+
+/**
+ Relocate SmmBases for each processor.
+
+ Execute on first boot and all S3 resumes
+
+**/
+VOID
+EFIAPI
+SmmRelocateBases (
+ VOID
+ )
+{
+ UINT8 BakBuf[BACK_BUF_SIZE];
+ EFI_SMM_CPU_STATE BakBuf2;
+ EFI_SMM_CPU_STATE *CpuStatePtr;
+ UINT8 *U8Ptr;
+ UINT32 ApicId;
+ UINTN Index;
+
+ //
+ // Make sure the reserved size is large enough for procedure SmmInitTemplate.
+ //
+ ASSERT (sizeof (BakBuf) >= gcSmmInitSize);
+
+ //
+ // Patch ASM code template with current CR0, CR3, and CR4 values
+ //
+ gSmmCr0 = (UINT32)AsmReadCr0 ();
+ gSmmCr3 = (UINT32)AsmReadCr3 ();
+ gSmmCr4 = (UINT32)AsmReadCr4 ();
+
+ U8Ptr = (UINT8*)(UINTN)(SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET);
+ CpuStatePtr = (EFI_SMM_CPU_STATE *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_CPU_STATE_OFFSET);
+
+ //
+ // Backup original contents @ 0x38000
+ //
+ CopyMem (BakBuf, U8Ptr, sizeof (BakBuf));
+ CopyMem (&BakBuf2, CpuStatePtr, sizeof (BakBuf2));
+
+ //
+ // Load image for relocation
+ //
+ CopyMem (U8Ptr, gcSmmInitTemplate, gcSmmInitSize);
+
+ //
+ // Retrieve the local APIC ID of current processor
+ //
+ ApicId = GetApicId ();
+
+ //
+ // Relocate SM bases for all APs
+ // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overriden by gcSmmInitTemplate
+ //
+ mIsBsp = FALSE;
+ for (Index = 0; Index < mNumberOfCpus; Index++) {
+ if (ApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {
+ mRebased[Index] = FALSE;
+ SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId);
+
+ //
+ // Wait for this AP to finish its 1st SMI
+ //
+ while (!mRebased[Index]);
+ }
+ }
+
+ //
+ // Relocate BSP's SM base
+ //
+ mIsBsp = TRUE;
+ SendSmiIpi (ApicId);
+
+ //
+ // Restore contents @ 0x38000
+ //
+ CopyMem (CpuStatePtr, &BakBuf2, sizeof (BakBuf2));
+ CopyMem (U8Ptr, BakBuf, sizeof (BakBuf));
+}
+
+/**
+ Perform SMM initialization for all processors in the S3 boot path.
+
+ For a native platform, MP initialization in the S3 boot path is also performed in this function.
+**/
+VOID
+SmmRestoreCpu (
+ VOID
+ )
+{
+ SMM_S3_RESUME_STATE *SmmS3ResumeState;
+ IA32_DESCRIPTOR Ia32Idtr;
+ IA32_DESCRIPTOR X64Idtr;
+ IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
+
+ DEBUG ((EFI_D_INFO, "SmmRestoreCpu()\n"));
+
+ //
+ // See if there is enough context to resume PEI Phase
+ //
+ if (mSmmS3ResumeState == NULL) {
+ DEBUG ((EFI_D_ERROR, "No context to return to PEI Phase\n"));
+ CpuDeadLoop ();
+ }
+
+ SmmS3ResumeState = mSmmS3ResumeState;
+ ASSERT (SmmS3ResumeState != NULL);
+
+ if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {
+ //
+ // Save the IA32 IDT Descriptor
+ //
+ AsmReadIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);
+
+ //
+ // Setup X64 IDT table
+ //
+ ZeroMem (IdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32);
+ X64Idtr.Base = (UINTN) IdtEntryTable;
+ X64Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32 - 1);
+ AsmWriteIdtr ((IA32_DESCRIPTOR *) &X64Idtr);
+
+
+ }
+
+ //
+ // Do below CPU things for native platform only
+ //
+ if (!FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
+ //
+ // First time microcode load and restore MTRRs
+ //
+ EarlyInitializeCpu ();
+ }
+
+ //
+ // Restore SMBASE for BSP and all APs
+ //
+ SmmRelocateBases ();
+
+ //
+ // Do below CPU things for native platform only
+ //
+ if (!FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
+ //
+ // Restore MSRs for BSP and all APs
+ //
+ InitializeCpu ();
+ }
+
+ if (mSmmCodeAccessCheckEnable || FeaturePcdGet (PcdCpuSmmFeatureControlMsrLock)) {
+ //
+ // Set a flag to restore SMM configuration in S3 path.
+ //
+ mRestoreSmmConfigurationInS3 = TRUE;
+ }
+
+ DEBUG (( EFI_D_INFO, "SMM S3 Return CS = %x\n", SmmS3ResumeState->ReturnCs));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return Entry Point = %x\n", SmmS3ResumeState->ReturnEntryPoint));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return Context1 = %x\n", SmmS3ResumeState->ReturnContext1));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return Context2 = %x\n", SmmS3ResumeState->ReturnContext2));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return Stack Pointer = %x\n", SmmS3ResumeState->ReturnStackPointer));
+
+ //
+ // If SMM is in 32-bit mode, then use SwitchStack() to resume PEI Phase
+ //
+ if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {
+ DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));
+
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->ReturnEntryPoint,
+ (VOID *)(UINTN)SmmS3ResumeState->ReturnContext1,
+ (VOID *)(UINTN)SmmS3ResumeState->ReturnContext2,
+ (VOID *)(UINTN)SmmS3ResumeState->ReturnStackPointer
+ );
+ }
+
+ //
+ // If SMM is in 64-bit mode, then use AsmDisablePaging64() to resume PEI Phase
+ //
+ if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {
+ DEBUG ((EFI_D_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));
+ //
+ // Disable interrupt of Debug timer, since new IDT table is for IA32 and will not work in long mode.
+ //
+ SaveAndSetDebugTimerInterrupt (FALSE);
+ //
+ // Restore IA32 IDT table
+ //
+ AsmWriteIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);
+ AsmDisablePaging64 (
+ SmmS3ResumeState->ReturnCs,
+ (UINT32)SmmS3ResumeState->ReturnEntryPoint,
+ (UINT32)SmmS3ResumeState->ReturnContext1,
+ (UINT32)SmmS3ResumeState->ReturnContext2,
+ (UINT32)SmmS3ResumeState->ReturnStackPointer
+ );
+ }
+
+ //
+ // Can not resume PEI Phase
+ //
+ DEBUG ((EFI_D_ERROR, "No context to return to PEI Phase\n"));
+ CpuDeadLoop ();
+}
+
+/**
+ Smm Ready To Lock event notification handler.
+
+ The CPU S3 data is copied to SMRAM for security. SMM Code Access Check feature is enabled if available.
+
+ @param[in] Protocol Points to the protocol's unique identifier.
+ @param[in] Interface Points to the interface instance.
+ @param[in] Handle The handle on which the interface was installed.
+
+ @retval EFI_SUCCESS Notification handler runs successfully.
+ **/
+EFI_STATUS
+EFIAPI
+SmmReadyToLockEventNotify (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ UINTN Index;
+ CPU_REGISTER_TABLE *SourceRegisterTableList;
+ CPU_REGISTER_TABLE *DestinationRegisterTableList;
+ ACPI_CPU_DATA *AcpiCpuData;
+ IA32_DESCRIPTOR *Gdtr;
+ IA32_DESCRIPTOR *Idtr;
+
+ //
+ // For a native platform, copy the CPU S3 data into SMRAM for security.
+ //
+ if (!FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
+ //
+ // Get CPU S3 data address
+ //
+ AcpiCpuData = (ACPI_CPU_DATA *)(UINTN)PcdGet64 (PcdCpuS3DataAddress);
+
+ //
+ // Copy CPU S3 data into SMRAM for use on CPU S3 Resume.
+ //
+ CopyMem (&mAcpiCpuData, AcpiCpuData, sizeof (mAcpiCpuData));
+
+ mAcpiCpuData.MtrrTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (MTRR_SETTINGS));
+ ASSERT (mAcpiCpuData.MtrrTable != 0);
+
+ CopyMem ((VOID *)(UINTN)mAcpiCpuData.MtrrTable, (VOID *)(UINTN)AcpiCpuData->MtrrTable, sizeof (MTRR_SETTINGS));
+
+ mAcpiCpuData.GdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (IA32_DESCRIPTOR));
+ ASSERT (mAcpiCpuData.GdtrProfile != 0);
+
+ CopyMem ((VOID *)(UINTN)mAcpiCpuData.GdtrProfile, (VOID *)(UINTN)AcpiCpuData->GdtrProfile, sizeof (IA32_DESCRIPTOR));
+
+ mAcpiCpuData.IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (IA32_DESCRIPTOR));
+ ASSERT (mAcpiCpuData.IdtrProfile != 0);
+
+ CopyMem ((VOID *)(UINTN)mAcpiCpuData.IdtrProfile, (VOID *)(UINTN)AcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));
+
+ mAcpiCpuData.RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
+ ASSERT (mAcpiCpuData.RegisterTable != 0);
+
+ CopyMem ((CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable, (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable, mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
+
+ SourceRegisterTableList = (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable;
+ DestinationRegisterTableList = (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable;
+ for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
+ DestinationRegisterTableList[Index].RegisterTableEntry = AllocatePool (DestinationRegisterTableList[Index].AllocatedSize);
+ ASSERT (DestinationRegisterTableList[Index].RegisterTableEntry != NULL);
+
+ CopyMem (DestinationRegisterTableList[Index].RegisterTableEntry, SourceRegisterTableList[Index].RegisterTableEntry, DestinationRegisterTableList[Index].AllocatedSize);
+ }
+
+ //
+ // Copy AP's GDT, IDT and Machine Check handler into SMRAM.
+ //
+ Gdtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.GdtrProfile;
+ Idtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.IdtrProfile;
+
+ mGdtForAp = AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) + mAcpiCpuData.ApMachineCheckHandlerSize);
+ ASSERT (mGdtForAp != NULL);
+ mIdtForAp = (VOID *) ((UINTN)mGdtForAp + (Gdtr->Limit + 1));
+ mMachineCheckHandlerForAp = (VOID *) ((UINTN)mIdtForAp + (Idtr->Limit + 1));
+
+ CopyMem (mGdtForAp, (VOID *)Gdtr->Base, Gdtr->Limit + 1);
+ CopyMem (mIdtForAp, (VOID *)Idtr->Base, Idtr->Limit + 1);
+ CopyMem (mMachineCheckHandlerForAp, (VOID *)(UINTN)mAcpiCpuData.ApMachineCheckHandlerBase, mAcpiCpuData.ApMachineCheckHandlerSize);
+ }
+
+ //
+ // Configure SMM Code Access Check feature if available.
+ //
+ if (PcdGetBool (PcdCpuSmmCodeAccessCheckEnable) ||
+ FeaturePcdGet (PcdCpuSmmFeatureControlMsrLock)) {
+ //
+ // Save the PcdCpuSmmCodeAccessCheckEnable value into a local variable for s3 boot path.
+ //
+ mSmmCodeAccessCheckEnable = PcdGetBool (PcdCpuSmmCodeAccessCheckEnable);
+ ConfigSmmCodeAccessCheck ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The module Entry Point of the CPU SMM driver.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+PiCpuSmmEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_MP_SERVICES_PROTOCOL *MpServices;
+ UINTN NumberOfEnabledProcessors;
+ UINTN Index;
+ VOID *Buffer;
+ UINTN TileSize;
+ VOID *GuidHob;
+ EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
+ SMM_S3_RESUME_STATE *SmmS3ResumeState;
+ UINT8 *Stacks;
+ VOID *Registration;
+
+ //
+ // Initialize Debug Agent to support source level debug in SMM code
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_SMM, NULL, NULL);
+
+ //
+ // Report thhe start of CPU SMM initialization.
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_INIT
+ );
+
+ //
+ // Fix segment address of the long-mode-switch jmp
+ //
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ gSmmJmpAddr.Segment = 8;
+ }
+
+ //
+ // Find out SMRR Base and Size
+ //
+ FindSmramInfo (&mCpuHotPlugData.SmrrBase, &mCpuHotPlugData.SmrrSize);
+
+ //
+ // Get MP Services Protocol
+ //
+ Status = SystemTable->BootServices->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Use MP Services Protocol to retrieve the number of processors and number of enabled processors
+ //
+ Status = MpServices->GetNumberOfProcessors (MpServices, &mNumberOfCpus, &NumberOfEnabledProcessors);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (mNumberOfCpus <= FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber));
+
+ //
+ // If support CPU hot plug, PcdCpuSmmEnableBspElection should be set to TRUE.
+ // A constant BSP index makes no sense because it may be hot removed.
+ //
+ DEBUG_CODE (
+ if (FeaturePcdGet (PcdCpuHotPlugSupport)) {
+
+ ASSERT (FeaturePcdGet (PcdCpuSmmEnableBspElection));
+ }
+ );
+
+ //
+ // If support CPU hot plug, we need to allocate resources for possibly hot-added processors
+ //
+ if (FeaturePcdGet (PcdCpuHotPlugSupport)) {
+ mMaxNumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ } else {
+ mMaxNumberOfCpus = mNumberOfCpus;
+ }
+ gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus = mMaxNumberOfCpus;
+
+ //
+ // The CPU save state and code for the SMI entry point are tiled within an SMRAM
+ // allocated buffer. The miniumu size of this buffer for a uniprocessor system
+ // is 32 KB, because the entry point is SMBASE + 32KB, and CPU save state area
+ // just below SMBASE + 64KB. If more than one CPU is present in the platform,
+ // then the SMI entry point and the CPU save state areas can be tiles to minimize
+ // the total amount SMRAM required for all the CPUs. The tile size can be computed
+ // by adding the // CPU save state size, any extra CPU specific context, and
+ // the size of code that must be placed at the SMI entry point to transfer
+ // control to a C function in the native SMM execution mode. This size is
+ // rounded up to the nearest power of 2 to give the tile size for a each CPU.
+ // The total amount of memory required is the maximum number of CPUs that
+ // platform supports times the tile size. The picture below shows the tiling,
+ // where m is the number of tiles that fit in 32KB.
+ //
+ // +-----------------------------+ <-- 2^n offset from Base of allocated buffer
+ // | CPU m+1 Save State |
+ // +-----------------------------+
+ // | CPU m+1 Extra Data |
+ // +-----------------------------+
+ // | Padding |
+ // +-----------------------------+
+ // | CPU 2m SMI Entry |
+ // +#############################+ <-- Base of allocated buffer + 64 KB
+ // | CPU m-1 Save State |
+ // +-----------------------------+
+ // | CPU m-1 Extra Data |
+ // +-----------------------------+
+ // | Padding |
+ // +-----------------------------+
+ // | CPU 2m-1 SMI Entry |
+ // +=============================+ <-- 2^n offset from Base of allocated buffer
+ // | . . . . . . . . . . . . |
+ // +=============================+ <-- 2^n offset from Base of allocated buffer
+ // | CPU 2 Save State |
+ // +-----------------------------+
+ // | CPU 2 Extra Data |
+ // +-----------------------------+
+ // | Padding |
+ // +-----------------------------+
+ // | CPU m+1 SMI Entry |
+ // +=============================+ <-- Base of allocated buffer + 32 KB
+ // | CPU 1 Save State |
+ // +-----------------------------+
+ // | CPU 1 Extra Data |
+ // +-----------------------------+
+ // | Padding |
+ // +-----------------------------+
+ // | CPU m SMI Entry |
+ // +#############################+ <-- Base of allocated buffer + 32 KB == CPU 0 SMBASE + 64 KB
+ // | CPU 0 Save State |
+ // +-----------------------------+
+ // | CPU 0 Extra Data |
+ // +-----------------------------+
+ // | Padding |
+ // +-----------------------------+
+ // | CPU m-1 SMI Entry |
+ // +=============================+ <-- 2^n offset from Base of allocated buffer
+ // | . . . . . . . . . . . . |
+ // +=============================+ <-- 2^n offset from Base of allocated buffer
+ // | Padding |
+ // +-----------------------------+
+ // | CPU 1 SMI Entry |
+ // +=============================+ <-- 2^n offset from Base of allocated buffer
+ // | Padding |
+ // +-----------------------------+
+ // | CPU 0 SMI Entry |
+ // +#############################+ <-- Base of allocated buffer == CPU 0 SMBASE + 32 KB
+ //
+
+ //
+ // Compute tile size of buffer required to hold CPU save state, any extra CPU
+ // specific context, and the SMI entry point. This size of rounded up to
+ // nearest power of 2.
+ //
+ TileSize = 2 * GetPowerOfTwo32 (sizeof (EFI_SMM_CPU_STATE) + sizeof (PROCESSOR_SMM_DESCRIPTOR) + gcSmiHandlerSize - 1);
+
+ //
+ // Allocate buffer for all of the tiles.
+ // For 486/Pentium, the SMBASE (and hence the buffer) must be aligned on a 32KB boundary
+ //
+ Buffer = AllocatePages (EFI_SIZE_TO_PAGES (SIZE_64KB + TileSize * (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus - 1)));
+ Buffer = (VOID *)(((UINTN)Buffer & 0xFFFF8000) + SIZE_32KB);
+ ASSERT (Buffer != NULL);
+
+ //
+ // Retrieve APIC ID of each enabled processor from the MP Services protocol.
+ // Also compute the SMBASE address, CPU Save State address, and CPU Save state
+ // size for each CPU in the platform
+ //
+ for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
+ mCpuHotPlugData.SmBase[Index] = (UINTN)Buffer + Index * TileSize - SIZE_32KB;
+ gSmmCpuPrivate->CpuSaveStateSize[Index] = sizeof(EFI_SMM_CPU_STATE);
+ gSmmCpuPrivate->CpuSaveState[Index] = (VOID *)(mCpuHotPlugData.SmBase[Index] + SIZE_64KB - gSmmCpuPrivate->CpuSaveStateSize[Index]);
+ gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
+
+ if (Index < mNumberOfCpus) {
+ Status = MpServices->GetProcessorInfo (MpServices, Index, &gSmmCpuPrivate->ProcessorInfo[Index]);
+ ASSERT_EFI_ERROR (Status);
+ mCpuHotPlugData.ApicId[Index] = gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId;
+
+ DEBUG ((EFI_D_INFO, "CPU[%03x] APIC ID=%04x SMBASE=%08x SaveState=%08x Size=%08x\n",
+ Index,
+ (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId,
+ mCpuHotPlugData.SmBase[Index],
+ gSmmCpuPrivate->CpuSaveState[Index],
+ gSmmCpuPrivate->CpuSaveStateSize[Index]
+ ));
+ } else {
+ gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId = INVALID_APIC_ID;
+ mCpuHotPlugData.ApicId[Index] = INVALID_APIC_ID;
+ }
+ }
+
+ //
+ // Allocate SMI stacks for all processors.
+ //
+ if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+ //
+ // 2 more pages is allocated for each processor.
+ // one is guard page and the other is known good stack.
+ //
+ // +-------------------------------------------+-----+-------------------------------------------+
+ // | Known Good Stack | Guard Page | SMM Stack | ... | Known Good Stack | Guard Page | SMM Stack |
+ // +-------------------------------------------+-----+-------------------------------------------+
+ // | | | |
+ // |<-------------- Processor 0 -------------->| |<-------------- Processor n -------------->|
+ //
+ mSmmStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStackSize)) + 2);
+ Stacks = (UINT8 *) AllocatePages (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStackSize)) + 2));
+ ASSERT (Stacks != NULL);
+ mSmmStackArrayBase = (UINTN)Stacks;
+ mSmmStackArrayEnd = mSmmStackArrayBase + gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * mSmmStackSize - 1;
+ } else {
+ mSmmStackSize = PcdGet32 (PcdCpuSmmStackSize);
+ Stacks = (UINT8 *) AllocatePages (EFI_SIZE_TO_PAGES (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * mSmmStackSize));
+ ASSERT (Stacks != NULL);
+ }
+
+ //
+ // Set SMI stack for SMM base relocation
+ //
+ gSmmInitStack = (UINTN) (Stacks + mSmmStackSize - sizeof (UINTN));
+
+ //
+ // Relocate SMM Base addresses to the ones allocated from SMRAM
+ // BUGBUG: Work on later
+ //
+ SmmRelocateBases ();
+
+ //
+ // SMM Init
+ // BUGBUG: Work on later
+ //
+ InitializeSmmTimer ();
+
+ //
+ // Initialize IDT
+ // BUGBUG: Work on later
+ //
+ InitializeIDT ();
+
+ SetMem (mExternalVectorTable, sizeof(mExternalVectorTable), 0);
+ //
+ // Set the pointer to the array of C based exception handling routines.
+ //
+ InitializeSmmExternalVectorTablePtr (mExternalVectorTable);
+
+ //
+ // Initialize MP globals
+ //
+ InitializeMpServiceData (ImageHandle, Stacks, mSmmStackSize);
+
+ //
+ // Fill in SMM Reserved Regions
+ //
+ gSmmCpuPrivate->SmmReservedSmramRegion[0].SmramReservedStart = 0;
+ gSmmCpuPrivate->SmmReservedSmramRegion[0].SmramReservedSize = 0;
+
+ //
+ // Install the SMM Configuration Protocol onto a new handle on the handle database.
+ // The entire SMM Configuration Protocol is allocated from SMRAM, so only a pointer
+ // to an SMRAM address will be present in the handle database
+ //
+ Status = SystemTable->BootServices->InstallMultipleProtocolInterfaces (
+ &gSmmCpuPrivate->SmmCpuHandle,
+ &gEfiSmmConfigurationProtocolGuid, &gSmmCpuPrivate->SmmConfiguration,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the SMM CPU Protocol into SMM protocol database
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mSmmCpuHandle,
+ &gEfiSmmCpuProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mSmmCpu
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Smm CPU Sync protocol
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mSmmCpuHandle,
+ &gSmmCpuSyncProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mSmmCpuSync
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Smm CPU Sync2 protocol
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mSmmCpuHandle,
+ &gSmmCpuSync2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mSmmCpuSync2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Expose address of CPU Hot Plug Data structure if CPU hot plug is supported.
+ //
+ if (FeaturePcdGet (PcdCpuHotPlugSupport)) {
+ PcdSet64 (PcdCpuHotPlugDataAddress, (UINT64)(UINTN)&mCpuHotPlugData);
+ }
+
+ //
+ // Initialize SMM CPU Services Support
+ //
+ Status = InitializeSmmCpuServices (mSmmCpuHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
+ //
+ // Install Framework SMM Save State Protocol into UEFI protocol database for backward compatibility
+ //
+ Status = SystemTable->BootServices->InstallMultipleProtocolInterfaces (
+ &gSmmCpuPrivate->SmmCpuHandle,
+ &gEfiSmmCpuSaveStateProtocolGuid,
+ &mSmmCpuSaveState,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // The SmmStartupThisAp service in Framework SMST should always be non-null.
+ // Update SmmStartupThisAp pointer in PI SMST here so that PI/Framework SMM thunk
+ // can have it ready when constructing Framework SMST.
+ //
+ gSmst->SmmStartupThisAp = SmmStartupThisAp;
+ }
+
+ //
+ // register SMM Ready To Lock Protocol notification
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmReadyToLockProtocolGuid,
+ SmmReadyToLockEventNotify,
+ &Registration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+ if (GuidHob != NULL) {
+ SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
+
+ DEBUG ((EFI_D_INFO, "SMM S3 SMRAM Structure = %x\n", SmramDescriptor));
+ DEBUG ((EFI_D_INFO, "SMM S3 Structure = %x\n", SmramDescriptor->CpuStart));
+
+ SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
+ ZeroMem (SmmS3ResumeState, sizeof (SMM_S3_RESUME_STATE));
+
+ mSmmS3ResumeState = SmmS3ResumeState;
+ SmmS3ResumeState->Smst = (EFI_PHYSICAL_ADDRESS)(UINTN)gSmst;
+
+ SmmS3ResumeState->SmmS3ResumeEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)SmmRestoreCpu;
+
+ SmmS3ResumeState->SmmS3StackSize = SIZE_32KB;
+ SmmS3ResumeState->SmmS3StackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES ((UINTN)SmmS3ResumeState->SmmS3StackSize));
+ if (SmmS3ResumeState->SmmS3StackBase == 0) {
+ SmmS3ResumeState->SmmS3StackSize = 0;
+ }
+
+ SmmS3ResumeState->SmmS3Cr0 = gSmmCr0;
+ SmmS3ResumeState->SmmS3Cr3 = gSmiCr3;
+ SmmS3ResumeState->SmmS3Cr4 = gSmmCr4;
+
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ SmmS3ResumeState->Signature = SMM_S3_RESUME_SMM_64;
+ }
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ SmmS3ResumeState->Signature = SMM_S3_RESUME_SMM_32;
+ }
+ }
+ if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ InitSmmProfile ();
+ }
+ DEBUG ((EFI_D_INFO, "SMM CPU Module exit from SMRAM with EFI_SUCCESS\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Find out SMRAM information including SMRR base and SMRR size.
+
+ @param SmrrBase SMRR base
+ @param SmrrSize SMRR size
+
+**/
+VOID
+FindSmramInfo (
+ OUT UINT32 *SmrrBase,
+ OUT UINT32 *SmrrSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
+ EFI_SMRAM_DESCRIPTOR *CurrentSmramRange;
+ EFI_SMRAM_DESCRIPTOR *SmramRanges;
+ UINTN SmramRangeCount;
+ UINTN Index;
+ UINT64 MaxSize;
+ BOOLEAN Found;
+
+ //
+ // Get SMM Access Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get SMRAM information
+ //
+ Size = 0;
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ SmramRanges = (EFI_SMRAM_DESCRIPTOR *)AllocatePool (Size);
+ ASSERT (SmramRanges != NULL);
+
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, SmramRanges);
+ ASSERT_EFI_ERROR (Status);
+
+ SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+
+ //
+ // Find the largest SMRAM range between 1MB and 4GB that is at least 256K - 4K in size
+ //
+ CurrentSmramRange = NULL;
+ for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < SmramRangeCount; Index++) {
+ //
+ // Skip any SMRAM region that is already allocated, needs testing, or needs ECC initialization
+ //
+ if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
+ continue;
+ }
+
+ if (SmramRanges[Index].CpuStart >= BASE_1MB) {
+ if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize) <= BASE_4GB) {
+ if (SmramRanges[Index].PhysicalSize >= MaxSize) {
+ MaxSize = SmramRanges[Index].PhysicalSize;
+ CurrentSmramRange = &SmramRanges[Index];
+ }
+ }
+ }
+ }
+
+ ASSERT (CurrentSmramRange != NULL);
+
+ *SmrrBase = (UINT32)CurrentSmramRange->CpuStart;
+ *SmrrSize = (UINT32)CurrentSmramRange->PhysicalSize;
+
+ do {
+ Found = FALSE;
+ for (Index = 0; Index < SmramRangeCount; Index++) {
+ if (SmramRanges[Index].CpuStart < *SmrrBase && *SmrrBase == (SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize)) {
+ *SmrrBase = (UINT32)SmramRanges[Index].CpuStart;
+ *SmrrSize = (UINT32)(*SmrrSize + SmramRanges[Index].PhysicalSize);
+ Found = TRUE;
+ } else if ((*SmrrBase + *SmrrSize) == SmramRanges[Index].CpuStart && SmramRanges[Index].PhysicalSize > 0) {
+ *SmrrSize = (UINT32)(*SmrrSize + SmramRanges[Index].PhysicalSize);
+ Found = TRUE;
+ }
+ }
+ } while (Found);
+
+ DEBUG ((EFI_D_INFO, "SMRR Base: 0x%x, SMRR Size: 0x%x\n", *SmrrBase, *SmrrSize));
+}
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
new file mode 100644
index 0000000..5d70e6d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -0,0 +1,782 @@
+/** @file
+ Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef _CPU_PISMMCPUDXESMM_H_
+#define _CPU_PISMMCPUDXESMM_H_
+#include <PiSmm.h>
+#include <AcpiCpuData.h>
+
+#include <Protocol/MpService.h>
+#include <Protocol/SmmConfiguration.h>
+#include <Protocol/SmmCpu.h>
+#include <Protocol/SmmAccess2.h>
+#include <Protocol/SmmCpuSaveState.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <Protocol/SmmCpuSync.h>
+#include <Protocol/SmmCpuSync2.h>
+#include <Protocol/SmmCpuService.h>
+
+#include <Guid/AcpiS3Context.h>
+
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/SmmLib.h>
+#include <Library/SynchronizationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/SocketLga775Lib.h>
+#include <Library/SmmCpuPlatformHookLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/HobLib.h>
+#include <Library/CpuConfigLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/UefiCpuLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+#include <CpuHotPlugData.h>
+
+#include "SmmFeatures.h"
+#include "CpuService.h"
+#include "SmmProfile.h"
+
+//
+// Size of Task-State Segment defined in IA32 Manual
+//
+#define TSS_SIZE 104
+#define TSS_X64_IST1_OFFSET 36
+#define TSS_IA32_CR3_OFFSET 28
+#define TSS_IA32_ESP_OFFSET 56
+
+//
+// The size 0x20 must be bigger than
+// the size of template code of SmmInit. Currently,
+// the size of SmmInit requires the 0x16 Bytes buffer
+// at least.
+//
+#define BACK_BUF_SIZE 0x20
+
+#define EXCEPTION_VECTOR_NUMBER 0x20
+
+#define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL
+
+//
+// SMM CPU synchronization features available on a processor
+//
+typedef struct {
+ BOOLEAN TargetedSmiSupported;
+ BOOLEAN DelayIndicationSupported;
+ BOOLEAN BlockIndicationSupported;
+} SMM_CPU_SYNC_FEATURE;
+
+typedef UINT32 SMM_CPU_ARRIVAL_EXCEPTIONS;
+#define ARRIVAL_EXCEPTION_BLOCKED 0x1
+#define ARRIVAL_EXCEPTION_DELAYED 0x2
+#define ARRIVAL_EXCEPTION_SMI_DISABLED 0x4
+
+//
+// Private structure for the SMM CPU module that is stored in DXE Runtime memory
+// Contains the SMM Configuration Protocols that is produced.
+// Contains a mix of DXE and SMM contents. All the fields must be used properly.
+//
+#define SMM_CPU_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('s', 'c', 'p', 'u')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE SmmCpuHandle;
+
+ EFI_PROCESSOR_INFORMATION ProcessorInfo [FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+ SMM_CPU_OPERATION Operation [FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+ UINTN CpuSaveStateSize [FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+ VOID *CpuSaveState [FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+ UINT64 TstateMsr [FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+ SMM_CPU_SYNC_FEATURE SmmSyncFeature [FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+
+ EFI_SMM_RESERVED_SMRAM_REGION SmmReservedSmramRegion[1];
+ EFI_SMM_ENTRY_CONTEXT SmmCoreEntryContext;
+ EFI_SMM_ENTRY_POINT SmmCoreEntry;
+
+ EFI_SMM_CONFIGURATION_PROTOCOL SmmConfiguration;
+} SMM_CPU_PRIVATE_DATA;
+
+extern SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate;
+extern CPU_HOT_PLUG_DATA mCpuHotPlugData;
+extern UINTN mMaxNumberOfCpus;
+extern UINTN mNumberOfCpus;
+extern volatile BOOLEAN mRebased[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+extern UINT32 gSmbase;
+extern BOOLEAN mRestoreSmmConfigurationInS3;
+extern EFI_SMM_CPU_PROTOCOL mSmmCpu;
+
+//
+// SMM CPU Protocol function prototypes.
+//
+
+/**
+ Read information from the CPU save state.
+
+ @param This EFI_SMM_CPU_PROTOCOL instance
+ @param Widthe The number of bytes to read from the CPU save state.
+ @param Register Specifies the CPU register to read form the save state.
+ @param CpuIndex Specifies the zero-based index of the CPU save state
+ @param Buffer Upon return, this holds the CPU register value read from the save state.
+
+ @retval EFI_SUCCESS The register was read from Save State
+ @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
+ @retval EFI_INVALID_PARAMTER This or Buffer is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmReadSaveState (
+ IN CONST EFI_SMM_CPU_PROTOCOL *This,
+ IN UINTN Width,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN CpuIndex,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write data to the CPU save state.
+
+ @param This EFI_SMM_CPU_PROTOCOL instance
+ @param Widthe The number of bytes to read from the CPU save state.
+ @param Register Specifies the CPU register to write to the save state.
+ @param CpuIndex Specifies the zero-based index of the CPU save state
+ @param Buffer Upon entry, this holds the new CPU register value.
+
+ @retval EFI_SUCCESS The register was written from Save State
+ @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
+ @retval EFI_INVALID_PARAMTER ProcessorIndex or Width is not correct
+
+**/
+EFI_STATUS
+EFIAPI
+SmmWriteSaveState (
+ IN CONST EFI_SMM_CPU_PROTOCOL *This,
+ IN UINTN Width,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN CpuIndex,
+ IN CONST VOID *Buffer
+ );
+
+//
+// SMM CPU Sync Protocol and SMM CPU Sync2 Protocol function prototypes.
+//
+
+/**
+ Given timeout constraint, wait for all APs to arrive. If this function returns EFI_SUCCESS, then
+ no AP will execute normal mode code before entering SMM, so it is safe to access shared hardware resource
+ between SMM and normal mode. Note if there are SMI disabled APs, this function will return EFI_NOT_READY.
+
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS No AP will execute normal mode code before entering SMM, so it is safe to access
+ shared hardware resource between SMM and normal mode
+ @retval EFI_NOT_READY One or more CPUs may still execute normal mode code
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSyncCheckApArrival (
+ IN SMM_CPU_SYNC_PROTOCOL *This
+ );
+
+/**
+ Given timeout constraint, wait for all APs to arrive. If this function returns EFI_SUCCESS, then
+ no AP will execute normal mode code before entering SMM, so it is safe to access shared hardware resource
+ between SMM and normal mode. Note if there are SMI disabled APs, this function will return EFI_NOT_READY.
+
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS No AP will execute normal mode code before entering SMM, so it is safe to access
+ shared hardware resource between SMM and normal mode
+ @retval EFI_NOT_READY One or more CPUs may still execute normal mode code
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2CheckApArrival (
+ IN SMM_CPU_SYNC2_PROTOCOL *This
+ );
+
+/**
+ Set SMM synchronization mode starting from the next SMI run.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode The SMM synchronization mode to be set and effective from the next SMI run.
+
+ @retval EFI_SUCCESS The function completes successfully.
+ @retval EFI_INVALID_PARAMETER SynMode is not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSyncSetMode (
+ IN SMM_CPU_SYNC_PROTOCOL *This,
+ IN SMM_CPU_SYNC_MODE SyncMode
+ );
+
+/**
+ Set SMM synchronization mode starting from the next SMI run.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode The SMM synchronization mode to be set and effective from the next SMI run.
+
+ @retval EFI_SUCCESS The function completes successfully.
+ @retval EFI_INVALID_PARAMETER SynMode is not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2SetMode (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN SMM_CPU_SYNC_MODE SyncMode
+ );
+
+/**
+ Get current effective SMM synchronization mode.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode Output parameter. The current effective SMM synchronization mode.
+
+ @retval EFI_SUCCESS The SMM synchronization mode has been retrieved successfully.
+ @retval EFI_INVALID_PARAMETER SyncMode is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSyncGetMode (
+ IN SMM_CPU_SYNC_PROTOCOL *This,
+ OUT SMM_CPU_SYNC_MODE *SyncMode
+ );
+
+/**
+ Get current effective SMM synchronization mode.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param SyncMode Output parameter. The current effective SMM synchronization mode.
+
+ @retval EFI_SUCCESS The SMM synchronization mode has been retrieved successfully.
+ @retval EFI_INVALID_PARAMETER SyncMode is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2GetMode (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ OUT SMM_CPU_SYNC_MODE *SyncMode
+ );
+
+/**
+ Checks CPU SMM synchronization state
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param CpuIndex Index of the CPU for which the state is to be retrieved.
+ @param CpuState The state of the CPU
+
+ @retval EFI_SUCCESS Returns EFI_SUCCESS if the CPU's state is retrieved.
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid or CpuState is NULL
+ @retval EFI_DEVICE_ERROR Error occured in obtaining CPU status.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2CheckCpuState (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex,
+ OUT SMM_CPU_SYNC2_CPU_STATE *CpuState
+ );
+
+/**
+ Change CPU's SMM enabling state.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param CpuIndex Index of the CPU to enable / disable SMM
+ @param Enable If TRUE, enable SMM; if FALSE disable SMM
+
+ @retval EFI_SUCCESS The CPU's SMM enabling state is changed.
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+ @retval EFI_UNSUPPORTED Returns EFI_UNSUPPORTED the CPU does not support dynamically enabling / disabling SMI
+ @retval EFI_DEVICE_ERROR Error occured in changing SMM enabling state.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2ChangeSmmEnabling (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex,
+ IN BOOLEAN Enable
+ );
+
+/**
+ Send SMI IPI to a specific CPU.
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+ @param CpuIndex Index of the CPU to send SMI to.
+
+ @retval EFI_SUCCESS The SMI IPI is sent successfully.
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+ @retval EFI_DEVICE_ERROR Error occured in sending SMI IPI.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2SendSmi (
+ IN SMM_CPU_SYNC2_PROTOCOL *This,
+ IN UINTN CpuIndex
+ );
+
+/**
+ Send SMI IPI to all CPUs excluding self
+
+ @param This A pointer to the SMM_CPU_SYNC_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The SMI IPI is sent successfully.
+ @retval EFI_INVALID_PARAMETER Returns EFI_INVALID_PARAMETER if CpuIndex is invalid
+ @retval EFI_DEVICE_ERROR Error occured in sending SMI IPI.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuSync2SendSmiAllExcludingSelf (
+ IN SMM_CPU_SYNC2_PROTOCOL *This
+ );
+
+///
+/// Structure used to describe a range of registers
+///
+typedef struct {
+ EFI_SMM_SAVE_STATE_REGISTER Start;
+ EFI_SMM_SAVE_STATE_REGISTER End;
+ UINTN Length;
+} CPU_SMM_SAVE_STATE_REGISTER_RANGE;
+
+///
+/// Structure used to build a lookup table to retrieve the widths and offsets
+/// associated with each supported EFI_SMM_SAVE_STATE_REGISTER value
+///
+
+#define SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX 1
+#define SMM_SAVE_STATE_REGISTER_IOMISC_INDEX 2
+#define SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX 3
+#define SMM_SAVE_STATE_REGISTER_MAX_INDEX 4
+
+typedef struct {
+ UINT8 Width32;
+ UINT8 Width64;
+ UINT16 Offset32;
+ UINT16 Offset64Lo;
+ UINT16 Offset64Hi;
+ BOOLEAN Writeable;
+} CPU_SMM_SAVE_STATE_LOOKUP_ENTRY;
+
+///
+/// Structure used to build a lookup table for the IOMisc width information
+///
+typedef struct {
+ UINT8 Width;
+ EFI_SMM_SAVE_STATE_IO_WIDTH IoWidth;
+} CPU_SMM_SAVE_STATE_IO_WIDTH;
+
+//
+//
+//
+typedef struct {
+ UINT32 Offset;
+ UINT16 Segment;
+ UINT16 Reserved;
+} IA32_FAR_ADDRESS;
+
+extern IA32_FAR_ADDRESS gSmmJmpAddr;
+
+extern CONST UINT8 gcSmmInitTemplate[];
+extern CONST UINT16 gcSmmInitSize;
+extern UINT32 gSmmCr0;
+extern UINT32 gSmmCr3;
+extern UINT32 gSmmCr4;
+extern UINTN gSmmInitStack;
+
+/**
+ Seamphore operation for all processor relocate SMMBase.
+**/
+VOID
+EFIAPI
+SmmRelocationSemaphoreComplete (
+ VOID
+ );
+
+/**
+ Hook return address of SMM Save State so that semaphore code
+ can be executed immediately after AP exits SMM to indicate to
+ the BSP that an AP has exited SMM after SMBASE relocation.
+
+ @param CpuIndex The processor index.
+**/
+VOID
+SemaphoreHook (
+ IN UINTN CpuIndex
+ );
+
+///
+/// The type of SMM CPU Information
+///
+typedef struct {
+ SPIN_LOCK Busy;
+ volatile EFI_AP_PROCEDURE Procedure;
+ volatile VOID *Parameter;
+ volatile UINT32 Run;
+ volatile BOOLEAN Present;
+} SMM_CPU_DATA_BLOCK;
+
+typedef struct {
+ SMM_CPU_DATA_BLOCK CpuData[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+ volatile UINT32 Counter;
+ volatile UINT32 BspIndex;
+ volatile BOOLEAN InsideSmm;
+ volatile BOOLEAN AllCpusInSync;
+ SMM_CPU_SYNC_MODE SyncModeToBeSet;
+ volatile SMM_CPU_SYNC_MODE EffectiveSyncMode;
+ volatile BOOLEAN SwitchBsp;
+ volatile BOOLEAN CandidateBsp[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+} SMM_DISPATCHER_MP_SYNC_DATA;
+
+extern IA32_DESCRIPTOR gcSmiGdtr;
+extern CONST IA32_DESCRIPTOR gcSmiIdtr;
+extern UINT32 gSmiCr3;
+extern volatile UINTN gSmiStack;
+extern CONST PROCESSOR_SMM_DESCRIPTOR gcPsd;
+extern volatile UINT8 gcSmiHandlerTemplate[];
+extern CONST UINT16 gcSmiHandlerSize;
+extern CONST UINT16 gcSmiHandlerOffset;
+extern UINT64 gPhyMask;
+extern ACPI_CPU_DATA mAcpiCpuData;
+extern SMM_DISPATCHER_MP_SYNC_DATA *mSmmMpSyncData;
+extern VOID *mGdtForAp;
+extern VOID *mIdtForAp;
+extern VOID *mMachineCheckHandlerForAp;
+extern UINTN mSmmStackArrayBase;
+extern UINTN mSmmStackArrayEnd;
+extern UINTN mSmmStackSize;
+extern IA32_IDT_GATE_DESCRIPTOR gSavedPageFaultIdtEntry;
+extern IA32_IDT_GATE_DESCRIPTOR gSavedDebugExceptionIdtEntry;
+extern EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService;
+
+/**
+ Create 4G PageTable in SMRAM.
+
+ @param ExtraPages Additional page numbers besides for 4G memory
+ @return PageTable Address
+
+**/
+UINT32
+Gen4GPageTable (
+ IN UINTN ExtraPages
+ );
+
+
+/**
+ Initialize global data for MP synchronization.
+
+ @param ImageHandle File Image Handle.
+ @param Stacks Base address of SMI stack buffer for all processors.
+ @param StackSize Stack size for each processor in SMM.
+
+**/
+VOID
+InitializeMpServiceData (
+ IN EFI_HANDLE ImageHandle,
+ IN VOID *Stacks,
+ IN UINTN StackSize
+ );
+
+/**
+ Initialize Timer for Smm AP Sync.
+
+**/
+VOID
+InitializeSmmTimer (
+ VOID
+ );
+
+/**
+ Start Timer for Smm AP Sync.
+
+**/
+UINT64
+EFIAPI
+StartSyncTimer (
+ VOID
+ );
+
+/**
+ Check if the Smm AP Sync timer is timeout.
+
+ @param Timer The start timer from the begin.
+
+**/
+BOOLEAN
+EFIAPI
+IsSyncTimerTimeout (
+ IN UINT64 Timer
+ );
+
+/**
+ Initialize IDT for SM mode.
+
+**/
+VOID
+EFIAPI
+InitializeIDT (
+ VOID
+ );
+
+/**
+
+ Register the SMM Foundation entry point.
+
+ @param This Pointer to EFI_SMM_CONFIGURATION_PROTOCOL instance
+ @param SmmEntryPoint SMM Foundation EntryPoint
+
+ @retval EFI_SUCCESS Successfully to register SMM foundation entry point
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterSmmEntry (
+ IN CONST EFI_SMM_CONFIGURATION_PROTOCOL *This,
+ IN EFI_SMM_ENTRY_POINT SmmEntryPoint
+ );
+
+/**
+ Create PageTable for SMM use.
+
+ @return PageTable Address
+
+**/
+UINT32
+SmmInitPageTable (
+ VOID
+ );
+
+/**
+ Schedule a procedure to run on the specified CPU.
+
+ @param Procedure The address of the procedure to run
+ @param CpuIndex Target CPU number
+ @param ProcArguments The parameter to pass to the procedure
+
+ @retval EFI_INVALID_PARAMETER CpuNumber not valid
+ @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
+ @retval EFI_SUCCESS - The procedure has been successfully scheduled
+
+**/
+EFI_STATUS
+EFIAPI
+SmmStartupThisAp (
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN CpuIndex,
+ IN OUT VOID *ProcArguments OPTIONAL
+ );
+
+/**
+ Schedule a procedure to run on the specified CPU in a blocking fashion.
+
+ @param Procedure The address of the procedure to run
+ @param CpuIndex Target CPU Index
+ @param ProcArguments The parameter to pass to the procedure
+
+ @retval EFI_INVALID_PARAMETER CpuNumber not valid
+ @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
+ @retval EFI_SUCCESS The procedure has been successfully scheduled
+
+**/
+EFI_STATUS
+EFIAPI
+SmmBlockingStartupThisAp (
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN CpuIndex,
+ IN OUT VOID *ProcArguments OPTIONAL
+ );
+
+/**
+ Initialize MP synchronization data.
+
+**/
+VOID
+EFIAPI
+InitializeMpSyncData (
+ VOID
+ );
+
+/**
+
+ Find out SMRAM information including SMRR base and SMRR size.
+
+ @param SmrrBase SMRR base
+ @param SmrrSize SMRR size
+
+**/
+VOID
+FindSmramInfo (
+ OUT UINT32 *SmrrBase,
+ OUT UINT32 *SmrrSize
+ );
+
+/**
+ The function is invoked before SMBASE relocation in S3 path to restors CPU status.
+
+ The function is invoked before SMBASE relocation in S3 path. It does first time microcode load
+ and restores MTRRs for both BSP and APs.
+
+**/
+VOID
+EarlyInitializeCpu (
+ VOID
+ );
+
+/**
+ The function is invoked after SMBASE relocation in S3 path to restors CPU status.
+
+ The function is invoked after SMBASE relocation in S3 path. It restores configuration according to
+ data saved by normal boot path for both BSP and APs.
+
+**/
+VOID
+InitializeCpu (
+ VOID
+ );
+
+/**
+ Page Fault handler for SMM use.
+
+ @param InterruptType Defines the type of interrupt or exception that
+ occurred on the processor.This parameter is processor architecture specific.
+ @param SystemContext A pointer to the processor context when
+ the interrupt occurred on the processor.
+**/
+VOID
+EFIAPI
+SmiPFHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Restore SMM Configuration.
+**/
+VOID
+RestoreSmmConfigurationInS3 (
+ VOID
+ );
+
+/**
+ Read a CPU Save State register on the target processor.
+
+ This function abstracts the differences that whether the CPU Save State register is in the IA32 Cpu Save State Map
+ or x64 Cpu Save State Map or a CPU Save State MSR.
+
+ This function supports reading a CPU Save State register in SMBase relocation handler.
+
+ @param[in] CpuIndex Specifies the zero-based index of the CPU save state.
+ @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.
+ @param[in] Width The number of bytes to read from the CPU save state.
+ @param[out] Buffer Upon return, this holds the CPU register value read from the save state.
+
+ @retval EFI_SUCCESS The register was read from Save State.
+ @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
+ @retval EFI_INVALID_PARAMTER This or Buffer is NULL.
+ @retval EFI_UNSUPPORTED The register has no corresponding MSR.
+
+**/
+EFI_STATUS
+ReadSaveStateRegister (
+ IN UINTN CpuIndex,
+ IN UINTN RegisterIndex,
+ IN UINTN Width,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write value to a CPU Save State register on the target processor.
+
+ This function abstracts the differences that whether the CPU Save State register is in the IA32 Cpu Save State Map
+ or x64 Cpu Save State Map or a CPU Save State MSR.
+
+ This function supports writing a CPU Save State register in SMBase relocation handler.
+
+ @param[in] CpuIndex Specifies the zero-based index of the CPU save state.
+ @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table.
+ @param[in] Width The number of bytes to read from the CPU save state.
+ @param[in] Buffer Upon entry, this holds the new CPU register value.
+
+ @retval EFI_SUCCESS The register was written to Save State.
+ @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
+ @retval EFI_INVALID_PARAMTER ProcessorIndex or Width is not correct.
+ @retval EFI_UNSUPPORTED The register is read-only, cannot be written, or has no corresponding MSR.
+
+**/
+EFI_STATUS
+WriteSaveStateRegister (
+ IN UINTN CpuIndex,
+ IN UINTN RegisterIndex,
+ IN UINTN Width,
+ IN CONST VOID *Buffer
+ );
+
+/**
+ Read information from the CPU save state.
+
+ @param Register Specifies the CPU register to read form the save state.
+
+ @retval 0 Register is not valid
+ @retval >0 Index into mSmmCpuWidthOffset[] associated with Register
+
+**/
+UINTN
+GetRegisterIndex (
+ IN EFI_SMM_SAVE_STATE_REGISTER Register
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
new file mode 100644
index 0000000..122f096
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -0,0 +1,156 @@
+## @file
+#
+# Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PiSmmCpuDxeSmm
+ FILE_GUID = A3FF0EF5-0C28-42f5-B544-8C7DE1E80014
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = PiCpuSmmEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ PiSmmCpuDxeSmm.c
+ PiSmmCpuDxeSmm.h
+ SmmFeatures.c
+ SmmFeatures.h
+ MpService.c
+ SyncTimer.c
+ CpuS3.c
+ CpuService.c
+ CpuService.h
+ SmmProfile.c
+
+[Sources.Ia32]
+ Ia32/Semaphore.c
+ Ia32/PageTbl.c
+ Ia32/SmmProfileArch.c
+ Ia32/SmmInit.asm | MSFT
+ Ia32/SmiException.asm | MSFT
+ Ia32/SmiEntry.asm | MSFT
+ Ia32/MpFuncs.asm | MSFT
+
+ Ia32/SmmInit.asm | INTEL
+ Ia32/SmiException.asm | INTEL
+ Ia32/SmiEntry.asm | INTEL
+ Ia32/MpFuncs.asm | INTEL
+
+ Ia32/SmmInit.S | GCC
+ Ia32/SmiException.S | GCC
+ Ia32/SmiEntry.S | GCC
+ Ia32/MpFuncs.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ CacheMaintenanceLib
+ PcdLib
+ DebugLib
+ BaseLib
+ SynchronizationLib
+ BaseMemoryLib
+ MtrrLib
+ SmmLib
+ IoLib
+ TimerLib
+ SmmServicesTableLib
+ MemoryAllocationLib
+ DebugAgentLib
+ HobLib
+ CpuConfigLib
+ PciLib
+ LocalApicLib
+ UefiCpuLib
+ SmmCpuPlatformHookLib
+ UefiLib
+ DxeServicesTableLib
+ CpuLib
+ ReportStatusCodeLib
+
+[Protocols]
+ gEfiSmmAccess2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSmmConfigurationProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmCpuProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gSmmCpuSyncProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gSmmCpuSync2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmCpuServiceProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmCpuSaveStateProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+
+[Guids]
+ gEfiAcpiVariableGuid # ALWAYS_CONSUMED
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED
+ gEfiAcpi20TableGuid # ALWAYS_CONSUMED System Table
+ gEfiAcpi10TableGuid # ALWAYS_CONSUMED System Table
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmEnableBspElection
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmDebug
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmUncacheCpuSyncData
+ gEfiCpuTokenSpaceGuid.PcdCpuHotPlugSupport
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmStackGuard
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileEnable
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileRingBuffer
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock
+
+[FixedPcd]
+ gEfiCpuTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileSize
+
+[Pcd]
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmStackSize
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmApSyncTimeout
+ gEfiCpuTokenSpaceGuid.PcdCpuS3DataAddress
+ gEfiCpuTokenSpaceGuid.PcdCpuHotPlugDataAddress
+ gEfiCpuTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable
+
+[Depex]
+ gEfiMpServiceProtocolGuid
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmFeatures.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmFeatures.c
new file mode 100644
index 0000000..a3bfbc9
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmFeatures.c
@@ -0,0 +1,380 @@
+/** @file
+ The CPU specific programming for PiSmmCpuDxeSmm module, such as SMRR.
+ Currently below CPUs are supported.
+
+ 0x00000590 // Quark
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Base.h>
+#include "SmmFeatures.h"
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/LocalApicLib.h>
+
+#include "PiSmmCpuDxeSmm.h"
+
+//
+// The CPUID mapping for Pentium
+//
+CPUID_MAPPING mPentiumMap[] = {
+ {CPUID_SIGNATURE_QUARK, CPUID_MASK_NO_STEPPING}, // Quark
+ };
+
+//
+// The CLASS for Pentium
+//
+CPU_SMM_CLASS mPentiumClass = {
+ CpuPentium,
+ sizeof(mPentiumMap)/sizeof(mPentiumMap[0]),
+ mPentiumMap,
+ };
+
+//
+// This table defines supported CPU class
+//
+CPU_SMM_CLASS *mCpuClasstable[] = {
+ &mPentiumClass,
+ };
+
+////////
+// Below section is common definition
+////////
+
+//
+// Assumes UP, or MP with identical feature set
+//
+CPU_SMM_FEATURE_CONTEXT mFeatureContext;
+
+CPU_SMM_CLASS *mThisCpu;
+BOOLEAN mSmmCodeAccessCheckEnable = FALSE;
+
+/**
+ Return if SMRR is supported
+
+ @retval TRUE SMRR is supported.
+ @retval FALSE SMRR is not supported.
+
+**/
+BOOLEAN
+IsSmrrSupported (
+ VOID
+ )
+{
+ UINT64 MtrrCap;
+
+ MtrrCap = AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP);
+ if ((MtrrCap & IA32_MTRR_SMRR_SUPPORT_BIT) == 0) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+////////
+// Below section is definition for CpuPentium
+////////
+/*
+ Initialize SMRR in SMM relocate.
+
+ @param SmrrBase The base address SMRR.
+ @param SmrrSize The size of SMRR.
+*/
+VOID
+PentiumInitSmrr (
+ IN UINT32 SmrrBase,
+ IN UINT32 SmrrSize
+ )
+{
+ AsmWriteMsr64 (EFI_MSR_PENTIUM_SMRR_PHYS_BASE, SmrrBase);
+ AsmWriteMsr64 (EFI_MSR_PENTIUM_SMRR_PHYS_MASK, (~(SmrrSize - 1) & EFI_MSR_SMRR_MASK) | EFI_MSR_SMRR_PHYS_MASK_VALID);
+}
+
+/*
+ Disable SMRR register when SmmInit replace non-SMM MTRRs.
+*/
+VOID
+PentiumDisableSmrr (
+ VOID
+ )
+{
+ AsmWriteMsr64(EFI_MSR_PENTIUM_SMRR_PHYS_MASK, AsmReadMsr64(EFI_MSR_PENTIUM_SMRR_PHYS_MASK) & ~EFI_MSR_SMRR_PHYS_MASK_VALID);
+}
+
+/*
+ Enable SMRR register when SmmInit restores non-SMM MTRRs.
+*/
+VOID
+PentiumEnableSmrr (
+ VOID
+ )
+{
+ AsmWriteMsr64(EFI_MSR_PENTIUM_SMRR_PHYS_MASK, AsmReadMsr64(EFI_MSR_PENTIUM_SMRR_PHYS_MASK) | EFI_MSR_SMRR_PHYS_MASK_VALID);
+}
+
+////////
+// Below section is definition for the supported class
+////////
+
+/**
+ This function will return current CPU_SMM_CLASS accroding to CPUID mapping.
+
+ @return The point to current CPU_SMM_CLASS
+
+**/
+CPU_SMM_CLASS *
+GetCpuFamily (
+ VOID
+ )
+{
+ UINT32 ClassIndex;
+ UINT32 Index;
+ UINT32 Count;
+ CPUID_MAPPING *CpuMapping;
+ UINT32 RegEax;
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
+ for (ClassIndex = 0; ClassIndex < sizeof(mCpuClasstable)/sizeof(mCpuClasstable[0]); ClassIndex++) {
+ CpuMapping = mCpuClasstable[ClassIndex]->MappingTable;
+ Count = mCpuClasstable[ClassIndex]->MappingCount;
+ for (Index = 0; Index < Count; Index++) {
+ if ((CpuMapping[Index].Signature & CpuMapping[Index].Mask) == (RegEax & CpuMapping[Index].Mask)) {
+ return mCpuClasstable[ClassIndex];
+ }
+ }
+ }
+
+ // Not found!!! Should not happen
+ ASSERT (FALSE);
+ return NULL;
+}
+
+////////
+// Below section is external function
+////////
+
+/**
+ Disable SMRR register when SmmInit set SMM MTRRs.
+**/
+VOID
+DisableSmrr (
+ VOID
+ )
+{
+ ASSERT (mThisCpu != NULL);
+
+ switch (mThisCpu->Family) {
+ case CpuPentium:
+ if (mFeatureContext.SmrrEnabled) {
+ PentiumDisableSmrr ();
+ }
+ return ;
+ default:
+ return ;
+ }
+}
+
+/**
+ Enable SMRR register when SmmInit restore non SMM MTRRs.
+**/
+VOID
+ReenableSmrr (
+ VOID
+ )
+{
+ ASSERT (mThisCpu != NULL);
+
+ switch (mThisCpu->Family) {
+ case CpuPentium:
+ if (mFeatureContext.SmrrEnabled) {
+ PentiumEnableSmrr ();
+ }
+ return ;
+ default:
+ return ;
+ }
+}
+
+/**
+ Return if it is needed to configure MTRR to set TSEG cacheability.
+
+ @retval TRUE - we need configure MTRR
+ @retval FALSE - we do not need configure MTRR
+**/
+BOOLEAN
+NeedConfigureMtrrs (
+ VOID
+ )
+{
+ ASSERT (mThisCpu != NULL);
+
+ switch (mThisCpu->Family) {
+ case CpuPentium:
+ default:
+ return TRUE;
+ }
+}
+
+/**
+ Processor specific hook point at each SMM entry.
+
+ @param CpuIndex The index of the cpu which need to check.
+
+**/
+VOID
+SmmRendezvousEntry (
+ IN UINTN CpuIndex
+ )
+{
+ ASSERT (mThisCpu != NULL);
+
+ switch (mThisCpu->Family) {
+ case CpuPentium:
+ default:
+ return ;
+ }
+}
+
+/**
+ Processor specific hook point at each SMM exit.
+
+ @param CpuIndex The index of the cpu which need to check.
+**/
+VOID
+SmmRendezvousExit (
+ IN UINTN CpuIndex
+ )
+{
+ ASSERT (mThisCpu != NULL);
+
+ switch (mThisCpu->Family) {
+ case CpuPentium:
+ default:
+ return ;
+ }
+}
+
+/**
+ Initialize SMRR context in SMM Init.
+**/
+VOID
+InitializeSmmMtrrManager (
+ VOID
+ )
+{
+ mThisCpu = GetCpuFamily ();
+ ASSERT (mThisCpu != NULL);
+
+ switch (mThisCpu->Family) {
+ case CpuPentium:
+ if (!IsSmrrSupported ()) {
+ return ;
+ }
+ mFeatureContext.SmrrEnabled = TRUE;
+ return ;
+ default:
+ return ;
+ }
+}
+
+/**
+ Initialize SMRR/SMBASE/SMM Sync features in SMM Relocate.
+
+ @param ProcessorNumber The processor number
+ @param SmrrBase The base address of SMRR.
+ @param SmrrSize The size of SMRR.
+ @param SmBase The SMBASE value.
+ @param IsBsp If this processor treated as BSP.
+**/
+VOID
+SmmInitiFeatures (
+ IN UINTN ProcessorNumber,
+ IN UINT32 SmrrBase,
+ IN UINT32 SmrrSize,
+ IN UINT32 SmBase,
+ IN BOOLEAN IsBsp
+ )
+{
+ EFI_SMM_CPU_STATE *CpuState;
+ SMM_CPU_SYNC_FEATURE *SyncFeature;
+
+ SyncFeature = &(gSmmCpuPrivate->SmmSyncFeature[ProcessorNumber]);
+ SyncFeature->TargetedSmiSupported = FALSE;
+ SyncFeature->DelayIndicationSupported = FALSE;
+ SyncFeature->BlockIndicationSupported = FALSE;
+
+ mThisCpu = GetCpuFamily ();
+ ASSERT (mThisCpu != NULL);
+
+ //
+ // Configure SMBASE.
+ //
+ switch (mThisCpu->Family) {
+ //
+ // Fall back to legacy SMBASE setup.
+ //
+ case CpuPentium:
+ CpuState = (EFI_SMM_CPU_STATE *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_CPU_STATE_OFFSET);
+ CpuState->x86.SMBASE = SmBase;
+ break ;
+ default:
+ return ;
+ }
+
+ switch (mThisCpu->Family) {
+ case CpuPentium:
+ if (!IsSmrrSupported ()) {
+ return ;
+ }
+ PentiumInitSmrr (SmrrBase, SmrrSize);
+ return ;
+ default:
+ ASSERT (FALSE);
+ return ;
+ }
+}
+
+/**
+ Configure SMM Code Access Check feature for all processors.
+ SMM Feature Control MSR will be locked after configuration.
+**/
+VOID
+ConfigSmmCodeAccessCheck (
+ VOID
+ )
+{
+
+}
+
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmFeatures.h b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmFeatures.h
new file mode 100644
index 0000000..15e44d0
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmFeatures.h
@@ -0,0 +1,191 @@
+/** @file
+ The CPU specific programming for PiSmmCpuDxeSmm module.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __SMM_FEATURES_H__
+#define __SMM_FEATURES_H__
+
+////////
+// Below definition is from IA32 SDM
+////////
+#define EFI_CPUID_VERSION_INFO 0x1
+#define EFI_CPUID_CORE_TOPOLOGY 0x0B
+#define EFI_CPUID_EXTENDED_FUNCTION 0x80000000
+#define EFI_CPUID_VIR_PHY_ADDRESS_SIZE 0x80000008
+
+#define EFI_MSR_IA32_MTRR_CAP 0xFE
+#define IA32_MTRR_SMRR_SUPPORT_BIT BIT11
+
+#define EFI_MSR_SMRR_PHYS_MASK_VALID BIT11
+#define EFI_MSR_SMRR_MASK 0xFFFFF000
+
+#define EFI_MSR_PENTIUM_SMRR_PHYS_BASE 0xA0
+#define EFI_MSR_PENTIUM_SMRR_PHYS_MASK 0xA1
+
+#define CACHE_WRITE_PROTECT 5
+#define CACHE_WRITE_BACK 6
+#define SMM_DEFAULT_SMBASE 0x30000
+
+////////
+// Below section is definition for CPU SMM Feature context
+////////
+
+//
+// Structure to describe CPU identification mapping
+// if ((CPUID_EAX(1) & Mask) == (Signature & Mask)), it means matched.
+//
+typedef struct {
+ UINT32 Signature;
+ UINT32 Mask;
+} CPUID_MAPPING;
+
+//
+// CPU SMM familiy
+//
+typedef enum {
+ CpuPentium,
+ CpuSmmFamilyMax
+} CPU_SMM_FAMILY;
+
+//
+// Structure to describe CPU SMM class
+//
+typedef struct {
+ CPU_SMM_FAMILY Family;
+ UINT32 MappingCount;
+ CPUID_MAPPING *MappingTable;
+} CPU_SMM_CLASS;
+
+//
+// Structure to describe CPU_SMM_FEATURE_CONTEXT
+//
+typedef struct {
+ BOOLEAN SmrrEnabled;
+} CPU_SMM_FEATURE_CONTEXT;
+
+//
+// Pentium CPUID signatures
+//
+#define CPUID_SIGNATURE_QUARK 0x00000590
+
+//
+// CPUID masks
+//
+#define CPUID_MASK_NO_STEPPING 0x0FFF0FF0
+#define CPUID_MASK_NO_STEPPING_MODEL 0x0FFF0F00
+
+extern BOOLEAN mSmmCodeAccessCheckEnable;
+extern CPU_SMM_CLASS *mThisCpu;
+
+/**
+ Disable SMRR register when SmmInit set SMM MTRRs.
+**/
+VOID
+DisableSmrr (
+ VOID
+ );
+
+/**
+ Enable SMRR register when SmmInit restore non SMM MTRRs.
+**/
+VOID
+ReenableSmrr (
+ VOID
+ );
+
+/**
+ Return if it is needed to configure MTRR to set TSEG cacheability.
+
+ @retval TRUE - we need configure MTRR
+ @retval FALSE - we do not need configure MTRR
+**/
+BOOLEAN
+NeedConfigureMtrrs (
+ VOID
+ );
+
+/**
+ Processor specific hook point at each SMM entry.
+
+ @param CpuIndex The index of the cpu which need to check.
+**/
+VOID
+SmmRendezvousEntry (
+ IN UINTN CpuIndex
+ );
+
+/**
+ Processor specific hook point at each SMM exit.
+
+ @param CpuIndex The index of the cpu which need to check.
+**/
+VOID
+SmmRendezvousExit (
+ IN UINTN CpuIndex
+ );
+
+/**
+ Initialize SMRR context in SMM Init.
+**/
+VOID
+InitializeSmmMtrrManager (
+ VOID
+ );
+
+/**
+ Initialize SMRR/SMBASE/SMM Sync features in SMM Relocate.
+
+ @param ProcessorNumber The processor number
+ @param SmrrBase The base address of SMRR.
+ @param SmrrSize The size of SMRR.
+ @param SmBase The SMBASE value.
+ @param IsBsp If this processor treated as BSP.
+**/
+VOID
+SmmInitiFeatures (
+ IN UINTN ProcessorNumber,
+ IN UINT32 SmrrBase,
+ IN UINT32 SmrrSize,
+ IN UINT32 SmBase,
+ IN BOOLEAN IsBsp
+ );
+
+/**
+ Configure SMM Code Access Check feature for all processors.
+ SMM Feature Control MSR will be locked after configuration.
+**/
+VOID
+ConfigSmmCodeAccessCheck (
+ VOID
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfile.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfile.c
new file mode 100644
index 0000000..1d97595
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -0,0 +1,1376 @@
+/** @file
+ Enable SMM profile.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+#include "SmmProfileInternal.h"
+
+SMM_PROFILE_HEADER *mSmmProfileBase;
+MSR_DS_AREA_STRUCT *mMsrDsAreaBase;
+//
+// The buffer to store SMM profile data.
+//
+UINTN mSmmProfileSize = FixedPcdGet32 (PcdCpuSmmProfileSize);
+
+//
+// The buffer to enable branch trace store.
+//
+UINTN mMsrDsAreaSize = SMM_PROFILE_DTS_SIZE;
+
+//
+// The flag indicates if execute-disable is supported by processor.
+//
+BOOLEAN mXdSupported = FALSE;
+
+//
+// The flag indicates if BTS is supported by processor.
+//
+BOOLEAN mBtsSupported = FALSE;
+
+//
+// The flag indicates if SMM profile starts to record data.
+//
+BOOLEAN mSmmProfileStart = FALSE;
+
+//
+// Record the page fault exception count for one instruction execution.
+//
+UINTN mPFEntryCount[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+
+UINT64 mLastPFEntryValue[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)][MAX_PF_ENTRY_COUNT];
+UINT64 *mLastPFEntryPointer[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)][MAX_PF_ENTRY_COUNT];
+
+MSR_DS_AREA_STRUCT *mMsrDsArea[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+BRANCH_TRACE_RECORD *mMsrBTSRecord[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+UINTN mBTSRecordNumber;
+PEBS_RECORD *mMsrPEBSRecord[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+
+//
+// These memory ranges are always present, they does not generate the access type of page fault exception,
+// but they possibly generate instruction fetch type of page fault exception.
+//
+MEMORY_PROTECTION_RANGE *mProtectionMemRange = NULL;
+UINTN mProtectionMemRangeCount = 0;
+
+//
+// Some pre-defined memory ranges.
+//
+MEMORY_PROTECTION_RANGE mProtectionMemRangeTemplate[] = {
+ //
+ // SMRAM range (to be fixed in runtime).
+ // It is always present and instruction fetches are allowed.
+ //
+ {{0x00000000, 0x00000000},TRUE,FALSE},
+
+ //
+ // SMM profile data range( to be fixed in runtime).
+ // It is always present and instruction fetches are not allowed.
+ //
+ {{0x00000000, 0x00000000},TRUE,TRUE},
+
+ //
+ // Future exended range could be added here.
+ //
+
+ //
+ // PCI MMIO ranges (to be added in runtime).
+ // They are always present and instruction fetches are not allowed.
+ //
+};
+
+//
+// These memory ranges are mapped by 4KB-page instead of 2MB-page.
+//
+MEMORY_RANGE *mSplitMemRange = NULL;
+UINTN mSplitMemRangeCount = 0;
+
+//
+// SMI command port.
+//
+UINT32 mSmiCommandPort;
+
+/**
+ Disable branch trace store.
+
+**/
+VOID
+DisableBTS (
+ VOID
+ )
+{
+ AsmMsrAnd64 (MSR_DEBUG_CTL, ~((UINT64)(MSR_DEBUG_CTL_BTS | MSR_DEBUG_CTL_TR)));
+}
+
+/**
+ Enable branch trace store.
+
+**/
+VOID
+EnableBTS (
+ VOID
+ )
+{
+ AsmMsrOr64 (MSR_DEBUG_CTL, (MSR_DEBUG_CTL_BTS | MSR_DEBUG_CTL_TR));
+}
+
+/**
+ Get CPU Index from Apic ID.
+
+**/
+UINTN
+GetCpuIndex (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT32 ApicId;
+
+ ApicId = GetApicId ();
+
+ for (Index = 0; Index < FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber); Index++) {
+ if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) {
+ return Index;
+ }
+ }
+ ASSERT (FALSE);
+ return 0;
+}
+
+/**
+ Get the source of IP after execute-disable exception is triggered.
+
+ @param CpuIndex The index of CPU.
+ @param DestinationIP The destination address.
+
+**/
+UINT64
+GetSourceFromDestinationOnBts (
+ UINTN CpuIndex,
+ UINT64 DestinationIP
+ )
+{
+ BRANCH_TRACE_RECORD *CurrentBTSRecord;
+ UINTN Index;
+ BOOLEAN FirstMatch;
+
+ FirstMatch = FALSE;
+
+ CurrentBTSRecord = (BRANCH_TRACE_RECORD *)mMsrDsArea[CpuIndex]->BTSIndex;
+ for (Index = 0; Index < mBTSRecordNumber; Index++) {
+ if ((UINTN)CurrentBTSRecord < (UINTN)mMsrBTSRecord[CpuIndex]) {
+ //
+ // Underflow
+ //
+ CurrentBTSRecord = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[CpuIndex]->BTSAbsoluteMaximum - 1);
+ CurrentBTSRecord --;
+ }
+ if (CurrentBTSRecord->LastBranchTo == DestinationIP) {
+ //
+ // Good! find 1st one, then find 2nd one.
+ //
+ if (!FirstMatch) {
+ //
+ // The first one is DEBUG exception
+ //
+ FirstMatch = TRUE;
+ } else {
+ //
+ // Good find proper one.
+ //
+ return CurrentBTSRecord->LastBranchFrom;
+ }
+ }
+ CurrentBTSRecord--;
+ }
+
+ return 0;
+}
+
+/**
+ SMM profile specific INT 1 (single-step) exception handler.
+
+ @param InterruptType Defines the type of interrupt or exception that
+ occurred on the processor.This parameter is processor architecture specific.
+ @param SystemContext A pointer to the processor context when
+ the interrupt occurred on the processor.
+**/
+VOID
+EFIAPI
+DebugExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINTN CpuIndex;
+ UINTN PFEntry;
+
+ if (!mSmmProfileStart) {
+ return;
+ }
+ CpuIndex = GetCpuIndex ();
+
+ //
+ // Clear last PF entries
+ //
+ for (PFEntry = 0; PFEntry < mPFEntryCount[CpuIndex]; PFEntry++) {
+ *mLastPFEntryPointer[CpuIndex][PFEntry] = mLastPFEntryValue[CpuIndex][PFEntry];
+ }
+
+ //
+ // Reset page fault exception count for next page fault.
+ //
+ mPFEntryCount[CpuIndex] = 0;
+
+ //
+ // Flush TLB
+ //
+ CpuFlushTlb ();
+}
+
+/**
+ Check if the memory address will be mapped by 4KB-page.
+
+ @param Address The address of Memory.
+ @param Nx The flag indicates if the memory is execute-disable.
+
+**/
+BOOLEAN
+IsAddressValid (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN BOOLEAN *Nx
+ )
+{
+ UINTN Index;
+
+ //
+ // Check config
+ //
+ for (Index = 0; Index < mProtectionMemRangeCount; Index++) {
+ if ((Address >= mProtectionMemRange[Index].Range.Base) && (Address < mProtectionMemRange[Index].Range.Top)) {
+ *Nx = mProtectionMemRange[Index].Nx;
+ return mProtectionMemRange[Index].Present;
+ }
+ }
+
+ //
+ // Return default
+ //
+ *Nx = FALSE;
+ return FALSE;
+}
+
+/**
+ Check if the memory address will be mapped by 4KB-page.
+
+ @param Address The address of Memory.
+
+**/
+BOOLEAN
+IsAddressSplit (
+ IN EFI_PHYSICAL_ADDRESS Address
+ )
+{
+ UINTN Index;
+
+ //
+ // Check config
+ //
+ for (Index = 0; Index < mSplitMemRangeCount; Index++) {
+ if ((Address >= mSplitMemRange[Index].Base) && (Address < mSplitMemRange[Index].Top)) {
+ return TRUE;
+ }
+ }
+
+ //
+ // Return default
+ //
+ return FALSE;
+}
+
+/**
+ Initialize the protected memory ranges and the 4KB-page mapped memory ranges.
+
+**/
+VOID
+InitProtectedMemRange (
+ VOID
+ )
+{
+ UINTN Index;
+ UINTN NumberOfDescriptors;
+ UINTN NumberOfMmioDescriptors;
+ UINTN NumberOfProtectRange;
+ UINTN NumberOfSpliteRange;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ UINTN TotalSize;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS ProtectBaseAddress;
+ EFI_PHYSICAL_ADDRESS ProtectEndAddress;
+ EFI_PHYSICAL_ADDRESS Top2MBAlignedAddress;
+ EFI_PHYSICAL_ADDRESS Base2MBAlignedAddress;
+ UINT64 High4KBPageSize;
+ UINT64 Low4KBPageSize;
+
+ NumberOfDescriptors = 0;
+ NumberOfMmioDescriptors = 0;
+ NumberOfSpliteRange = 0;
+ MemorySpaceMap = NULL;
+
+ //
+ // Get MMIO ranges from GCD and add them into protected memory ranges.
+ //
+ Status = gDS->GetMemorySpaceMap (
+ &NumberOfDescriptors,
+ &MemorySpaceMap
+ );
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
+ NumberOfMmioDescriptors++;
+ }
+ }
+
+ if (NumberOfMmioDescriptors != 0) {
+ TotalSize = NumberOfMmioDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate);
+ mProtectionMemRange = (MEMORY_PROTECTION_RANGE *) AllocateZeroPool (TotalSize);
+ ASSERT (mProtectionMemRange != NULL);
+ mProtectionMemRangeCount = TotalSize / sizeof (MEMORY_PROTECTION_RANGE);
+
+ //
+ // Copy existing ranges.
+ //
+ CopyMem (mProtectionMemRange, mProtectionMemRangeTemplate, sizeof (mProtectionMemRangeTemplate));
+
+ //
+ // Create split ranges which come from protected ranges.
+ //
+ TotalSize = (TotalSize / sizeof (MEMORY_PROTECTION_RANGE)) * sizeof (MEMORY_RANGE);
+ mSplitMemRange = (MEMORY_RANGE *) AllocateZeroPool (TotalSize);
+ ASSERT (mSplitMemRange != NULL);
+
+ //
+ // Create MMIO ranges which are set to present and execution-disable.
+ //
+ NumberOfProtectRange = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {
+ continue;
+ }
+ mProtectionMemRange[NumberOfProtectRange].Range.Base = MemorySpaceMap[Index].BaseAddress;
+ mProtectionMemRange[NumberOfProtectRange].Range.Top = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length;
+ mProtectionMemRange[NumberOfProtectRange].Present = TRUE;
+ mProtectionMemRange[NumberOfProtectRange].Nx = TRUE;
+ NumberOfProtectRange++;
+ }
+ }
+
+ //
+ // According to protected ranges, create the ranges which will be mapped by 2KB page.
+ //
+ NumberOfSpliteRange = 0;
+ NumberOfProtectRange = mProtectionMemRangeCount;
+ for (Index = 0; Index < NumberOfProtectRange; Index++) {
+ //
+ // If MMIO base address is not 2MB alignment, make 2MB alignment for create 4KB page in page table.
+ //
+ ProtectBaseAddress = mProtectionMemRange[Index].Range.Base;
+ ProtectEndAddress = mProtectionMemRange[Index].Range.Top;
+ if (((ProtectBaseAddress & (SIZE_2MB - 1)) != 0) || ((ProtectEndAddress & (SIZE_2MB - 1)) != 0)) {
+ //
+ // Check if it is possible to create 4KB-page for not 2MB-aligned range and to create 2MB-page for 2MB-aligned range.
+ // A mix of 4KB and 2MB page could save SMRAM space.
+ //
+ Top2MBAlignedAddress = ProtectEndAddress & ~(SIZE_2MB - 1);
+ Base2MBAlignedAddress = (ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);
+ if ((Top2MBAlignedAddress > Base2MBAlignedAddress) &&
+ ((Top2MBAlignedAddress - Base2MBAlignedAddress) >= SIZE_2MB)) {
+ //
+ // There is an range which could be mapped by 2MB-page.
+ //
+ High4KBPageSize = ((ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1)) - (ProtectEndAddress & ~(SIZE_2MB - 1));
+ Low4KBPageSize = ((ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1)) - (ProtectBaseAddress & ~(SIZE_2MB - 1));
+ if (High4KBPageSize != 0) {
+ //
+ // Add not 2MB-aligned range to be mapped by 4KB-page.
+ //
+ mSplitMemRange[NumberOfSpliteRange].Base = ProtectEndAddress & ~(SIZE_2MB - 1);
+ mSplitMemRange[NumberOfSpliteRange].Top = (ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);
+ NumberOfSpliteRange++;
+ }
+ if (Low4KBPageSize != 0) {
+ //
+ // Add not 2MB-aligned range to be mapped by 4KB-page.
+ //
+ mSplitMemRange[NumberOfSpliteRange].Base = ProtectBaseAddress & ~(SIZE_2MB - 1);
+ mSplitMemRange[NumberOfSpliteRange].Top = (ProtectBaseAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);
+ NumberOfSpliteRange++;
+ }
+ } else {
+ //
+ // The range could only be mapped by 4KB-page.
+ //
+ mSplitMemRange[NumberOfSpliteRange].Base = ProtectBaseAddress & ~(SIZE_2MB - 1);
+ mSplitMemRange[NumberOfSpliteRange].Top = (ProtectEndAddress + SIZE_2MB - 1) & ~(SIZE_2MB - 1);
+ NumberOfSpliteRange++;
+ }
+ }
+ }
+
+ mSplitMemRangeCount = NumberOfSpliteRange;
+
+ DEBUG ((EFI_D_INFO, "SMM Profile Memory Ranges:\n"));
+ for (Index = 0; Index < mProtectionMemRangeCount; Index++) {
+ DEBUG ((EFI_D_INFO, "mProtectionMemRange[%d].Base = %lx\n", Index, mProtectionMemRange[Index].Range.Base));
+ DEBUG ((EFI_D_INFO, "mProtectionMemRange[%d].Top = %lx\n", Index, mProtectionMemRange[Index].Range.Top));
+ }
+ for (Index = 0; Index < mSplitMemRangeCount; Index++) {
+ DEBUG ((EFI_D_INFO, "mSplitMemRange[%d].Base = %lx\n", Index, mSplitMemRange[Index].Base));
+ DEBUG ((EFI_D_INFO, "mSplitMemRange[%d].Top = %lx\n", Index, mSplitMemRange[Index].Top));
+ }
+}
+
+/**
+ Update page table according to protected memory ranges and the 4KB-page mapped memory ranges.
+
+**/
+VOID
+InitPaging (
+ VOID
+ )
+{
+ UINT64 *Pml4;
+ UINT64 *Pde;
+ UINT64 *Pte;
+ UINT64 *Pt;
+ UINTN Address;
+ UINTN Level1;
+ UINTN Level2;
+ UINTN Level3;
+ UINTN Level4;
+ UINTN NumberOfPdpEntries;
+ UINTN NumberOfPml4Entries;
+ UINTN SizeOfMemorySpace;
+ BOOLEAN Nx;
+
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ Pml4 = (UINT64*)(UINTN)gSmiCr3;
+ SizeOfMemorySpace = HighBitSet64 (gPhyMask) + 1;
+ //
+ // Calculate the table entries of PML4E and PDPTE.
+ //
+ if (SizeOfMemorySpace <= 39 ) {
+ NumberOfPml4Entries = 1;
+ NumberOfPdpEntries = (UINT32)LShiftU64 (1, (SizeOfMemorySpace - 30));
+ } else {
+ NumberOfPml4Entries = (UINT32)LShiftU64 (1, (SizeOfMemorySpace - 39));
+ NumberOfPdpEntries = 512;
+ }
+ } else {
+ NumberOfPml4Entries = 1;
+ NumberOfPdpEntries = 4;
+ }
+
+ //
+ // Go through page table and change 2MB-page into 4KB-page.
+ //
+ for (Level1 = 0; Level1 < NumberOfPml4Entries; Level1++) {
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ Pde = (UINT64 *)(UINTN)(Pml4[Level1] & PHYSICAL_ADDRESS_MASK);
+ } else {
+ Pde = (UINT64*)(UINTN)gSmiCr3;
+ }
+ for (Level2 = 0; Level2 < NumberOfPdpEntries; Level2++, Pde++) {
+ Pte = (UINT64 *)(UINTN)(*Pde & PHYSICAL_ADDRESS_MASK);
+ if (Pte == 0) {
+ continue;
+ }
+ for (Level3 = 0; Level3 < SIZE_4KB / sizeof (*Pte); Level3++, Pte++) {
+ Address = (((Level2 << 9) + Level3) << 21);
+
+ //
+ // if it is 2M page, check IsAddressSplit()
+ //
+ if (((*Pte & IA32_PG_PS) != 0) && IsAddressSplit (Address)) {
+ //
+ // Based on current page table, create 4KB page table for split area.
+ //
+ ASSERT (Address == (*Pte & PHYSICAL_ADDRESS_MASK));
+
+ Pt = AllocatePages (1);
+ ASSERT (Pt != NULL);
+
+ *Pte = (UINTN)Pt | IA32_PG_RW | IA32_PG_P;
+
+ // Split it
+ for (Level4 = 0; Level4 < SIZE_4KB / sizeof(*Pt); Level4++, Pt++) {
+ *Pt = Address + ((Level4 << 12) | IA32_PG_RW | IA32_PG_P);
+ } // end for PT
+ } // end if IsAddressSplit
+ } // end for PTE
+ } // end for PDE
+ }
+
+ //
+ // Go through page table and set several page table entries to absent or execute-disable.
+ //
+ DEBUG ((EFI_D_INFO, "Patch page table start ...\n"));
+ for (Level1 = 0; Level1 < NumberOfPml4Entries; Level1++) {
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ Pde = (UINT64 *)(UINTN)(Pml4[Level1] & PHYSICAL_ADDRESS_MASK);
+ } else {
+ Pde = (UINT64*)(UINTN)gSmiCr3;
+ }
+ for (Level2 = 0; Level2 < NumberOfPdpEntries; Level2++, Pde++) {
+ Pte = (UINT64 *)(UINTN)(*Pde & PHYSICAL_ADDRESS_MASK);
+ if (Pte == 0) {
+ continue;
+ }
+ for (Level3 = 0; Level3 < SIZE_4KB / sizeof (*Pte); Level3++, Pte++) {
+ Address = (((Level2 << 9) + Level3) << 21);
+
+ if ((*Pte & IA32_PG_PS) != 0) {
+ // 2MB page
+
+ if (!IsAddressValid (Address, &Nx)) {
+ //
+ // Patch to remove present flag and rw flag
+ //
+ *Pte = *Pte & (INTN)(INT32)(~(IA32_PG_RW | IA32_PG_P));
+ }
+ if (Nx && mXdSupported) {
+ *Pte = *Pte | IA32_PG_NX;
+ }
+ } else {
+ // 4KB page
+ Pt = (UINT64 *)(UINTN)(*Pte & PHYSICAL_ADDRESS_MASK);
+ if (Pt == 0) {
+ continue;
+ }
+ for (Level4 = 0; Level4 < SIZE_4KB / sizeof(*Pt); Level4++, Pt++) {
+ if (!IsAddressValid (Address, &Nx)) {
+ *Pt = *Pt & (INTN)(INT32)(~(IA32_PG_RW | IA32_PG_P));
+ }
+ if (Nx && mXdSupported) {
+ *Pt = *Pt | IA32_PG_NX;
+ }
+ Address += SIZE_4KB;
+ } // end for PT
+ } // end if PS
+ } // end for PTE
+ } // end for PDE
+ }
+
+ //
+ // Flush TLB
+ //
+ CpuFlushTlb ();
+ DEBUG ((EFI_D_INFO, "Patch page table done!\n"));
+
+ return ;
+}
+
+/**
+ To find Fadt in Acpi tables.
+
+ @param AcpiTableGuid The guid used to find ACPI table in UEFI ConfigurationTable.
+
+ @return Fadt table pointer.
+**/
+EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *
+FindAcpiFadtTableByAcpiGuid (
+ IN EFI_GUID *AcpiTableGuid
+ )
+{
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
+ EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
+ UINTN Index;
+ UINT32 Data32;
+ Rsdp = NULL;
+ Rsdt = NULL;
+ Fadt = NULL;
+ //
+ // found ACPI table RSD_PTR from system table
+ //
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), AcpiTableGuid)) {
+ //
+ // A match was found.
+ //
+ Rsdp = gST->ConfigurationTable[Index].VendorTable;
+ break;
+ }
+ }
+
+ if (Rsdp == NULL) {
+ return NULL;
+ }
+
+ Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress;
+ if (Rsdt == NULL || Rsdt->Signature != EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ return NULL;
+ }
+
+ for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Rsdt->Length; Index = Index + sizeof (UINT32)) {
+
+ Data32 = *(UINT32 *) ((UINT8 *) Rsdt + Index);
+ Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) (UINT32 *) (UINTN) Data32;
+ if (Fadt->Header.Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
+ break;
+ }
+ }
+
+ if (Fadt == NULL || Fadt->Header.Signature != EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
+ return NULL;
+ }
+
+ return Fadt;
+}
+
+/**
+ To find Fadt in Acpi tables.
+
+ @return Fadt table pointer.
+**/
+EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *
+FindAcpiFadtTable (
+ VOID
+ )
+{
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
+
+ Fadt = FindAcpiFadtTableByAcpiGuid (&gEfiAcpi20TableGuid);
+ if (Fadt != NULL) {
+ return Fadt;
+ }
+
+ return FindAcpiFadtTableByAcpiGuid (&gEfiAcpi10TableGuid);
+}
+
+/**
+ To get system port address of the SMI Command Port in FADT table.
+
+**/
+VOID
+GetSmiCommandPort (
+ VOID
+ )
+{
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
+
+ Fadt = FindAcpiFadtTable ();
+ ASSERT (Fadt != NULL);
+
+ mSmiCommandPort = Fadt->SmiCmd;
+ DEBUG ((EFI_D_ERROR, "mSmiCommandPort = %x\n", mSmiCommandPort));
+}
+
+/**
+ The SmmReadyToLock protocol callback function updates page table
+ to make some memory ranges (like system memory) absent and make
+ some memory ranges (like MMIO) present and execute disable. It also
+ update 2MB-page to 4KB-page for some memory ranges.
+
+ @param Protocol Points to the protocol's unique identifier.
+ @param Interface Points to the interface instance.
+ @param Handle The handle on which the interface was installed.
+
+ @retval EFI_SUCCESS SmmReadyToLock protocol callback runs successfully.
+**/
+EFI_STATUS
+EFIAPI
+SmmProfileStartCallBack (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Save to variable so that SMM profile data can be found.
+ //
+ Status = gRT->SetVariable (
+ SMM_PROFILE_NAME,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(mSmmProfileBase),
+ &mSmmProfileBase
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Software SMI from Fadt
+ //
+ GetSmiCommandPort ();
+
+ //
+ // Init protected mem range for patching page table below.
+ //
+ InitProtectedMemRange ();
+
+ //
+ // Create a mix of 2MB and 4KB page table. Update some memory ranges absent and execute-disable.
+ //
+ InitPaging ();
+
+ //
+ // The flag indicates SMM profile starts to work.
+ //
+ mSmmProfileStart = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize SMM profile data structures.
+
+**/
+VOID
+InitSmmProfileInternal (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Base;
+ VOID *Registration;
+ UINTN Index;
+ UINTN MsrDsAreaSizePerCpu;
+ UINTN TotalSize;
+
+ //
+ // Allocate memory for SmmProfile below 4GB.
+ // The base address
+ //
+ ASSERT ((mSmmProfileSize & 0xFFF) == 0);
+
+ if (mBtsSupported) {
+ TotalSize = mSmmProfileSize + mMsrDsAreaSize;
+ } else {
+ TotalSize = mSmmProfileSize;
+ }
+
+ Base = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (TotalSize),
+ &Base
+ );
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem ((VOID *)(UINTN)Base, TotalSize);
+ mSmmProfileBase = (SMM_PROFILE_HEADER *)(UINTN)Base;
+
+ //
+ // Initialize SMM profile data header.
+ //
+ mSmmProfileBase->HeaderSize = sizeof (SMM_PROFILE_HEADER);
+ mSmmProfileBase->MaxDataEntries = (UINT64)((mSmmProfileSize - sizeof(SMM_PROFILE_HEADER)) / sizeof (SMM_PROFILE_ENTRY));
+ mSmmProfileBase->MaxDataSize = MultU64x64 (mSmmProfileBase->MaxDataEntries, sizeof(SMM_PROFILE_ENTRY));
+ mSmmProfileBase->CurDataEntries = 0;
+ mSmmProfileBase->CurDataSize = 0;
+ mSmmProfileBase->TsegStart = mCpuHotPlugData.SmrrBase;
+ mSmmProfileBase->TsegSize = mCpuHotPlugData.SmrrSize;
+ mSmmProfileBase->NumSmis = 0;
+ mSmmProfileBase->NumCpus = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;
+
+ if (mBtsSupported) {
+ mMsrDsAreaBase = (MSR_DS_AREA_STRUCT *)((UINTN)Base + mSmmProfileSize);
+ MsrDsAreaSizePerCpu = mMsrDsAreaSize / FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ mBTSRecordNumber = (MsrDsAreaSizePerCpu - sizeof(PEBS_RECORD) * PEBS_RECORD_NUMBER - sizeof(MSR_DS_AREA_STRUCT)) / sizeof(BRANCH_TRACE_RECORD);
+ for (Index = 0; Index < FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber); Index++) {
+ mMsrDsArea[Index] = (MSR_DS_AREA_STRUCT *)((UINTN)mMsrDsAreaBase + MsrDsAreaSizePerCpu * Index);
+ mMsrBTSRecord[Index] = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[Index] + sizeof(MSR_DS_AREA_STRUCT));
+ mMsrPEBSRecord[Index] = (PEBS_RECORD *)((UINTN)mMsrDsArea[Index] + MsrDsAreaSizePerCpu - sizeof(PEBS_RECORD) * PEBS_RECORD_NUMBER);
+
+ mMsrDsArea[Index]->BTSBufferBase = (UINTN)mMsrBTSRecord[Index];
+ mMsrDsArea[Index]->BTSIndex = mMsrDsArea[Index]->BTSBufferBase;
+ mMsrDsArea[Index]->BTSAbsoluteMaximum = mMsrDsArea[Index]->BTSBufferBase + mBTSRecordNumber * sizeof(BRANCH_TRACE_RECORD) + 1;
+ mMsrDsArea[Index]->BTSInterruptThreshold = mMsrDsArea[Index]->BTSAbsoluteMaximum + 1;
+
+ mMsrDsArea[Index]->PEBSBufferBase = (UINTN)mMsrPEBSRecord[Index];
+ mMsrDsArea[Index]->PEBSIndex = mMsrDsArea[Index]->PEBSBufferBase;
+ mMsrDsArea[Index]->PEBSAbsoluteMaximum = mMsrDsArea[Index]->PEBSBufferBase + PEBS_RECORD_NUMBER * sizeof(PEBS_RECORD) + 1;
+ mMsrDsArea[Index]->PEBSInterruptThreshold = mMsrDsArea[Index]->PEBSAbsoluteMaximum + 1;
+ }
+ }
+
+ mProtectionMemRange = mProtectionMemRangeTemplate;
+ mProtectionMemRangeCount = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);
+
+ //
+ // Update TSeg entry.
+ //
+ mProtectionMemRange[0].Range.Base = mCpuHotPlugData.SmrrBase;
+ mProtectionMemRange[0].Range.Top = mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize;
+
+ //
+ // Update SMM profile entry.
+ //
+ mProtectionMemRange[1].Range.Base = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase;
+ mProtectionMemRange[1].Range.Top = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase + TotalSize;
+
+ //
+ // Allocate memory reserved for creating 4KB pages.
+ //
+ InitPagesForPFHandler ();
+
+ //
+ // Start SMM profile when SmmReadyToLock protocol is installed.
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmReadyToLockProtocolGuid,
+ SmmProfileStartCallBack,
+ &Registration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return ;
+}
+
+/**
+ Check if XD feature is supported by a processor.
+
+**/
+VOID
+CheckFeatureSupported (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT32 RegEdx;
+
+ if (mXdSupported) {
+ AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax <= EFI_CPUID_EXTENDED_FUNCTION) {
+ //
+ // Entended CPUID functions are not supported on this processor.
+ //
+ mXdSupported = FALSE;
+ }
+
+ AsmCpuid (EFI_CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {
+ //
+ // Execute Disable Bit feature is not supported on this processor.
+ //
+ mXdSupported = FALSE;
+ }
+ }
+
+ if (mBtsSupported) {
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & CPUID1_EDX_BTS_AVAILABLE) != 0) {
+ //
+ // Per IA32 manuals:
+ // When CPUID.1:EDX[21] is set, the following BTS facilities are available:
+ // 1. The BTS_UNAVAILABLE flag in the IA32_MISC_ENABLE MSR indicates the
+ // availability of the BTS facilities, including the ability to set the BTS and
+ // BTINT bits in the MSR_DEBUGCTLA MSR.
+ // 2. The IA32_DS_AREA MSR can be programmed to point to the DS save area.
+ //
+ if ((AsmMsrBitFieldRead64 (MSR_IA32_MISC_ENABLE, 11, 11) == 0) &&
+ (AsmMsrBitFieldRead64 (MSR_IA32_MISC_ENABLE, 12, 12) == 0)) {
+ //
+ // BTS facilities is supported.
+ //
+ mBtsSupported = FALSE;
+ }
+ }
+ }
+}
+
+/**
+ Check if XD and BTS features are supported by all processors.
+
+ @param MpServices The MP services protocol.
+
+**/
+VOID
+CheckProcessorFeature (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ )
+{
+ mXdSupported = TRUE;
+ mBtsSupported = TRUE;
+
+ //
+ // Check if XD and BTS are supported on all processors.
+ //
+ CheckFeatureSupported ();
+
+ //
+ //Check on other processors if BSP supports this
+ //
+ if (mXdSupported || mBtsSupported) {
+ MpServices->StartupAllAPs (
+ MpServices,
+ (EFI_AP_PROCEDURE) CheckFeatureSupported,
+ TRUE,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ }
+}
+
+/**
+ Enable XD feature.
+
+**/
+VOID
+ActivateXd (
+ VOID
+ )
+{
+ UINT64 MsrRegisters;
+
+ MsrRegisters = AsmReadMsr64 (MSR_EFER);
+ if ((MsrRegisters & MSR_EFER_XD) != 0) {
+ return ;
+ }
+ MsrRegisters |= MSR_EFER_XD;
+ AsmWriteMsr64 (MSR_EFER, MsrRegisters);
+}
+
+/**
+ Enable single step.
+
+**/
+VOID
+ActivateSingleStepDB (
+ VOID
+ )
+{
+ UINTN Dr6;
+
+ Dr6 = AsmReadDr6 ();
+ if ((Dr6 & DR6_SINGLE_STEP) != 0) {
+ return;
+ }
+ Dr6 |= DR6_SINGLE_STEP;
+ AsmWriteDr6 (Dr6);
+}
+
+/**
+ Enable last branch.
+
+**/
+VOID
+ActivateLBR (
+ VOID
+ )
+{
+ UINT64 DebugCtl;
+
+ DebugCtl = AsmReadMsr64 (MSR_DEBUG_CTL);
+ if ((DebugCtl & MSR_DEBUG_CTL_LBR) != 0) {
+ return ;
+ }
+ AsmWriteMsr64 (MSR_LER_FROM_LIP, 0);
+ AsmWriteMsr64 (MSR_LER_TO_LIP, 0);
+ DebugCtl |= MSR_DEBUG_CTL_LBR;
+ AsmWriteMsr64 (MSR_DEBUG_CTL, DebugCtl);
+}
+
+/**
+ Enable branch trace store.
+
+ @param CpuIndex The index of the processor.
+
+**/
+VOID
+ActivateBTS (
+ IN UINTN CpuIndex
+ )
+{
+ UINT64 DebugCtl;
+
+ DebugCtl = AsmReadMsr64 (MSR_DEBUG_CTL);
+ if ((DebugCtl & MSR_DEBUG_CTL_BTS) != 0) {
+ return ;
+ }
+
+ AsmWriteMsr64 (MSR_DS_AREA, (UINT64)(UINTN)mMsrDsArea[CpuIndex]);
+ DebugCtl |= (MSR_DEBUG_CTL_BTS | MSR_DEBUG_CTL_TR);
+ DebugCtl &= ~MSR_DEBUG_CTL_BTINT;
+ AsmWriteMsr64 (MSR_DEBUG_CTL, DebugCtl);
+}
+
+/**
+ Increase SMI number in each SMI entry.
+
+**/
+VOID
+SmmProfileRecordSmiNum (
+ VOID
+ )
+{
+ if (mSmmProfileStart) {
+ mSmmProfileBase->NumSmis++;
+ }
+}
+
+/**
+ Initialize processor environment for SMM profile.
+
+ @param CpuIndex The index of the processor.
+
+**/
+VOID
+ActivateSmmProfile (
+ IN UINTN CpuIndex
+ )
+{
+ //
+ // Try to enable NX
+ //
+ if (mXdSupported) {
+ ActivateXd ();
+ }
+
+ //
+ // Enable Single Step DB#
+ //
+ ActivateSingleStepDB ();
+
+ if (mBtsSupported) {
+ //
+ // We can not get useful information from LER, so we have to use BTS.
+ //
+ ActivateLBR ();
+
+ //
+ // Enable BTS
+ //
+ ActivateBTS (CpuIndex);
+ }
+}
+
+/**
+ Initialize SMM profile in SMM CPU entrypoint.
+
+**/
+VOID
+InitSmmProfile (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_MP_SERVICES_PROTOCOL *MpServices;
+
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // First detect if XD and BTS are supported
+ //
+ CheckProcessorFeature (MpServices);
+
+ //
+ // Init SmmProfile here
+ //
+ InitSmmProfileInternal ();
+
+ //
+ // Init profile IDT.
+ //
+ InitIdtr ();
+
+ //
+ // Patch SmmS3ResumeState->SmmS3Cr3
+ //
+ InitSmmS3Cr3 ();
+}
+
+/**
+ Update page table to map the memory correctly in order to make the instruction
+ which caused page fault execute successfully. And it also save the original page
+ table to be restored in single-step exception.
+
+ @param PageTable PageTable Address.
+ @param PFAddress The memory address which caused page fault exception.
+ @param CpuIndex The index of the processor.
+ @param ErrorCode The Error code of exception.
+
+**/
+VOID
+RestorePageTableBelow4G (
+ UINT64 *PageTable,
+ UINT64 PFAddress,
+ UINTN CpuIndex,
+ UINTN ErrorCode
+ )
+{
+ UINTN PTIndex;
+ UINTN PFIndex;
+
+ //
+ // PML4
+ //
+ if (sizeof(UINT64) == sizeof(UINTN)) {
+ PTIndex = (UINTN)BitFieldRead64 (PFAddress, 39, 47);
+ ASSERT (PageTable[PTIndex] != 0);
+ PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
+ }
+
+ //
+ // PDPTE
+ //
+ PTIndex = (UINTN)BitFieldRead64 (PFAddress, 30, 38);
+ ASSERT (PageTable[PTIndex] != 0);
+ PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
+
+ //
+ // PD
+ //
+ PTIndex = (UINTN)BitFieldRead64 (PFAddress, 21, 29);
+ if ((PageTable[PTIndex] & IA32_PG_PS) != 0) {
+ //
+ // Large page
+ //
+
+ //
+ // Record old entries with non-present status
+ // Old entries include the memory which instruction is at and the memory which instruction access.
+ //
+ //
+ ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);
+ if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {
+ PFIndex = mPFEntryCount[CpuIndex];
+ mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];
+ mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];
+ mPFEntryCount[CpuIndex]++;
+ }
+
+ //
+ // Set new entry
+ //
+ PageTable[PTIndex] = (PFAddress & ~((1ull << 21) - 1));
+ PageTable[PTIndex] |= IA32_PG_PS;
+ PageTable[PTIndex] |= IA32_PG_RW | IA32_PG_P;
+ if ((ErrorCode & IA32_PF_EC_ID) != 0) {
+ PageTable[PTIndex] &= ~IA32_PG_NX;
+ }
+ } else {
+ //
+ // Small page
+ //
+ ASSERT (PageTable[PTIndex] != 0);
+ PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
+
+ //
+ // 4K PTE
+ //
+ PTIndex = (UINTN)BitFieldRead64 (PFAddress, 12, 20);
+
+ //
+ // Record old entries with non-present status
+ // Old entries include the memory which instruction is at and the memory which instruction access.
+ //
+ //
+ ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);
+ if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {
+ PFIndex = mPFEntryCount[CpuIndex];
+ mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];
+ mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];
+ mPFEntryCount[CpuIndex]++;
+ }
+
+ //
+ // Set new entry
+ //
+ PageTable[PTIndex] = (PFAddress & ~((1ull << 12) - 1));
+ PageTable[PTIndex] |= IA32_PG_RW | IA32_PG_P;
+ if ((ErrorCode & IA32_PF_EC_ID) != 0) {
+ PageTable[PTIndex] &= ~IA32_PG_NX;
+ }
+ }
+}
+
+/**
+ The Page fault handler to save SMM profile data.
+
+ @param Rip The RIP when exception happens.
+ @param ErrorCode The Error code of exception.
+
+**/
+VOID
+SmmProfilePFHandler (
+ UINTN Rip,
+ UINTN ErrorCode
+ )
+{
+ UINT64 *PageTable;
+ UINT64 PFAddress;
+ UINTN CpuIndex;
+ UINTN Index;
+ UINT64 InstructionAddress;
+ UINTN MaxEntryNumber;
+ UINTN CurrentEntryNumber;
+ BOOLEAN IsValidPFAddress;
+ SMM_PROFILE_ENTRY *SmmProfileEntry;
+ UINT64 SmiCommand;
+ EFI_STATUS Status;
+ UINTN SwSmiCpuIndex;
+ UINT8 SoftSmiValue;
+ EFI_SMM_SAVE_STATE_IO_INFO IoInfo;
+
+ if (!mSmmProfileStart) {
+ //
+ // If SMM profile does not start, call original page fault handler.
+ //
+ SmiDefaultPFHandler ();
+ return;
+ }
+
+ if (mBtsSupported) {
+ DisableBTS ();
+ }
+
+ IsValidPFAddress = FALSE;
+ PageTable = (UINT64 *)AsmReadCr3 ();
+ PFAddress = AsmReadCr2 ();
+ CpuIndex = GetCpuIndex ();
+
+ if (PFAddress <= 0xFFFFFFFF) {
+ RestorePageTableBelow4G (PageTable, PFAddress, CpuIndex, ErrorCode);
+ } else {
+ RestorePageTableAbove4G (PageTable, PFAddress, CpuIndex, ErrorCode, &IsValidPFAddress);
+ }
+
+ if (!IsValidPFAddress) {
+ InstructionAddress = Rip;
+ if ((ErrorCode & IA32_PF_EC_ID) != 0 && (mBtsSupported)) {
+ //
+ // If it is instruction fetch failure, get the correct IP from BTS.
+ //
+ InstructionAddress = GetSourceFromDestinationOnBts (CpuIndex, Rip);
+ if (InstructionAddress == 0) {
+ //
+ // It indicates the instruction which caused page fault is not a jump instruction,
+ // set instruction address same as the page fault address.
+ //
+ InstructionAddress = PFAddress;
+ }
+ }
+
+ //
+ // Try to find which CPU trigger SWSMI
+ //
+ SwSmiCpuIndex = 0;
+ //
+ // Indicate it is not software SMI
+ //
+ SmiCommand = 0xFFFFFFFFFFFFFFFFULL;
+ for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
+ Status = SmmReadSaveState(&mSmmCpu, sizeof(IoInfo), EFI_SMM_SAVE_STATE_REGISTER_IO, Index, &IoInfo);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (IoInfo.IoPort == mSmiCommandPort) {
+ //
+ // Great! Find it.
+ //
+ SwSmiCpuIndex = Index;
+ //
+ // A software SMI triggered by SMI command port has been found, get SmiCommand from SMI command port.
+ //
+ SoftSmiValue = IoRead8 (mSmiCommandPort);
+ SmiCommand = (UINT64)SoftSmiValue;
+ break;
+ }
+ }
+
+ SmmProfileEntry = (SMM_PROFILE_ENTRY *)(UINTN)(mSmmProfileBase + 1);
+ //
+ // Check if there is already a same entry in profile data.
+ //
+ for (Index = 0; Index < (UINTN) mSmmProfileBase->CurDataEntries; Index++) {
+ if ((SmmProfileEntry[Index].ErrorCode == (UINT64)ErrorCode) &&
+ (SmmProfileEntry[Index].Address == PFAddress) &&
+ (SmmProfileEntry[Index].CpuNum == (UINT64)CpuIndex) &&
+ (SmmProfileEntry[Index].Instruction == InstructionAddress) &&
+ (SmmProfileEntry[Index].SmiCmd == SmiCommand)) {
+ //
+ // Same record exist, need not save again.
+ //
+ break;
+ }
+ }
+ if (Index == mSmmProfileBase->CurDataEntries) {
+ CurrentEntryNumber = (UINTN) mSmmProfileBase->CurDataEntries;
+ MaxEntryNumber = (UINTN) mSmmProfileBase->MaxDataEntries;
+ if (FeaturePcdGet (PcdCpuSmmProfileRingBuffer)) {
+ CurrentEntryNumber = CurrentEntryNumber % MaxEntryNumber;
+ }
+ if (CurrentEntryNumber < MaxEntryNumber) {
+ //
+ // Log the new entry
+ //
+ SmmProfileEntry[CurrentEntryNumber].SmiNum = mSmmProfileBase->NumSmis;
+ SmmProfileEntry[CurrentEntryNumber].ErrorCode = (UINT64)ErrorCode;
+ SmmProfileEntry[CurrentEntryNumber].ApicId = (UINT64)GetApicId ();
+ SmmProfileEntry[CurrentEntryNumber].CpuNum = (UINT64)CpuIndex;
+ SmmProfileEntry[CurrentEntryNumber].Address = PFAddress;
+ SmmProfileEntry[CurrentEntryNumber].Instruction = InstructionAddress;
+ SmmProfileEntry[CurrentEntryNumber].SmiCmd = SmiCommand;
+ //
+ // Update current entry index and data size in the header.
+ //
+ mSmmProfileBase->CurDataEntries++;
+ mSmmProfileBase->CurDataSize = MultU64x64 (mSmmProfileBase->CurDataEntries, sizeof (SMM_PROFILE_ENTRY));
+ }
+ }
+ }
+ //
+ // Flush TLB
+ //
+ CpuFlushTlb ();
+
+ if (mBtsSupported) {
+ EnableBTS ();
+ }
+}
+
+/**
+ Replace INT1 exception handler to restore page table to absent/execute-diable state
+ in order to trigger page fault again to save SMM profile data..
+
+**/
+VOID
+InitIdtr (
+ VOID
+ )
+{
+ SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_DEBUG, DebugExceptionHandler);
+}
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfile.h b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfile.h
new file mode 100644
index 0000000..0ef13c8
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfile.h
@@ -0,0 +1,83 @@
+/** @file
+ SMM profile header file.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SMM_PROFILE_H_
+#define _SMM_PROFILE_H_
+
+//
+// External functions
+//
+
+/**
+ Initialize processor environment for SMM profile.
+
+ @param CpuIndex The index of the processor.
+
+**/
+VOID
+ActivateSmmProfile (
+ IN UINTN CpuIndex
+ );
+
+/**
+ Initialize SMM profile in SMM CPU entrypoint.
+
+**/
+VOID
+InitSmmProfile (
+ VOID
+ );
+
+/**
+ Increase SMI number in each SMI entry.
+
+**/
+VOID
+SmmProfileRecordSmiNum (
+ VOID
+ );
+
+/**
+ The Page fault handler to save SMM profile data.
+
+ @param Rip The RIP when exception happens.
+ @param ErrorCode The Error code of exception.
+
+**/
+VOID
+SmmProfilePFHandler (
+ UINTN Rip,
+ UINTN ErrorCode
+ );
+
+#endif // _SMM_PROFILE_H_
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfileInternal.h b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfileInternal.h
new file mode 100644
index 0000000..7983490
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SmmProfileInternal.h
@@ -0,0 +1,184 @@
+/** @file
+ SMM profile internal header file.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SMM_PROFILE_INTERNAL_H_
+#define _SMM_PROFILE_INTERNAL_H_
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/Acpi.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/CpuLib.h>
+#include <IndustryStandard/Acpi.h>
+
+#include "SmmProfileArch.h"
+
+//
+// Config the SMM_PROFILE DTS region size
+//
+#define SMM_PROFILE_DTS_SIZE (4 * 1024 * 1024) // 4M
+
+#define MAX_PF_PAGE_COUNT 0x2
+
+#define PEBS_RECORD_NUMBER 0x2
+
+#define MAX_PF_ENTRY_COUNT 10
+
+//
+// This MACRO just enable unit test for the profile
+// Please disable it.
+//
+
+#define IA32_PF_EC_P (1u << 0)
+#define IA32_PF_EC_WR (1u << 1)
+#define IA32_PF_EC_US (1u << 2)
+#define IA32_PF_EC_RSVD (1u << 3)
+#define IA32_PF_EC_ID (1u << 4)
+
+#define SMM_PROFILE_NAME L"SmmProfileData"
+
+//
+// CPU generic definition
+//
+#define IA32_PG_NX (1ll << 63)
+
+#define IA32_CPUID_SS 0x08000000
+
+#define CPUID1_EDX_XD_SUPPORT 0x100000
+#define MSR_EFER 0xc0000080
+#define MSR_EFER_XD 0x800
+
+#define CPUID1_EDX_BTS_AVAILABLE 0x200000
+
+#define DR6_SINGLE_STEP 0x4000
+#define RFLAG_TF 0x100
+
+#define MSR_DEBUG_CTL 0x1D9
+#define MSR_DEBUG_CTL_LBR 0x1
+#define MSR_DEBUG_CTL_TR 0x40
+#define MSR_DEBUG_CTL_BTS 0x80
+#define MSR_DEBUG_CTL_BTINT 0x100
+#define MSR_LASTBRANCH_TOS 0x1C9
+#define MSR_LER_FROM_LIP 0x1DD
+#define MSR_LER_TO_LIP 0x1DE
+#define MSR_DS_AREA 0x600
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS Base;
+ EFI_PHYSICAL_ADDRESS Top;
+} MEMORY_RANGE;
+
+typedef struct {
+ MEMORY_RANGE Range;
+ BOOLEAN Present;
+ BOOLEAN Nx;
+} MEMORY_PROTECTION_RANGE;
+
+typedef struct {
+ UINT64 HeaderSize;
+ UINT64 MaxDataEntries;
+ UINT64 MaxDataSize;
+ UINT64 CurDataEntries;
+ UINT64 CurDataSize;
+ UINT64 TsegStart;
+ UINT64 TsegSize;
+ UINT64 NumSmis;
+ UINT64 NumCpus;
+} SMM_PROFILE_HEADER;
+
+typedef struct {
+ UINT64 SmiNum;
+ UINT64 CpuNum;
+ UINT64 ApicId;
+ UINT64 ErrorCode;
+ UINT64 Instruction;
+ UINT64 Address;
+ UINT64 SmiCmd;
+} SMM_PROFILE_ENTRY;
+
+extern SMM_S3_RESUME_STATE *mSmmS3ResumeState;
+extern UINTN gSmiExceptionHandlers[];
+extern BOOLEAN mXdSupported;
+extern UINTN mPFEntryCount[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];
+extern UINT64 mLastPFEntryValue[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)][MAX_PF_ENTRY_COUNT];
+extern UINT64 *mLastPFEntryPointer[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)][MAX_PF_ENTRY_COUNT];
+
+//
+// Internal functions
+//
+
+/**
+ Update IDT table to replace page fault handler and INT 1 handler.
+
+**/
+VOID
+InitIdtr (
+ VOID
+ );
+
+/**
+ Check if the memory address will be mapped by 4KB-page.
+
+ @param Address The address of Memory.
+
+**/
+BOOLEAN
+IsAddressSplit (
+ IN EFI_PHYSICAL_ADDRESS Address
+ );
+
+/**
+ Check if the memory address will be mapped by 4KB-page.
+
+ @param Address The address of Memory.
+ @param Nx The flag indicates if the memory is execute-disable.
+
+**/
+BOOLEAN
+IsAddressValid (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN BOOLEAN *Nx
+ );
+
+/**
+ Page Fault handler for SMM use.
+
+**/
+VOID
+EFIAPI
+SmiDefaultPFHandler (
+ VOID
+ );
+
+#endif // _SMM_PROFILE_H_
diff --git a/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SyncTimer.c b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SyncTimer.c
new file mode 100644
index 0000000..ccf3983
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/SyncTimer.c
@@ -0,0 +1,130 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PiSmmCpuDxeSmm.h"
+
+UINT64 mTimeoutTicker = 0;
+//
+// Number of counts in a roll-over cycle of the performance counter.
+//
+UINT64 mCycle = 0;
+//
+// Flag to indicate the performance counter is count-up or count-down.
+//
+BOOLEAN mCountDown;
+
+/**
+ Initialize Timer for Smm AP Sync.
+
+**/
+VOID
+InitializeSmmTimer (
+ VOID
+ )
+{
+ UINT64 TimerFrequency;
+ UINT64 Start;
+ UINT64 End;
+
+ TimerFrequency = GetPerformanceCounterProperties (&Start, &End);
+ mTimeoutTicker = DivU64x32 (
+ MultU64x64(TimerFrequency, PcdGet64 (PcdCpuSmmApSyncTimeout)),
+ 1000 * 1000
+ );
+ if (End < Start) {
+ mCountDown = TRUE;
+ mCycle = Start - End;
+ } else {
+ mCountDown = FALSE;
+ mCycle = End - Start;
+ }
+}
+
+/**
+ Start Timer for Smm AP Sync.
+
+**/
+UINT64
+EFIAPI
+StartSyncTimer (
+ VOID
+ )
+{
+ return GetPerformanceCounter ();
+}
+
+
+/**
+ Check if the Smm AP Sync timer is timeout.
+
+ @param Timer The start timer from the begin.
+
+**/
+BOOLEAN
+EFIAPI
+IsSyncTimerTimeout (
+ IN UINT64 Timer
+ )
+{
+ UINT64 CurrentTimer;
+ UINT64 Delta;
+
+ CurrentTimer = GetPerformanceCounter ();
+
+ if (mCountDown) {
+ //
+ // The performance counter counts down. Check for roll over condition.
+ //
+ if (CurrentTimer < Timer) {
+ Delta = Timer - CurrentTimer;
+ } else {
+ //
+ // Handle one roll-over.
+ //
+ Delta = mCycle - (CurrentTimer - Timer);
+ }
+ } else {
+ //
+ // The performance counter counts up. Check for roll over condition.
+ //
+ if (CurrentTimer > Timer) {
+ Delta = CurrentTimer - Timer;
+ } else {
+ //
+ // Handle one roll-over.
+ //
+ Delta = mCycle - (Timer - CurrentTimer);
+ }
+ }
+
+ return (BOOLEAN) (Delta >= mTimeoutTicker);
+}
diff --git a/IA32FamilyCpuBasePkg/SecCore/FindPeiCore.c b/IA32FamilyCpuBasePkg/SecCore/FindPeiCore.c
new file mode 100644
index 0000000..fc31532
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/FindPeiCore.c
@@ -0,0 +1,218 @@
+/** @file
+ Locate the entry point for the PEI Core
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+
+#include "SecMain.h"
+
+/**
+ Find core image base.
+
+ @param BootFirmwareVolumePtr Point to the boot firmware volume.
+ @param SecCoreImageBase The base address of the SEC core image.
+ @param PeiCoreImageBase The base address of the PEI core image.
+
+**/
+EFI_STATUS
+EFIAPI
+FindImageBase (
+ IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
+ OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase,
+ OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
+ )
+{
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
+ EFI_FFS_FILE_HEADER *File;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfFile;
+ EFI_COMMON_SECTION_HEADER *Section;
+ EFI_PHYSICAL_ADDRESS EndOfSection;
+
+ *SecCoreImageBase = 0;
+ *PeiCoreImageBase = 0;
+
+ CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
+ EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
+
+ //
+ // Loop through the FFS files in the Boot Firmware Volume
+ //
+ for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
+
+ CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
+ if (CurrentAddress > EndOfFirmwareVolume) {
+ return EFI_NOT_FOUND;
+ }
+
+ File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
+ if (IS_FFS_FILE2 (File)) {
+ Size = FFS_FILE2_SIZE (File);
+ if (Size <= 0x00FFFFFF) {
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ Size = FFS_FILE_SIZE (File);
+ if (Size < sizeof (EFI_FFS_FILE_HEADER)) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ EndOfFile = CurrentAddress + Size;
+ if (EndOfFile > EndOfFirmwareVolume) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Look for SEC Core / PEI Core files
+ //
+ if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
+ File->Type != EFI_FV_FILETYPE_PEI_CORE) {
+ continue;
+ }
+
+ //
+ // Loop through the FFS file sections within the FFS file
+ //
+ if (IS_FFS_FILE2 (File)) {
+ EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER2));
+ } else {
+ EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER));
+ }
+ for (;;) {
+ CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
+ Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
+
+ if (IS_SECTION2 (Section)) {
+ Size = SECTION2_SIZE (Section);
+ if (Size <= 0x00FFFFFF) {
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ Size = SECTION_SIZE (Section);
+ if (Size < sizeof (EFI_COMMON_SECTION_HEADER)) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ EndOfSection = CurrentAddress + Size;
+ if (EndOfSection > EndOfFile) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Look for executable sections
+ //
+ if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
+ if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
+ if (IS_SECTION2 (Section)) {
+ *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
+ } else {
+ *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
+ }
+ } else {
+ if (IS_SECTION2 (Section)) {
+ *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
+ } else {
+ *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
+ }
+ }
+ break;
+ }
+ }
+
+ //
+ // Both SEC Core and PEI Core images found
+ //
+ if (*SecCoreImageBase != 0 && *PeiCoreImageBase != 0) {
+ return EFI_SUCCESS;
+ }
+ }
+}
+
+/**
+ Find and return Pei Core entry point.
+
+ It also find SEC and PEI Core file debug inforamtion. It will report them if
+ remote debug is enabled.
+
+ @param BootFirmwareVolumePtr Point to the boot firmware volume.
+ @param PeiCoreEntryPoint The entry point of the PEI core.
+
+**/
+VOID
+EFIAPI
+FindAndReportEntryPoints (
+ IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
+ OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS SecCoreImageBase;
+ EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ //
+ // Find SEC Core and PEI Core image base
+ //
+ Status = FindImageBase (BootFirmwareVolumePtr, &SecCoreImageBase, &PeiCoreImageBase);
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+ //
+ // Report SEC Core debug information when remote debug is enabled
+ //
+ ImageContext.ImageAddress = SecCoreImageBase;
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+ //
+ // Report PEI Core debug information when remote debug is enabled
+ //
+ ImageContext.ImageAddress = PeiCoreImageBase;
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+ //
+ // Find PEI Core entry point
+ //
+ Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
+ if (EFI_ERROR (Status)) {
+ *PeiCoreEntryPoint = 0;
+ }
+
+ return;
+}
+
diff --git a/IA32FamilyCpuBasePkg/SecCore/Ia32/ResetVec.S16 b/IA32FamilyCpuBasePkg/SecCore/Ia32/ResetVec.S16
new file mode 100644
index 0000000..f83f5fe
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/Ia32/ResetVec.S16
@@ -0,0 +1,116 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# ResetVec.S16
+#
+# Abstract:
+#
+# Reset Vector Data structure
+# This structure is located at 0xFFFFFFD0
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX (_start)
+ASM_PFX(_start):
+
+#
+# FIT table pointer for LT-SX.
+#
+FitTablePointer:
+ .long 0xeeeeeeee, 0xeeeeeeee
+
+ .align 16
+
+#
+# This is located at 0xFFFFFFD0h
+#
+ .byte 0xBF, 0x50, 0x41 # mov di, "AP"
+ jmp ApStartup
+ .fill PeiCoreEntryPoint - ., 1, 0
+
+ .align 16
+#
+# 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:
+ .long 0x87654321
+
+#
+# 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:
+ jmp .
+ iret
+ .fill ResetHandler - ., 1, 0
+
+ .align 16
+#
+# For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
+# Execution starts here upon power-on/platform-reset.
+#
+ResetHandler:
+ wbinvd
+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.
+ #
+ # Typically, SEC entry point is the function _ModuleEntryPoint() defined in
+ # SecEntry.asm
+ #
+ .byte 0xe9
+ .word -3
+ .fill ApSegAddress - ., 1, 0
+
+ .align 8
+#
+# 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:
+ .long 0x12345678
+
+#
+# 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:
+ .long 0x12345678
diff --git a/IA32FamilyCpuBasePkg/SecCore/Ia32/ResetVec.asm16 b/IA32FamilyCpuBasePkg/SecCore/Ia32/ResetVec.asm16
new file mode 100644
index 0000000..63db4f8
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/Ia32/ResetVec.asm16
@@ -0,0 +1,125 @@
+; -----------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; ResetVec.asm
+;
+; Abstract:
+;
+; Reset Vector Data structure
+; This structure is located at 0xFFFFFFC0
+;
+;------------------------------------------------------------------------------
+
+ .model tiny
+ .686p
+ .stack 0h
+ .code
+
+;
+; The layout of this file is fixed. The build tool makes assumption of the layout.
+;
+
+ 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.
+ ;
+ ; Typically, SEC entry point is the function _ModuleEntryPoint() defined in
+ ; SecEntry.asm
+ ;
+ 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
+
+;
+; Nothing can go here, otherwise the layout of this file would change.
+;
+
+ END
diff --git a/IA32FamilyCpuBasePkg/SecCore/Ia32/Stack.S b/IA32FamilyCpuBasePkg/SecCore/Ia32/Stack.S
new file mode 100644
index 0000000..0ea2e8a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/Ia32/Stack.S
@@ -0,0 +1,97 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Abstract:
+#
+# Switch the stack from temporary memory to permenent memory.
+#
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+# VOID
+# EFIAPI
+# SecSwitchStack (
+# UINT32 TemporaryMemoryBase,
+# UINT32 PermenentMemoryBase
+# )#
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX (SecSwitchStack)
+ASM_PFX(SecSwitchStack):
+ #
+ # Save standard registers so they can be used to change stack
+ #
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+
+ #
+ # !!CAUTION!! this function address's is pushed into stack after
+ # migration of whole temporary memory, so need save it to permenent
+ # memory at first!
+ #
+ movl 20(%esp), %ebx # Save the first parameter
+ movl 24(%esp), %ecx # Save the second parameter
+
+ #
+ # Save this function's return address into permenent memory at first.
+ # Then, Fixup the esp point to permenent memory
+ #
+ movl %esp, %eax
+ subl %ebx, %eax
+ addl %ecx, %eax
+ movl 0(%esp), %edx # copy pushed register's value to permenent memory
+ movl %edx, 0(%eax)
+ movl 4(%esp), %edx
+ movl %edx, 4(%eax)
+ movl 8(%esp), %edx
+ movl %edx, 8(%eax)
+ movl 12(%esp), %edx
+ movl %edx, 12(%eax)
+ movl 16(%esp), %edx # Update this function's return address into permenent memory
+ movl %edx, 16(%eax)
+ movl %eax, %esp # From now, esp is pointed to permenent memory
+
+ #
+ # Fixup the ebp point to permenent memory
+ #
+ movl %ebp, %eax
+ subl %ebx, %eax
+ addl %ecx, %eax
+ movl %eax, %ebp # From now, ebp is pointed to permenent memory
+
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %eax
+ ret
+
+
diff --git a/IA32FamilyCpuBasePkg/SecCore/Ia32/Stack.asm b/IA32FamilyCpuBasePkg/SecCore/Ia32/Stack.asm
new file mode 100644
index 0000000..3066133
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/Ia32/Stack.asm
@@ -0,0 +1,101 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Abstract:
+;
+; Switch the stack from temporary memory to permenent memory.
+;
+;------------------------------------------------------------------------------
+
+ .586p
+ .model flat,C
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; SecSwitchStack (
+; UINT32 TemporaryMemoryBase,
+; UINT32 PermenentMemoryBase
+; );
+;------------------------------------------------------------------------------
+SecSwitchStack PROC
+ ;
+ ; Save three register: eax, ebx, ecx
+ ;
+ push eax
+ push ebx
+ push ecx
+ push edx
+
+ ;
+ ; !!CAUTION!! this function address's is pushed into stack after
+ ; migration of whole temporary memory, so need save it to permenent
+ ; memory at first!
+ ;
+
+ mov ebx, [esp + 20] ; Save the first parameter
+ mov ecx, [esp + 24] ; Save the second parameter
+
+ ;
+ ; Save this function's return address into permenent memory at first.
+ ; Then, Fixup the esp point to permenent memory
+ ;
+ mov eax, esp
+ sub eax, ebx
+ add eax, ecx
+ mov edx, dword ptr [esp] ; copy pushed register's value to permenent memory
+ mov dword ptr [eax], edx
+ mov edx, dword ptr [esp + 4]
+ mov dword ptr [eax + 4], edx
+ mov edx, dword ptr [esp + 8]
+ mov dword ptr [eax + 8], edx
+ mov edx, dword ptr [esp + 12]
+ mov dword ptr [eax + 12], edx
+ mov edx, dword ptr [esp + 16] ; Update this function's return address into permenent memory
+ mov dword ptr [eax + 16], edx
+ mov esp, eax ; From now, esp is pointed to permenent memory
+
+ ;
+ ; Fixup the ebp point to permenent memory
+ ;
+ mov eax, ebp
+ sub eax, ebx
+ add eax, ecx
+ mov ebp, eax ; From now, ebp is pointed to permenent memory
+
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ ret
+SecSwitchStack ENDP
+
+ END
diff --git a/IA32FamilyCpuBasePkg/SecCore/SecCore.inf b/IA32FamilyCpuBasePkg/SecCore/SecCore.inf
new file mode 100644
index 0000000..108a4d8
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/SecCore.inf
@@ -0,0 +1,90 @@
+## @file
+# This is the first module taking control of the platform upon power-on/reset.
+#
+# This module implements the first phase of Tiano - SEC. SecEntry.asm contains the entry point of this module.
+# Blank1.pad and Blank2.pad file tagged with "ToolCode="DUMMY"" is for adjusting alignment of VTF section.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecCore
+ FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ SecMain.c
+ SecMain.h
+ FindPeiCore.c
+
+[Sources.IA32]
+ Ia32/ResetVec.asm16 | MSFT
+ Ia32/ResetVec.asm16 | INTEL
+ Ia32/ResetVec.S16 | GCC
+ Ia32/Stack.asm
+ Ia32/Stack.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ PlatformSecLib
+ PcdLib
+ DebugAgentLib
+ UefiCpuLib
+ PeCoffGetEntryPointLib
+ PeCoffExtraActionLib
+ ReportStatusCodeLib
+
+[Ppis]
+ gEfiSecPlatformInformationPpiGuid # PPI ALWAYS_PRODUCED
+ gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
+
+[FixedPcd]
+ gEfiCpuTokenSpaceGuid.PcdSecCoreMaxPpiSupported
+
+[Pcd]
+ gEfiCpuTokenSpaceGuid.PcdPeiTemporaryRamStackSize
+
diff --git a/IA32FamilyCpuBasePkg/SecCore/SecMain.c b/IA32FamilyCpuBasePkg/SecCore/SecMain.c
new file mode 100644
index 0000000..e7d50cb
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/SecMain.c
@@ -0,0 +1,400 @@
+/** @file
+ C funtions in SEC
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+
+#include "SecMain.h"
+
+
+EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
+ SecTemporaryRamSupport
+};
+
+EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { SecPlatformInformation };
+
+
+EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiTemporaryRamSupportPpiGuid,
+ &gSecTemporaryRamSupportPpi
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiSecPlatformInformationPpiGuid,
+ &mSecPlatformInformationPpi
+ }
+};
+
+
+//
+// These are IDT entries pointing to 10:FFFFFFE4h.
+//
+UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL;
+
+/**
+ Caller provided function to be invoked at the end of InitializeDebugAgent().
+
+ 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] Context The first input parameter of InitializeDebugAgent().
+
+**/
+VOID
+EFIAPI
+SecStartupPhase2(
+ IN VOID *Context
+ );
+
+
+/**
+
+ 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 SizeOfRam Size of the temporary memory available for use.
+ @param TempRamBase Base address of tempory ram
+ @param BootFirmwareVolume Base address of the Boot Firmware Volume.
+**/
+VOID
+EFIAPI
+SecStartup (
+ IN UINT32 SizeOfRam,
+ IN UINT32 TempRamBase,
+ IN VOID *BootFirmwareVolume
+ )
+{
+ EFI_SEC_PEI_HAND_OFF SecCoreData;
+ IA32_DESCRIPTOR IdtDescriptor;
+ SEC_IDT_TABLE IdtTableInStack;
+ UINT32 Index;
+ UINT32 PeiStackSize;
+
+ //
+ // Report Status Code to indicate entering SEC core
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_ENTRY_POINT
+ );
+
+ PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize);
+ if (PeiStackSize == 0) {
+ PeiStackSize = (SizeOfRam >> 1);
+ }
+
+ ASSERT (PeiStackSize < SizeOfRam);
+
+ //
+ // Process all libraries constructor function linked to SecCore.
+ //
+ ProcessLibraryConstructorList ();
+
+ //
+ // Initialize floating point operating environment
+ // to be compliant with UEFI spec.
+ //
+ InitializeFloatingPointUnits ();
+
+
+ // |-------------------|---->
+ // |Idt Table |
+ // |-------------------|
+ // |PeiService Pointer | PeiStackSize
+ // |-------------------|
+ // | |
+ // | Stack |
+ // |-------------------|---->
+ // | |
+ // | |
+ // | Heap | PeiTemporayRamSize
+ // | |
+ // | |
+ // |-------------------|----> TempRamBase
+
+ IdtTableInStack.PeiService = 0;
+ for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
+ CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));
+ }
+
+ IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
+ IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
+
+ AsmWriteIdtr (&IdtDescriptor);
+
+ //
+ // Update the base address and length of Pei temporary memory
+ //
+ SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);
+ SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
+ SecCoreData.BootFirmwareVolumeSize = (UINTN)(0x100000000ULL - (UINTN) BootFirmwareVolume);
+ SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
+ SecCoreData.TemporaryRamSize = SizeOfRam;
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+ SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;
+ SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
+ SecCoreData.StackSize = PeiStackSize;
+
+ //
+ // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
+
+}
+
+/**
+ Caller provided function to be invoked at the end of InitializeDebugAgent().
+
+ 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] Context The first input parameter of InitializeDebugAgent().
+
+**/
+VOID
+EFIAPI
+SecStartupPhase2(
+ IN VOID *Context
+ )
+{
+ EFI_SEC_PEI_HAND_OFF *SecCoreData;
+ EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ UINT32 Index;
+ EFI_PEI_PPI_DESCRIPTOR AllSecPpiList[FixedPcdGet32(PcdSecCoreMaxPpiSupported)];
+ EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
+
+ SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
+ //
+ // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
+ // is enabled.
+ //
+ FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint);
+ if (PeiCoreEntryPoint == NULL)
+ {
+ CpuDeadLoop ();
+ }
+
+ //
+ // Perform platform specific initialization before entering PeiCore.
+ //
+ PpiList = SecPlatformMain (SecCoreData);
+ if (PpiList != NULL) {
+ //
+ // Remove the terminal flag from the terminal Ppi
+ //
+ CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));
+ for (Index = 0; Index < PcdGet32 (PcdSecCoreMaxPpiSupported); Index ++) {
+ if ((AllSecPpiList[Index].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
+ break;
+ }
+ }
+ AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+
+ //
+ // Append the platform additional Ppi list
+ //
+ Index += 1;
+ while (Index < PcdGet32 (PcdSecCoreMaxPpiSupported) &&
+ ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {
+ CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ Index++;
+ PpiList++;
+ }
+
+ //
+ // Check whether the total Ppis exceeds the max supported Ppi.
+ //
+ if (Index >= PcdGet32 (PcdSecCoreMaxPpiSupported)) {
+ //
+ // the total Ppi is larger than the supported Max
+ // PcdSecCoreMaxPpiSupported can be enlarged to solve it.
+ //
+ CpuDeadLoop ();
+ } else {
+ //
+ // Add the terminal Ppi
+ //
+ CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ }
+
+ //
+ // Set PpiList to the total Ppi
+ //
+ PpiList = &AllSecPpiList[0];
+ } else {
+ //
+ // No addition Ppi, PpiList directly point to the common Ppi list.
+ //
+ PpiList = &mPeiSecPlatformInformationPpi[0];
+ }
+
+ //
+ // Report Status Code to indicate transferring to PEI core
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT
+ );
+
+ //
+ // Transfer the control to the PEI core
+ //
+ ASSERT (PeiCoreEntryPoint != NULL);
+ (*PeiCoreEntryPoint) (SecCoreData, PpiList);
+
+ //
+ // Should not come here.
+ //
+ return ;
+}
+
+/**
+ This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupport (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ )
+{
+ IA32_DESCRIPTOR IdtDescriptor;
+ VOID* OldHeap;
+ VOID* NewHeap;
+ VOID* OldStack;
+ VOID* NewStack;
+ DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
+ BOOLEAN OldStatus;
+ UINTN PeiStackSize;
+
+ PeiStackSize = (UINTN)PcdGet32 (PcdPeiTemporaryRamStackSize);
+ if (PeiStackSize == 0) {
+ PeiStackSize = (CopySize >> 1);
+ }
+
+ ASSERT (PeiStackSize < CopySize);
+
+ //
+ // |-------------------|---->
+ // | Stack | PeiStackSize
+ // |-------------------|---->
+ // | Heap | PeiTemporayRamSize
+ // |-------------------|----> TempRamBase
+ //
+ // |-------------------|---->
+ // | Heap | PeiTemporayRamSize
+ // |-------------------|---->
+ // | Stack | PeiStackSize
+ // |-------------------|----> PermanentMemoryBase
+ //
+
+ OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
+ NewHeap = (VOID*)((UINTN)PermanentMemoryBase + PeiStackSize);
+
+ OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize - PeiStackSize);
+ NewStack = (VOID*)(UINTN)PermanentMemoryBase;
+
+ DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
+ DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
+
+ OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
+ //
+ // Initialize Debug Agent to support source level debug in PEI phase after memory ready.
+ // It will build HOB and fix up the pointer in IDT table.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
+
+ //
+ // Migrate Heap
+ //
+ CopyMem (NewHeap, OldHeap, CopySize - PeiStackSize);
+
+ //
+ // Migrate Stack
+ //
+ CopyMem (NewStack, OldStack, PeiStackSize);
+
+
+ //
+ // We need *not* fix the return address because currently,
+ // The PeiCore is executed in flash.
+ //
+
+ //
+ // Rebase IDT table in permanent memory
+ //
+ AsmReadIdtr (&IdtDescriptor);
+ IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
+
+ AsmWriteIdtr (&IdtDescriptor);
+
+
+ //
+ // Program MTRR
+ //
+
+ //
+ // SecSwitchStack function must be invoked after the memory migration
+ // immediatly, also we need fixup the stack change caused by new call into
+ // permenent memory.
+ //
+ SecSwitchStack (
+ (UINT32) (UINTN) OldStack,
+ (UINT32) (UINTN) NewStack
+ );
+
+ SaveAndSetDebugTimerInterrupt (OldStatus);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/IA32FamilyCpuBasePkg/SecCore/SecMain.h b/IA32FamilyCpuBasePkg/SecCore/SecMain.h
new file mode 100644
index 0000000..b8dbd4d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/SecMain.h
@@ -0,0 +1,154 @@
+/** @file
+ Master header file for SecCore.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SEC_CORE_H_
+#define _SEC_CORE_H_
+
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/TemporaryRamSupport.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PlatformSecLib.h>
+#include <Library/UefiCpuLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+#define SEC_IDT_ENTRY_COUNT 34
+
+typedef struct _SEC_IDT_TABLE {
+ //
+ // Reserved 8 bytes preceding IDT to store EFI_PEI_SERVICES**, since IDT base
+ // address should be 8-byte alignment.
+ // Note: For IA32, only the 4 bytes immediately preceding IDT is used to store
+ // EFI_PEI_SERVICES**
+ //
+ UINT64 PeiService;
+ UINT64 IdtTable[SEC_IDT_ENTRY_COUNT];
+} SEC_IDT_TABLE;
+
+/**
+ Switch the stack in the temporary memory to the one in the permanent memory.
+
+ This function must be invoked after the memory migration immediately. The relative
+ position of the stack in the temporary and permanent memory is same.
+
+ @param TemporaryMemoryBase Base address of the temporary memory.
+ @param PermenentMemoryBase Base address of the permanent memory.
+**/
+VOID
+EFIAPI
+SecSwitchStack (
+ UINT32 TemporaryMemoryBase,
+ UINT32 PermenentMemoryBase
+ );
+
+/**
+ This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupport (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+/**
+ 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 SizeOfRam Size of the temporary memory available for use.
+ @param TempRamBase Base address of tempory ram
+ @param BootFirmwareVolume Base address of the Boot Firmware Volume.
+**/
+VOID
+EFIAPI
+SecStartup (
+ IN UINT32 SizeOfRam,
+ IN UINT32 TempRamBase,
+ IN VOID *BootFirmwareVolume
+ );
+
+/**
+ Find and return Pei Core entry point.
+
+ It also find SEC and PEI Core file debug inforamtion. It will report them if
+ remote debug is enabled.
+
+ @param BootFirmwareVolumePtr Point to the boot firmware volume.
+ @param PeiCoreEntryPoint Point to the PEI core entry point.
+
+**/
+VOID
+EFIAPI
+FindAndReportEntryPoints (
+ IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
+ OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
+ );
+
+/**
+ Autogenerated function that calls the library constructors for all of the module's
+ dependent libraries. This function must be called by the SEC Core once a stack has
+ been established.
+
+**/
+VOID
+EFIAPI
+ProcessLibraryConstructorList (
+ VOID
+ );
+
+#endif
diff --git a/IA32FamilyCpuBasePkg/SecCore/Vtf0SecCore.inf b/IA32FamilyCpuBasePkg/SecCore/Vtf0SecCore.inf
new file mode 100644
index 0000000..1a234a9
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/SecCore/Vtf0SecCore.inf
@@ -0,0 +1,86 @@
+## @file
+# This is the first module taking control of the platform upon power-on/reset.
+#
+# This module implements the first phase of Tiano - SEC. SecEntry.asm contains the entry point of this module.
+# Blank1.pad and Blank2.pad file tagged with "ToolCode="DUMMY"" is for adjusting alignment of VTF section.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecCore
+ FILE_GUID = 2e7472a2-d7bf-4f5e-8fe4-bf19247856d0
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ FindPeiCore.c
+ SecMain.c
+ SecMain.h
+
+[Sources.IA32]
+ Ia32/Stack.asm
+ Ia32/Stack.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugAgentLib
+ DebugLib
+ PcdLib
+ PeCoffExtraActionLib
+ PeCoffGetEntryPointLib
+ PlatformSecLib
+ UefiCpuLib
+ ReportStatusCodeLib
+
+[Ppis]
+ gEfiSecPlatformInformationPpiGuid # PPI ALWAYS_PRODUCED
+ gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
+
+[FixedPcd]
+ gEfiCpuTokenSpaceGuid.PcdSecCoreMaxPpiSupported
+
+[Pcd]
+ gEfiCpuTokenSpaceGuid.PcdPeiTemporaryRamStackSize
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c4f01cb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2013 Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf b/QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf
new file mode 100644
index 0000000..b8b25cd
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf
@@ -0,0 +1,66 @@
+## @file
+# Component description file for PlatformAcpiTable module.
+#
+# Build acpi table data required by system boot.
+# All .asi files tagged with "ToolCode="DUMMY"" in following
+# file list are device description and are included by top
+# level ASL file which will be dealed with by asl.exe application.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiTables
+ FILE_GUID = 7E374E25-8E01-4FEE-87F2-390C23C606CD
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ Facs/Facs.aslc
+ Fadt/Fadt2.0.aslc
+ Hpet/Hpet.aslc
+ Mcfg/Mcfg.aslc
+ Dsdt/Platform.asl
+ CpuPm/CpuPm.asl
+ Cpu0Cst/Cpu0Cst.asl
+ Cpu0Ist/Cpu0Ist.asl
+ Cpu0Tst/Cpu0Tst.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Cst/Cpu0Cst.asl b/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Cst/Cpu0Cst.asl
new file mode 100644
index 0000000..f851c45
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Cst/Cpu0Cst.asl
@@ -0,0 +1,430 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Cpu0Cst.ASL
+
+ Abstract:
+
+ CPU C State control methods
+
+--*/
+
+DefinitionBlock (
+ "Cpu0Cst.aml",
+ "SSDT",
+ 0x01,
+ "SsgPmm",
+ "Cpu0Cst",
+ 0x0011
+ )
+{
+ External(\_PR.CPU0, DeviceObj)
+ External (PDC0, IntObj)
+ External (CFGD, FieldUnitObj)
+
+ Scope(\_PR.CPU0)
+ {
+ Method (_CST, 0)
+ {
+ // If CMP is supported, and OSPM is not capable of independent C1, P, T state
+ // support for each processor for multi-processor configuration, we will just report
+ // C1 halt
+ //
+ // PDCx[4] = Indicates whether OSPM is not capable of independent C1, P, T state
+ // support for each processor for multi-processor configuration.
+ //
+ If(LAnd(And(CFGD,0x01000000), LNot(And(PDC0,0x10))))
+ {
+ Return(Package() {
+ 1,
+ Package()
+ { // C1 halt
+ ResourceTemplate(){Register(FFixedHW, 0, 0, 0)},
+ 1,
+ 157,
+ 1000
+ }
+ })
+ }
+
+ //
+ // If MWAIT extensions is supported and OSPM is capable of performing
+ // native C state instructions for the C2/C3 in multi-processor configuration,
+ // we report every c state with MWAIT extensions.
+ //
+ // PDCx[9] = Indicates whether OSPM is capable of performing native C state instructions
+ // for the C2/C3 in multi-processor configuration
+ //
+ If(LAnd(And(CFGD, 0x200000), And(PDC0,0x200)))
+ {
+ //
+ // If C6 is supported, we report MWAIT C1,C2,C4,C6
+ //
+ If(And(CFGD,0x200))
+ {
+ Return( Package()
+ {
+ 4,
+ Package()
+ { // MWAIT C1, hardware coordinated with no bus master avoidance
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // MWAIT C2, hardware coordinated with no bus master avoidance
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x10, 1)},
+ 2,
+ 20,
+ 500
+ },
+ Package()
+ { // MWAIT C4, hardware coordinated with bus master avoidance enabled
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x30, 3)},
+ 3,
+ 100,
+ 100
+ },
+ Package()
+ { // MWAIT C6, hardware coordinated with bus master avoidance enabled
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x50, 3)},
+ 3,
+ 140,
+ 10
+ }
+ })
+ }
+ //
+ // If C4 is supported, we report MWAIT C1,C2,C4
+ //
+ If(And(CFGD,0x080))
+ {
+ Return( Package()
+ {
+ 3,
+ Package()
+ { // MWAIT C1, hardware coordinated with no bus master avoidance
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // MWAIT C2, hardware coordinated with no bus master avoidance
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x10, 1)},
+ 2,
+ 20,
+ 500
+ },
+ Package()
+ { // MWAIT C4, hardware coordinated with bus master avoidance enabled
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x30, 3)},
+ 3,
+ 100,
+ 100
+ }
+ })
+ }
+ //
+ // If C2 is supported, we report MWAIT C1,C2
+ //
+ If(And(CFGD,0x020))
+ {
+ Return( Package()
+ {
+ 2,
+ Package()
+ { // MWAIT C1, hardware coordinated with no bus master avoidance
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // MWAIT C2, hardware coordinated with no bus master avoidance
+ ResourceTemplate(){Register(FFixedHW, 1, 2, 0x10, 1)},
+ 2,
+ 20,
+ 500
+ }
+ })
+ }
+ //
+ // Else we only report MWAIT C1.
+ //
+ Return(Package()
+ {
+ 1,
+ Package()
+ { // MWAIT C1, hardware coordinated with no bus master avoidance
+ ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+ 1,
+ 1,
+ 1000
+ }
+ })
+ }
+
+ // If OSPM is only capable of performing native C state instructions for
+ // the C1 in multi-processor configuration, we report C1 with MWAIT, other
+ // C states with IO method.
+ //
+ // PDCx[8] = Indicates whether OSPM is capable of performing native C state instructions
+ // for the C1 in multi-processor configuration
+ //
+ If(LAnd(And(CFGD, 0x200000), And(PDC0,0x100)))
+ {
+ //
+ // If C6 is supported, we report MWAIT C1, IO C2,C4,C6
+ //
+ If(And(CFGD,0x200))
+ {
+ Return( Package()
+ {
+ 4,
+ Package()
+ { // MWAIT C1, hardware coordinated with no bus master avoidance
+ ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // IO C2 ("PMBALVL2" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+ 2,
+ 20,
+ 500
+ },
+ Package()
+ { // IO C4 ("PMBALVL4" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x344C564C41424D50)},
+ 3,
+ 100,
+ 100
+ },
+ Package()
+ { // IO C6 ("PMBALVL6" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x364C564C41424D50)},
+ 3,
+ 140,
+ 10
+ }
+ })
+ }
+ //
+ // If C4 is supported, we report MWAIT C1, IO C2,C4
+ //
+ If(And(CFGD,0x080))
+ {
+ Return( Package()
+ {
+ 3,
+ Package()
+ { // MWAIT C1, hardware coordinated with no bus master avoidance
+ ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // IO C2 ("PMBALVL2" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+ 2,
+ 20,
+ 500
+ },
+ Package()
+ { // IO C4 ("PMBALVL4" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x344C564C41424D50)},
+ 3,
+ 100,
+ 100
+ }
+ })
+ }
+ //
+ // If C2 is supported, we report MWAIT C1, IO C2
+ //
+ If(And(CFGD,0x020))
+ {
+ Return( Package()
+ {
+ 2,
+ Package()
+ { // MWAIT C1, hardware coordinated with no bus master avoidance
+ ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // IO C2 ("PMBALVL2" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+ 2,
+ 20,
+ 500
+ }
+ })
+ }
+ //
+ // Else we only report MWAIT C1.
+ //
+ Return(Package()
+ {
+ 1,
+ Package()
+ { // MWAIT C1, hardware coordinated with no bus master avoidance
+ ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+ 1,
+ 1,
+ 1000
+ }
+ })
+ }
+
+ //
+ // If MWAIT is not supported, we report all the c states with IO method
+ //
+
+ //
+ // If C6 is supported, we report C1 halt, IO C2,C4,C6
+ //
+ If(And(CFGD,0x200))
+ {
+ Return(Package()
+ {
+ 4,
+ Package()
+ { // C1 Halt
+ ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // IO C2 ("PMBALVL2" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+ 2,
+ 20,
+ 500
+ },
+ Package()
+ { // IO C4 ("PMBALVL4" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x344C564C41424D50)},
+ 3,
+ 100,
+ 100
+ },
+ Package()
+ { // IO C6 ("PMBALVL6" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x364C564C41424D50)},
+ 3,
+ 140,
+ 10
+ }
+ })
+ }
+ //
+ // If C4 is supported, we report C1 halt, IO C2,C4
+ //
+ If(And(CFGD,0x080))
+ {
+ Return(Package()
+ {
+ 3,
+ Package()
+ { // C1 halt
+ ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // IO C2 ("PMBALVL2" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+ 2,
+ 20,
+ 500
+ },
+ Package()
+ { // IO C4 ("PMBALVL4" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x344C564C41424D50)},
+ 3,
+ 100,
+ 100
+ }
+ })
+ }
+
+ //
+ // If C2 is supported, we report C1 halt, IO C2
+ //
+ If(And(CFGD,0x020))
+ {
+ Return(Package()
+ {
+ 2,
+ Package()
+ { // C1 halt
+ ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+ 1,
+ 1,
+ 1000
+ },
+ Package()
+ { // IO C2 ("PMBALVL2" will be updated at runtime)
+ ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+ 2,
+ 20,
+ 500
+ }
+ })
+ }
+ //
+ // Else we only report C1 halt.
+ //
+ Return(Package()
+ {
+ 1,
+ Package()
+ { // C1 halt
+ ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+ 1,
+ 1,
+ 1000
+ }
+ })
+ }
+ }
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Ist/Cpu0Ist.asl b/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Ist/Cpu0Ist.asl
new file mode 100644
index 0000000..e6d89ab
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Ist/Cpu0Ist.asl
@@ -0,0 +1,190 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Cpu0Ist.ASL
+
+ Abstract:
+
+ CPU EIST control methods
+
+--*/
+
+DefinitionBlock (
+ "CPU0IST.aml",
+ "SSDT",
+ 0x01,
+ "SsgPmm",
+ "Cpu0Ist",
+ 0x0012
+ )
+{
+ External (PDC0, IntObj)
+ External (CFGD, FieldUnitObj)
+ External(\_PR.CPU0, DeviceObj)
+
+ Scope(\_PR.CPU0)
+ {
+ Method(_PPC,0)
+ {
+ Return(ZERO) // Return All States Available.
+ }
+
+ Method(_PCT,0)
+ {
+ //
+ // If GV3 is supported and OSPM is capable of direct access to
+ // performance state MSR, we use MSR method
+ //
+ //
+ // PDCx[0] = Indicates whether OSPM is capable of direct access to
+ // performance state MSR.
+ //
+ If(LAnd(And(CFGD,0x0001), And(PDC0,0x0001)))
+ {
+ Return(Package() // MSR Method
+ {
+ ResourceTemplate(){Register(FFixedHW, 0, 0, 0)},
+ ResourceTemplate(){Register(FFixedHW, 0, 0, 0)}
+ })
+
+ }
+
+ //
+ // Otherwise, we use smi method
+ //
+ Return(Package() // SMI Method
+ {
+ ResourceTemplate(){Register(SystemIO,16,0,0xB2)},
+ ResourceTemplate(){Register(SystemIO, 8,0,0xB3)}
+ })
+ }
+
+ Method(_PSS,0)
+ {
+ //
+ // If OSPM is capable of direct access to performance state MSR,
+ // we report NPSS, otherwise, we report SPSS.
+ If (And(PDC0,0x0001))
+ {
+ Return(NPSS)
+ }
+
+ Return(SPSS)
+ }
+
+ Name(SPSS,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}
+ })
+
+ Name(NPSS,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}
+ })
+
+ Method(_PSD,0)
+ {
+ //
+ // If CMP is suppored, we report the dependency with two processors
+ //
+ If(And(CFGD,0x1000000))
+ {
+ //
+ // If OSPM is capable of hardware coordination of P-states, we report
+ // the dependency with hardware coordination.
+ //
+ // PDCx[11] = Indicates whether OSPM is capable of hardware coordination of P-states
+ //
+ If(And(PDC0,0x0800))
+ {
+ Return(Package(){
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFE, // Coord Type- HW_ALL.
+ 2 // # processors.
+ }
+ })
+ }
+
+ //
+ // Otherwise, the dependency with OSPM coordination
+ //
+ Return(Package(){
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFC, // Coord Type- SW_ALL.
+ 2 // # processors.
+ }
+ })
+ }
+
+ //
+ // Otherwise, we report the dependency with one processor
+ //
+ Return(Package(){
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFC, // Coord Type- SW_ALL.
+ 1 // # processors.
+ }
+ })
+ }
+ }
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Tst/Cpu0Tst.asl b/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Tst/Cpu0Tst.asl
new file mode 100644
index 0000000..f29cfd1
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Tst/Cpu0Tst.asl
@@ -0,0 +1,164 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Cpu0Tst.ASL
+
+ Abstract:
+
+ CPU T-state control methods
+
+--*/
+
+DefinitionBlock (
+ "CPU0TST.aml",
+ "SSDT",
+ 0x01,
+ "SsgPmm",
+ "Cpu0Tst",
+ 0x0013
+ )
+{
+ External (PDC0, IntObj)
+ External (CFGD, FieldUnitObj)
+ External(\_PR.CPU0, DeviceObj)
+ External(_PSS)
+
+ Scope(\_PR.CPU0)
+ {
+ Method(_TPC,0)
+ {
+ Return(ZERO) // Return All States Available.
+ }
+
+ Name(TPTC, ResourceTemplate()
+ {
+ Memory32Fixed(ReadOnly, 0, 0, FIX1) // IO APIC
+ })
+
+ //
+ // If OSPM is capable of direct access to on demand throttling MSR,
+ // we use MSR method;otherwise we use IO method.
+ //
+ //
+ // PDCx[2] = Indicates whether OSPM is capable of direct access to
+ // on demand throttling MSR.
+ //
+ Method(_PTC, 0)
+ {
+ If(And(PDC0, 0x0004))
+ {
+ Return(Package() // MSR Method
+ {
+ ResourceTemplate(){Register(FFixedHW, 0, 0, 0)},
+ ResourceTemplate(){Register(FFixedHW, 0, 0, 0)}
+ }
+ )
+ }
+ Return(Package() // IO Method
+ {
+ //
+ // PM IO base ("PMBALVL0" will be updated at runtime)
+ //
+ ResourceTemplate(){Register(SystemIO, 4, 1, 0x304C564C41424D50)},
+ ResourceTemplate(){Register(SystemIO, 4, 1, 0x304C564C41424D50)}
+ }
+ )
+ }
+
+ //
+ // _TSS returned package for IO Method
+ //
+ Name(TSSI, Package()
+ {
+ Package(){100, 1000, 0, 0x00, 0}
+ }
+ )
+ //
+ // _TSS returned package for MSR Method
+ //
+ Name(TSSM, Package()
+ {
+ Package(){100, 1000, 0, 0x00, 0}
+ }
+ )
+
+ Method(_TSS, 0)
+ {
+ //
+ // If OSPM is capable of direct access to on demand throttling MSR,
+ // we report TSSM;otherwise report TSSI.
+ //
+ If(And(PDC0, 0x0004))
+ {
+ Return(TSSM)
+ }
+ Return(TSSI)
+ }
+
+ Method(_TSD, 0)
+ {
+ //
+ // If CMP is suppored, we report the dependency with two processors
+ //
+ If(LAnd(And(CFGD, 0x1000000), LNot(And(PDC0, 4))))
+ {
+ Return(Package()
+ {
+ Package()
+ {
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ 2 // # processors.
+ }
+ }
+ )
+ }
+ //
+ // Otherwise, we report the dependency with one processor
+ //
+ Return(Package()
+ {
+ Package()
+ {
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ }
+ )
+ }
+ }
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/CpuPm/CpuPm.asl b/QuarkPlatformPkg/Acpi/AcpiTables/CpuPm/CpuPm.asl
new file mode 100644
index 0000000..84545b2
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/CpuPm/CpuPm.asl
@@ -0,0 +1,104 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ CpuPm.ASL
+
+ Abstract:
+
+ CPU power management control methods
+
+--*/
+
+DefinitionBlock (
+ "CPUPM.aml",
+ "SSDT",
+ 0x01,
+ "SsgPmm",
+ "CpuPm",
+ 0x0010
+ )
+{
+ External(\_PR.CPU0, DeviceObj)
+ External(CFGD, FieldUnitObj)
+
+ Scope(\)
+ {
+ // Config DWord, modified during POST
+ // Bit definitions are the same as PPMFlags:
+ // CFGD[0] = PPM_GV3 = GV3
+ // CFGD[1] = PPM_TURBO = Turbo Mode
+ // CFGD[2] = PPM_SUPER_LFM = N/2 Ratio
+ // CFGD[4] = PPM_C1 = C1 Capable, Enabled
+ // CFGD[5] = PPM_C2 = C2 Capable, Enabled
+ // CFGD[6] = PPM_C3 = C3 Capable, Enabled
+ // CFGD[7] = PPM_C4 = C4 Capable, Enabled
+ // CFGD[8] = PPM_C5 = C5/Deep C4 Capable, Enabled
+ // CFGD[9] = PPM_C6 = C6 Capable, Enabled
+ // CFGD[10] = PPM_C1E = C1E Enabled
+ // CFGD[11] = PPM_C2E = C2E Enabled
+ // CFGD[12] = PPM_C3E = C3E Enabled
+ // CFGD[13] = PPM_C4E = C4E Enabled
+ // CFGD[14] = PPM_HARD_C4E = Hard C4E Capable, Enabled
+ // CFGD[16] = PPM_TM1 = Thermal Monitor 1
+ // CFGD[17] = PPM_TM2 = Thermal Monitor 2
+ // CFGD[19] = PPM_PHOT = Bi-directional ProcHot
+ // CFGD[21] = PPM_MWAIT_EXT = MWAIT extensions supported
+ // CFGD[24] = PPM_CMP = CMP supported, Enabled
+ // CFGD[28] = PPM_TSTATE = CPU T states supported
+ //
+ // Name(CFGD, 0x80000000)
+ // External Defined in GNVS
+
+ Name(PDC0,0x80000000) // CPU0 _PDC Flags.
+
+ // We load it in AcpiPlatform
+ //Name(SSDT,Package()
+ //{
+ // "CPU0IST ", 0x80000000, 0x80000000,
+ // "CPU1IST ", 0x80000000, 0x80000000,
+ // "CPU0CST ", 0x80000000, 0x80000000,
+ // "CPU1CST ", 0x80000000, 0x80000000,
+ //})
+ }
+ Scope(\_PR.CPU0)
+ {
+ Method(_PDC, 1)
+ {
+ //
+ // Store result of PDC.
+ //
+ CreateDWordField(Arg0,8,CAP0) // Point to 3rd DWORD.
+ Store(CAP0,PDC0) // Store It in PDC0.
+ }
+ }
+
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/LpcDev.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/LpcDev.asi
new file mode 100644
index 0000000..1e2597e
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/LpcDev.asi
@@ -0,0 +1,277 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ LpcDev.asi
+
+ Abstract:
+
+ Legacy resource template
+
+--*/
+
+#ifndef LPC_DEV_ASI
+#define LPC_DEV_ASI
+
+Device(RTC)
+{
+ Name(_HID,EISAID("PNP0B00"))
+ Name(BUF0,ResourceTemplate() {
+ IO(Decode16,0x70,0x70,0x01,0x04)
+ IO(Decode16,0x74,0x74,0x01,0x04)
+ })
+ Name(BUF1,ResourceTemplate() {
+ IO(Decode16,0x70,0x70,0x01,0x04)
+ IO(Decode16,0x74,0x74,0x01,0x04)
+ IRQNoFlags(){8}
+ })
+ Method(_CRS,0,Serialized)
+ {
+ If (HPEA)
+ {
+ return (BUF0)
+ }
+ Else
+ {
+ return (BUF1)
+ }
+ }
+}
+
+Device(PIC)
+{
+ Name(_HID,EISAID("PNP0000"))
+
+ Name(_CRS,ResourceTemplate() {
+ IO(Decode16,0x20,0x20,0x01,0x1E) // length of 1Eh includes all aliases
+ IO(Decode16,0xA0,0xA0,0x01,0x1E)
+ IO(Decode16,0x4D0,0x4D0,0x01,0x02)
+ })
+}
+
+Device(TMR)
+{
+ Name(_HID,EISAID("PNP0100"))
+
+ Name(BUF0,ResourceTemplate() {
+ IO(Decode16,0x40,0x40,0x01,0x04)
+ IO(Decode16,0x50,0x50,0x01,0x04) // alias
+ })
+ Name(BUF1,ResourceTemplate() {
+ IO(Decode16,0x40,0x40,0x01,0x04)
+ IO(Decode16,0x50,0x50,0x01,0x04) // alias
+ IRQNoFlags(){0}
+ })
+ Method(_CRS,0,Serialized)
+ {
+ If (HPEA)
+ {
+ return (BUF0)
+ }
+ Else
+ {
+ return (BUF1)
+ }
+ }
+}
+
+Device(SPKR)
+{
+ Name(_HID,EISAID("PNP0800"))
+
+ Name(_CRS,ResourceTemplate() {
+ IO(Decode16,0x61,0x61,0x01,0x01)
+ })
+}
+
+Device(XTRA) // all "PNP0C02" devices- pieces that don't fit anywhere else
+{
+ Name(_HID,EISAID("PNP0C02")) // Generic motherboard devices
+
+ Name(CRS,
+ ResourceTemplate()
+ {
+ IO(Decode16,0x2E,0x2E,0x01,0x02)
+ IO(Decode16,0x4E,0x2E,0x01,0x02)
+ IO(Decode16,0x63,0x61,0x01,0x01)
+ IO(Decode16,0x65,0x61,0x01,0x01)
+ IO(Decode16,0x67,0x61,0x01,0x01)
+ IO(Decode16,0x80,0x80,0x01,0x01)
+ IO(Decode16,0x84,0x84,0x01,0x04)
+ IO(Decode16,0x88,0x88,0x01,0x01)
+ IO(Decode16,0x8c,0x8c,0x01,0x03)
+ IO(Decode16,0x92,0x92,0x01,0x01)
+
+ IO(
+ Decode16,
+ 0,
+ 0,
+ 0x01,
+ 0x10,
+ FIX1
+ )
+
+ IO(
+ Decode16,
+ 0,
+ 0,
+ 0x01,
+ 0x10,
+ FIX2
+ )
+
+ IO(
+ Decode16,
+ 0,
+ 0,
+ 0x01,
+ 0x40,
+ FIX3
+ )
+
+ IO(
+ Decode16,
+ 0,
+ 0,
+ 0x01,
+ 0x40,
+ FIX4
+ )
+
+ IO(
+ Decode16,
+ 0,
+ 0,
+ 0x01,
+ 0x40,
+ FIX5
+ )
+
+ IO(
+ Decode16,
+ 0,
+ 0,
+ 0x01,
+ 0x20,
+ FIX6
+ )
+
+ IO(
+ Decode16,
+ 0,
+ 0,
+ 0x01,
+ 0x40,
+ FIX7
+ )
+
+ }
+ )
+
+ Method (_CRS, 0, NotSerialized) {
+ CreateWordField (CRS, ^FIX1._MIN, MBR0)
+ Store(\P1BB, MBR0)
+ CreateWordField (CRS, ^FIX1._MAX, MBR1)
+ Store(\P1BB, MBR1)
+ CreateWordField (CRS, ^FIX2._MIN, MBR2)
+ Store(\PBAB, MBR2)
+ CreateWordField (CRS, ^FIX2._MAX, MBR3)
+ Store(\PBAB, MBR3)
+ CreateWordField (CRS, ^FIX3._MIN, MBR4)
+ Store(\GP0B, MBR4)
+ CreateWordField (CRS, ^FIX3._MAX, MBR5)
+ Store(\GP0B, MBR5)
+ CreateWordField (CRS, ^FIX4._MIN, MBR6)
+ Store(\GPAB, MBR6)
+ CreateWordField (CRS, ^FIX4._MAX, MBR7)
+ Store(\GPAB, MBR7)
+ CreateWordField (CRS, ^FIX5._MIN, MBR8)
+ Store(\SMBB, MBR8)
+ CreateWordField (CRS, ^FIX5._MAX, MBR9)
+ Store(\SMBB, MBR9)
+ CreateWordField (CRS, ^FIX6._MIN, MBRA)
+ Store(\SPIB, MBRA)
+ CreateWordField (CRS, ^FIX6._MAX, MBRB)
+ Store(\SPIB, MBRB)
+ CreateWordField (CRS, ^FIX7._MIN, MBRC)
+ Store(\WDTB, MBRC)
+ CreateWordField (CRS, ^FIX7._MAX, MBRD)
+ Store(\WDTB, MBRD)
+ return (CRS)
+ }
+}
+
+Device(HPET) // High Performance Event Timer
+{
+ Name(_HID,EISAID("PNP0103"))
+
+ Name(BUF0,ResourceTemplate()
+ {
+ IRQNoFlags() {0}
+ IRQNoFlags() {8}
+ Memory32Fixed(ReadOnly, 0, 0, FIX1)
+ })
+
+ Method(_STA,0)
+ {
+ // Show this Device only if the OS is WINXP or beyond.
+
+ If(LGreaterEqual(OSTP,WINDOWS_XP))
+ {
+ If(HPEA)
+ {
+ Return(0x000F) // Enabled, do Display.
+ }
+ }
+ Else
+ {
+ // OS = WIN98, WINME, or WIN2000.
+
+ If(HPEA)
+ {
+ Return(0x000B) // Enabled, don't Display.
+ }
+ }
+
+ Return(0x0000) // Return Nothing.
+ }
+
+ Method(_CRS,0,Serialized)
+ {
+ CreateDWordField (BUF0, ^FIX1._BAS, MBR0)
+ Store(\HPTB, MBR0)
+ CreateDWordField (BUF0, ^FIX1._LEN, MBR1)
+ Store(\HPTS, MBR1)
+ Return(BUF0)
+ }
+}
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciHostBridge.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciHostBridge.asi
new file mode 100644
index 0000000..37ed3f4
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciHostBridge.asi
@@ -0,0 +1,226 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ PciHostBridge.asi
+
+ Abstract:
+
+ PCI Host Bridge Definitions
+
+--*/
+
+
+Name(PBRS, ResourceTemplate() {
+ WORDBusNumber( //Bus number resource (0); the bridge produces bus numbers for its subsequent buses
+ ResourceProducer, // bit 0 of general flags is 1
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ PosDecode, // PosDecode
+ 0x0000, // Granularity
+ 0x0000, // Min
+ 0x001f, // Max
+ 0x0000, // Translation
+ 0x0020 // Range Length = Max-Min+1
+ )
+
+ WORDIO( //Consumed-and-produced resource (all I/O below CF8)
+ ResourceProducer, // bit 0 of general flags is 0
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ PosDecode,
+ EntireRange,
+ 0x0000, // Granularity
+ 0x0000, // Min
+ 0x0cf7, // Max
+ 0x0000, // Translation
+ 0x0cf8 // Range Length
+ )
+
+ IO( //Consumed resource (CF8-CFF)
+ Decode16,
+ 0x0cf8,
+ 0xcf8,
+ 1,
+ 8
+ )
+
+ WORDIO( //Consumed-and-produced resource (all I/O above CFF)
+ ResourceProducer, // bit 0 of general flags is 0
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ PosDecode,
+ EntireRange,
+ 0x0000, // Granularity
+ 0x0d00, // Min
+ 0xffff, // Max
+ 0x0000, // Translation
+ 0xf300 // Range Length
+ )
+
+ DWORDMEMORY( // descriptor for dos area(0->0xa0000)
+ ResourceProducer, // bit 0 of general flags is 0
+ PosDecode,
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is Fixed
+ Cacheable,
+ ReadWrite,
+ 0x00000000, // Granularity
+ 0x000a0000, // Min
+ 0x000bffff, // Max
+ 0x00000000, // Translation
+ 0x00020000 // Range Length
+ )
+
+ DWORDMemory( // Consumed-and-produced resource for pci memory mapped memory
+ ResourceProducer, // bit 0 of general flags is 0
+ PosDecode, // positive Decode
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ Cacheable,
+ ReadWrite,
+ 0x00000000, // Granularity
+ 0x00000000, // Min (calculated dynamically)
+
+ 0xfebfffff, // Max = IO Apic base address - 1
+ 0x00000000, // Translation
+ 0xfec00000, // Range Length (calculated dynamically)
+ , // Optional field left blank
+ , // Optional field left blank
+ MEM1 // Name declaration for this descriptor
+ )
+
+}) // end of CRES Buffer
+
+
+Method(_CRS, 0x0, NotSerialized)
+{
+ CreateDWordField(PBRS, \_SB.PCI0.MEM1._MIN, MMIN)
+ CreateDWordField(PBRS, \_SB.PCI0.MEM1._MAX, MMAX)
+ CreateDWordField(PBRS, \_SB.PCI0.MEM1._LEN, MLEN)
+
+ // HMBOUND is PCI memory base
+ And(MNRD(0x03, 0x08), 0xFFFFF000, MMIN)
+ Add(Subtract(MMAX, MMIN), 1, MLEN)
+
+ Return(PBRS)
+}
+
+// Message Nework Registers
+OperationRegion(MNR, PCI_Config, 0xD0, 0x10)
+Field(MNR, DWordAcc, NoLock, Preserve)
+{
+ MCR, 32, // Message Control Register
+ MDR, 32 // Message Data Register
+}
+
+// Message Nework Read Method
+// Arg0 = Port
+// Arg1 = RegAddress
+// return 32 bit register value
+Method(MNRD, 2, Serialized)
+{
+ Or(ShiftLeft(Arg0, 16), ShiftLeft(Arg1, 8), Local0)
+ Or(Local0, 0x100000F0, Local0)
+ Store(Local0, MCR)
+ Return(MDR)
+}
+
+// Message Nework Write Method
+// Arg0 = Port
+// Arg1 = RegAddress
+// Arg2 = 32 bit write value
+Method(MNWR, 3, Serialized)
+{
+ Store(Arg2, MDR)
+ Or(ShiftLeft(Arg0, 16), ShiftLeft(Arg1, 8), Local0)
+ Or(Local0, 0x110000F0, Local0)
+ Store(Local0, MCR)
+}
+
+Method(_PRT, 0, NotSerialized)
+{
+ If (LEqual(\GPIC, Zero)) // 8259 Interrupt Routing
+ {
+ Return (
+ Package()
+ {
+ // Bus 0, Device 20 - IOSFAHB Bridge
+ Package() {0x0014ffff, 0, \_SB.PCI0.LPC.LNKA, 0}, // INTA
+ Package() {0x0014ffff, 1, \_SB.PCI0.LPC.LNKB, 0}, // INTB
+ Package() {0x0014ffff, 2, \_SB.PCI0.LPC.LNKC, 0}, // INTC
+ Package() {0x0014ffff, 3, \_SB.PCI0.LPC.LNKD, 0}, // INTD
+
+ // Bus 0, Device 21 - IOSFAHB Bridge
+ Package() {0x0015ffff, 0, \_SB.PCI0.LPC.LNKA, 0}, // INTA
+ Package() {0x0015ffff, 1, \_SB.PCI0.LPC.LNKB, 0}, // INTB
+ Package() {0x0015ffff, 2, \_SB.PCI0.LPC.LNKC, 0}, // INTC
+ Package() {0x0015ffff, 3, \_SB.PCI0.LPC.LNKD, 0}, // INTD
+
+ // Bus 0, Device 23 - PCIe port 0
+ Package() {0x0017ffff, 0, \_SB.PCI0.LPC.LNKE, 0}, // INTA
+ Package() {0x0017ffff, 1, \_SB.PCI0.LPC.LNKF, 0}, // INTB
+ Package() {0x0017ffff, 2, \_SB.PCI0.LPC.LNKG, 0}, // INTC
+ Package() {0x0017ffff, 3, \_SB.PCI0.LPC.LNKH, 0}, // INTD
+
+ // Bus 0, Device 31
+ Package() {0x001fffff, 0, \_SB.PCI0.LPC.LNKA, 0}, // LPC Bridge
+ }
+ )
+ }
+ else {
+ Return (
+ Package()
+ {
+ // Bus 0, Device 20 - IOSFAHB Bridge
+ Package() {0x0014ffff, 0, 0, 16}, // INTA
+ Package() {0x0014ffff, 1, 0, 17}, // INTB
+ Package() {0x0014ffff, 2, 0, 18}, // INTC
+ Package() {0x0014ffff, 3, 0, 19}, // INTD
+
+ // Bus 0, Device 21 - IOSFAHB Bridge
+ Package() {0x0015ffff, 0, 0, 16}, // INTA
+ Package() {0x0015ffff, 1, 0, 17}, // INTB
+ Package() {0x0015ffff, 2, 0, 18}, // INTC
+ Package() {0x0015ffff, 3, 0, 19}, // INTD
+
+ // Bus 0, Device 23 - PCIe port 0
+ Package() {0x0017ffff, 0, 0, 20}, // INTA
+ Package() {0x0017ffff, 1, 0, 21}, // INTB
+ Package() {0x0017ffff, 2, 0, 22}, // INTC
+ Package() {0x0017ffff, 3, 0, 23}, // INTD
+
+ // Bus 0, Device 31
+ Package() {0x001fffff, 0, 0, 16}, // LPC Bridge
+ }
+ )
+ }
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciIrq.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciIrq.asi
new file mode 100644
index 0000000..db8aef8
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciIrq.asi
@@ -0,0 +1,582 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ pciirq.asi
+
+ Abstract:
+
+--*/
+
+
+// Interrupts can be DEB8=all except 13,8,6,2,1,0
+
+#ifndef PCIIRQ_ASI
+#define PCIIRQ_ASI
+
+OperationRegion(PRR0, PCI_Config, 0x60, 0x08)
+Field(PRR0, ANYACC, NOLOCK, PRESERVE)
+{
+ PIRA, 8,
+ PIRB, 8,
+ PIRC, 8,
+ PIRD, 8,
+ PIRE, 8,
+ PIRF, 8,
+ PIRG, 8,
+ PIRH, 8
+}
+
+Device(LNKA) // PCI IRQ link A
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID, 1)
+
+ Method(_STA,0,NotSerialized)
+ {
+ If(And(PIRA, 0x80))
+ {
+ Return(0x9)
+ }
+ Else
+ {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method(_DIS,0,NotSerialized)
+ {
+ Or(PIRA, 0x80, PIRA)
+ }
+
+ Method(_CRS,0,NotSerialized)
+ {
+ Name(BUF0,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+
+ // Define references to buffer elements
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ // Write current settings into IRQ descriptor
+ If (And(PIRA, 0x80))
+ {
+ Store(Zero, Local0)
+ }
+ Else
+ {
+ Store(One,Local0)
+ }
+ // Shift 1 by value in register 70
+ ShiftLeft(Local0,And(PIRA,0x0F),IRQW) // Save in buffer
+ Return(BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+ Method(_SRS,1,NotSerialized)
+ {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual(IRQW,Zero))
+ {
+ And(Local0, 0x7F,Local0)
+ Decrement(Local0)
+ }
+ Else
+ {
+ Or(Local0, 0x80,Local0)
+ }
+ store(Local0, PIRA)
+ } // End of _SRS Method
+}
+
+Device(LNKB) // PCI IRQ link B
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID, 2)
+
+ Method(_STA,0,NotSerialized)
+ {
+ If(And(PIRB, 0x80))
+ {
+ Return(0x9)
+ }
+ Else
+ {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method(_DIS,0,NotSerialized)
+ {
+ Or(PIRB, 0x80,PIRB)
+ }
+
+ Method(_CRS,0,NotSerialized)
+ {
+ Name(BUF0,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ // Define references to buffer elements
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ // Write current settings into IRQ descriptor
+ If (And(PIRB, 0x80))
+ {
+ Store(Zero, Local0)
+ }
+ Else
+ {
+ Store(One,Local0)
+ }
+ // Shift 1 by value in register 70
+ ShiftLeft(Local0,And(PIRB,0x0F),IRQW) // Save in buffer
+ Return(BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+ Method(_SRS,1,NotSerialized)
+ {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual(IRQW,Zero))
+ {
+ And(Local0, 0x7F,Local0)
+ Decrement(Local0)
+ }
+ Else
+ {
+ Or(Local0, 0x80,Local0)
+ }
+ Store(Local0, PIRB)
+ } // End of _SRS Method
+}
+
+Device(LNKC) // PCI IRQ link C
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID, 3)
+
+ Method(_STA,0,NotSerialized)
+ {
+ If(And(PIRC, 0x80))
+ {
+ Return(0x9)
+ }
+ Else
+ {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method(_DIS,0,NotSerialized)
+ {
+ Or(PIRC, 0x80,PIRC)
+ }
+
+ Method(_CRS,0,NotSerialized)
+ {
+ Name(BUF0,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ // Define references to buffer elements
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ // Write current settings into IRQ descriptor
+ If (And(PIRC, 0x80))
+ {
+ Store(Zero, Local0)
+ }
+ Else
+ {
+ Store(One,Local0)
+ } // Shift 1 by value in register 70
+ ShiftLeft(Local0,And(PIRC,0x0F),IRQW) // Save in buffer
+ Return(BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+ Method(_SRS,1,NotSerialized)
+ {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual(IRQW,Zero))
+ {
+ And(Local0, 0x7F,Local0)
+ Decrement(Local0)
+ }
+ Else {
+ Or(Local0, 0x80,Local0)
+ }
+ Store(Local0, PIRC)
+ } // End of _SRS Method
+}
+
+Device(LNKD) // PCI IRQ link D
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID, 4)
+
+ Method(_STA,0,NotSerialized)
+ {
+ If(And(PIRD, 0x80))
+ {
+ Return(0x9)
+ }
+ Else
+ {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method(_DIS,0,NotSerialized)
+ {
+ Or(PIRD, 0x80,PIRD)
+ }
+
+ Method(_CRS,0,NotSerialized)
+ {
+ Name(BUF0,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ // Define references to buffer elements
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ // Write current settings into IRQ descriptor
+ If (And(PIRD, 0x80))
+ {
+ Store(Zero, Local0)
+ }
+ Else
+ {
+ Store(One,Local0)
+ } // Shift 1 by value in register 70
+ ShiftLeft(Local0,And(PIRD,0x0F),IRQW) // Save in buffer
+ Return(BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+ Method(_SRS,1,NotSerialized)
+ {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0)// Set IRQ
+ If (LNotEqual(IRQW,Zero))
+ {
+ And(Local0, 0x7F,Local0)
+ Decrement(Local0)
+ }
+ Else
+ {
+ Or(Local0, 0x80,Local0)
+ }
+ Store(Local0, PIRD)
+ } // End of _SRS Method
+}
+
+Device(LNKE) // PCI IRQ link E
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID, 5)
+
+ Method(_STA,0,NotSerialized)
+ {
+ If(And(PIRE, 0x80))
+ {
+ Return(0x9)
+ }
+ Else
+ {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method(_DIS,0,NotSerialized)
+ {
+ Or(PIRE, 0x80, PIRE)
+ }
+
+ Method(_CRS,0,NotSerialized)
+ {
+ Name(BUF0,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+
+ // Define references to buffer elements
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ // Write current settings into IRQ descriptor
+ If (And(PIRE, 0x80))
+ {
+ Store(Zero, Local0)
+ }
+ Else
+ {
+ Store(One,Local0)
+ }
+ // Shift 1 by value in register 70
+ ShiftLeft(Local0,And(PIRE,0x0F),IRQW) // Save in buffer
+ Return(BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+ Method(_SRS,1,NotSerialized)
+ {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual(IRQW,Zero))
+ {
+ And(Local0, 0x7F,Local0)
+ Decrement(Local0)
+ }
+ Else
+ {
+ Or(Local0, 0x80,Local0)
+ }
+ store(Local0, PIRE)
+ } // End of _SRS Method
+}
+
+Device(LNKF) // PCI IRQ link F
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID, 6)
+
+ Method(_STA,0,NotSerialized)
+ {
+ If(And(PIRF, 0x80))
+ {
+ Return(0x9)
+ }
+ Else
+ {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method(_DIS,0,NotSerialized)
+ {
+ Or(PIRB, 0x80,PIRF)
+ }
+
+ Method(_CRS,0,NotSerialized)
+ {
+ Name(BUF0,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ // Define references to buffer elements
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ // Write current settings into IRQ descriptor
+ If (And(PIRF, 0x80))
+ {
+ Store(Zero, Local0)
+ }
+ Else
+ {
+ Store(One,Local0)
+ }
+ // Shift 1 by value in register 70
+ ShiftLeft(Local0,And(PIRF,0x0F),IRQW) // Save in buffer
+ Return(BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+ Method(_SRS,1,NotSerialized)
+ {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual(IRQW,Zero))
+ {
+ And(Local0, 0x7F,Local0)
+ Decrement(Local0)
+ }
+ Else
+ {
+ Or(Local0, 0x80,Local0)
+ }
+ Store(Local0, PIRF)
+ } // End of _SRS Method
+}
+
+Device(LNKG) // PCI IRQ link G
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID, 7)
+
+ Method(_STA,0,NotSerialized)
+ {
+ If(And(PIRG, 0x80))
+ {
+ Return(0x9)
+ }
+ Else
+ {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method(_DIS,0,NotSerialized)
+ {
+ Or(PIRG, 0x80,PIRG)
+ }
+
+ Method(_CRS,0,NotSerialized)
+ {
+ Name(BUF0,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ // Define references to buffer elements
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ // Write current settings into IRQ descriptor
+ If (And(PIRG, 0x80))
+ {
+ Store(Zero, Local0)
+ }
+ Else
+ {
+ Store(One,Local0)
+ } // Shift 1 by value in register 70
+ ShiftLeft(Local0,And(PIRG,0x0F),IRQW) // Save in buffer
+ Return(BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+ Method(_SRS,1,NotSerialized)
+ {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual(IRQW,Zero))
+ {
+ And(Local0, 0x7F,Local0)
+ Decrement(Local0)
+ }
+ Else {
+ Or(Local0, 0x80,Local0)
+ }
+ Store(Local0, PIRG)
+ } // End of _SRS Method
+}
+
+Device(LNKH) // PCI IRQ link H
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID, 8)
+
+ Method(_STA,0,NotSerialized)
+ {
+ If(And(PIRH, 0x80))
+ {
+ Return(0x9)
+ }
+ Else
+ {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method(_DIS,0,NotSerialized)
+ {
+ Or(PIRH, 0x80,PIRH)
+ }
+
+ Method(_CRS,0,NotSerialized)
+ {
+ Name(BUF0,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ // Define references to buffer elements
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ // Write current settings into IRQ descriptor
+ If (And(PIRH, 0x80))
+ {
+ Store(Zero, Local0)
+ }
+ Else
+ {
+ Store(One,Local0)
+ } // Shift 1 by value in register 70
+ ShiftLeft(Local0,And(PIRH,0x0F),IRQW) // Save in buffer
+ Return(BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+ Method(_SRS,1,NotSerialized)
+ {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0)// Set IRQ
+ If (LNotEqual(IRQW,Zero))
+ {
+ And(Local0, 0x7F,Local0)
+ Decrement(Local0)
+ }
+ Else
+ {
+ Or(Local0, 0x80,Local0)
+ }
+ Store(Local0, PIRH)
+ } // End of _SRS Method
+}
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PcieExpansionPrt.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PcieExpansionPrt.asi
new file mode 100644
index 0000000..3dd1f34
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PcieExpansionPrt.asi
@@ -0,0 +1,158 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ PcieExpansionPrt.asi
+
+ Abstract:
+
+ PCI express expansion ports
+
+--*/
+
+#ifndef PcieExpansionPrt_asi
+#define PcieExpansionPrt_asi
+
+Device (PEX0) // PCI express bus bridged from [Bus 0, Device 23, Function 0]
+{
+ Name(_ADR,0x00170000) // Device (HI WORD)=23, Func (LO WORD)=0
+ Name(_PRW,Package(){0x11,0x03}) // GPE pin 0x11, Wake from S3 -- PCI PME#
+
+ OperationRegion (PES0,PCI_Config,0x40,0xA0)
+ Field (PES0, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0x1A), // SLSTS - Slot Status Register
+ ABP0, 1, // Bit 0, Attention Button Pressed
+ , 2,
+ PDC0, 1, // Bit 3, Presence Detect Changed
+ , 2,
+ PDS0, 1, // Bit 6, Presence Detect State
+ , 1,
+ LSC0, 1, // Bit 8, Link Active State Changed
+ offset (0x20),
+ , 16,
+ PMS0, 1, // Bit 16, PME Status
+ offset (0x98),
+ , 30,
+ HPE0, 1, // Bit 30, Hot Plug SCI Enable
+ PCE0, 1, // Bit 31, Power Management SCI Enable.
+ , 30,
+ HPS0, 1, // Bit 30, Hot Plug SCI Status
+ PCS0, 1, // Bit 31, Power Management SCI Status.
+ }
+
+ Method(_PRT,0,NotSerialized) {
+ If (LEqual(\GPIC, Zero)) // 8259 Interrupt Routing
+ {
+ Return (
+ Package()
+ {
+ // Port 0: INTA->PIRQE,INTB->PIRQF,INTC->PIRQG,INTD->PIRQH
+ Package() {0x0000ffff, 0, \_SB_.PCI0.LPC.LNKE, 0}, // PCI Slot 1
+ Package() {0x0000ffff, 1, \_SB_.PCI0.LPC.LNKF, 0},
+ Package() {0x0000ffff, 2, \_SB_.PCI0.LPC.LNKG, 0},
+ Package() {0x0000ffff, 3, \_SB_.PCI0.LPC.LNKH, 0},
+ }
+ )
+ }
+ else // IOAPIC Routing
+ {
+ Return (
+ Package()
+ {
+ // Port 0: INTA->PIRQE,INTB->PIRQF,INTC->PIRQG,INTD->PIRQH
+ Package() {0x0000ffff, 0, 0, 20}, // PCI Slot 1
+ Package() {0x0000ffff, 1, 0, 21},
+ Package() {0x0000ffff, 2, 0, 22},
+ Package() {0x0000ffff, 3, 0, 23},
+ }
+ )
+ }
+ }
+}
+
+Device (PEX1) // PCI express bus bridged from [Bus 0, Device 23, Function 1]
+{
+ Name(_ADR,0x00170001) // Device (HI WORD)=23, Func (LO WORD)=1
+ Name(_PRW,Package(){0x11,0x03}) // GPE pin 0x11, Wake from S3 -- PCI PME#
+ OperationRegion (PES1,PCI_Config,0x40,0xA0)
+ Field (PES1, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0x1A), // SLSTS - Slot Status Register
+ ABP1, 1, // Bit 0, Attention Button Pressed
+ , 2,
+ PDC1, 1, // Bit 3, Presence Detect Changed
+ , 2,
+ PDS1, 1, // Bit 6, Presence Detect State
+ , 1,
+ LSC1, 1, // Bit 8, Link Active State Changed
+ offset (0x20),
+ , 16,
+ PMS1, 1, // Bit 16, PME Status
+ offset (0x98),
+ , 30,
+ HPE1, 1, // Bit 30, Hot Plug SCI Enable
+ PCE1, 1, // Bit 31, Power Management SCI Enable.
+ , 30,
+ HPS1, 1, // Bit 30, Hot Plug SCI Status
+ PCS1, 1, // Bit 31, Power Management SCI Status.
+ }
+ Method(_PRT,0,NotSerialized) {
+ If (LEqual(\GPIC, Zero)) // 8259 Interrupt Routing
+ {
+ Return (
+ Package()
+ {
+ // Port 1: INTA->PIRQF,INTB->PIRQG,INTC->PIRQH,INTD->PIRQE
+ Package() {0x0000ffff, 0, \_SB_.PCI0.LPC.LNKF, 0},
+ Package() {0x0000ffff, 1, \_SB_.PCI0.LPC.LNKG, 0},
+ Package() {0x0000ffff, 2, \_SB_.PCI0.LPC.LNKH, 0},
+ Package() {0x0000ffff, 3, \_SB_.PCI0.LPC.LNKE, 0},
+ }
+ )
+ }
+ else // IOAPIC Routing
+ {
+ Return (
+ Package()
+ {
+ // Port 1: INTA->PIRQF,INTB->PIRQG,INTC->PIRQH,INTD->PIRQE
+ Package() {0x0000ffff, 0, 0, 21},
+ Package() {0x0000ffff, 1, 0, 22},
+ Package() {0x0000ffff, 2, 0, 23},
+ Package() {0x0000ffff, 3, 0, 20},
+ }
+ )
+ }
+ }
+}
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Platform.asl b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Platform.asl
new file mode 100644
index 0000000..c145ea5
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Platform.asl
@@ -0,0 +1,325 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Platform.asl
+
+ Abstract:
+
+ Contains root level name space objects for the platform
+
+--*/
+
+
+//
+// OS TYPE DEFINITION
+//
+#define WINDOWS_XP 0x01
+#define WINDOWS_XP_SP1 0x02
+#define WINDOWS_XP_SP2 0x04
+#define WINDOWS_2003 0x08
+#define WINDOWS_Vista 0x10
+#define WINDOWS_WIN7 0x11
+#define LINUX 0xF0
+
+DefinitionBlock (
+ "Platform.aml",
+ "DSDT",
+ 1,
+ "INTEL ",
+ "QuarkNcSocId",
+ 3)
+{
+ //
+ // Global Variables
+ //
+ Name(\GPIC, 0x0)
+
+ //
+ // Port 80
+ //
+ OperationRegion (DBG0, SystemIO, 0x80, 1)
+ Field (DBG0, ByteAcc, NoLock, Preserve)
+ { IO80,8 }
+
+ //
+ // Access CMOS range
+ //
+ OperationRegion (ACMS, SystemIO, 0x72, 2)
+ Field (ACMS, ByteAcc, NoLock, Preserve)
+ { INDX, 8, DATA, 8 }
+
+ //
+ // Global NVS Memory Block
+ //
+ OperationRegion (MNVS, SystemMemory, 0xFFFF0000, 512)
+ Field (MNVS, ByteAcc, NoLock, Preserve)
+ {
+ OSTP, 32,
+ CFGD, 32,
+ HPEA, 32, // HPET Enabled ?
+
+ P1BB, 32, // Pm1blkIoBaseAddress;
+ PBAB, 32, // PmbaIoBaseAddress;
+ GP0B, 32, // Gpe0blkIoBaseAddress;
+ GPAB, 32, // GbaIoBaseAddress;
+
+ SMBB, 32, // SmbaIoBaseAddress;
+ SPIB, 32, // SpiDmaIoBaseAddress;
+ WDTB, 32, // WdtbaIoBaseAddress;
+
+ HPTB, 32, // HpetBaseAddress;
+ HPTS, 32, // HpetSize;
+ PEXB, 32, // PciExpressBaseAddress;
+ PEXS, 32, // PciExpressSize;
+
+ RCBB, 32, // RcbaMmioBaseAddress;
+ RCBS, 32, // RcbaMmioSize;
+ APCB, 32, // IoApicBaseAddress;
+ APCS, 32, // IoApicSize;
+
+ TPMP, 32, // TpmPresent ?
+ }
+
+ OperationRegion (GPEB, SystemIO, 0x1100, 0x40) //GPE Block
+ Field (GPEB, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0x10),
+ SMIE, 32, // SMI Enable
+ SMIS, 32, // SMI Status
+ }
+
+ //
+ // Processor Objects
+ //
+ Scope(\_PR) {
+ //
+ // IO base will be updated at runtime with search key "PRIO"
+ //
+ Processor (CPU0, 0x01, 0x4F495250, 0x06) {}
+ }
+
+ //
+ // System Sleep States
+ //
+ Name (\_S0,Package (){0,0,0,0})
+ Name (\_S3,Package (){5,0,0,0})
+ Name (\_S4,Package (){6,0,0,0})
+ Name (\_S5,Package (){7,0,0,0})
+
+ //
+ // General Purpose Event
+ //
+ Scope(\_GPE)
+ {
+ //
+ // EGPE generated GPE
+ //
+ Method(_L0D, 0x0, NotSerialized)
+ {
+ //
+ // Check EGPE for this wake event
+ //
+ Notify (\_SB.SLPB, 0x02)
+
+ }
+
+ //
+ // GPIO generated GPE
+ //
+ Method(_L0E, 0x0, NotSerialized)
+ {
+ //
+ // Check GPIO for this wake event
+ //
+ Notify (\_SB.PWRB, 0x02)
+
+ }
+
+ //
+ // SCLT generated GPE
+ //
+ Method(_L0F, 0x0, NotSerialized)
+ {
+ //
+ // Check SCLT for this wake event
+ //
+ Notify (\_SB.PCI0.SDIO, 0x02)
+ Notify (\_SB.PCI0.URT0, 0x02)
+ Notify (\_SB.PCI0.USBD, 0x02)
+ Notify (\_SB.PCI0.EHCI, 0x02)
+ Notify (\_SB.PCI0.OHCI, 0x02)
+ Notify (\_SB.PCI0.URT1, 0x02)
+ Notify (\_SB.PCI0.ENT0, 0x02)
+ Notify (\_SB.PCI0.ENT1, 0x02)
+ Notify (\_SB.PCI0.SPI0, 0x02)
+ Notify (\_SB.PCI0.SPI1, 0x02)
+ Notify (\_SB.PCI0.GIP0, 0x02)
+
+ }
+
+ //
+ // Remote Management Unit generated GPE
+ //
+ Method(_L10, 0x0, NotSerialized)
+ {
+ //
+ // Check Remote Management Unit for this wake event.
+ //
+ }
+
+ //
+ // PCIE generated GPE
+ //
+ Method(_L11, 0x0, NotSerialized)
+ {
+ //
+ // Check PCIE for this wake event
+ //
+ Notify (\_SB.PCI0.PEX0, 0x02)
+ Notify (\_SB.PCI0.PEX1, 0x02)
+ }
+ }
+
+ //
+ // define Sleeping button as mentioned in ACPI spec 2.0
+ //
+ Device (\_SB.SLPB)
+ {
+ Name (_HID, EISAID ("PNP0C0E"))
+ Method (_PRW, 0, NotSerialized)
+ {
+ Return (Package (0x02) {0x0D,0x04})
+ }
+ }
+
+ //
+ // define Power Button
+ //
+ Device (\_SB.PWRB)
+ {
+ Name (_HID, EISAID ("PNP0C0C"))
+ Method (_PRW, 0, NotSerialized)
+ {
+ Return (Package (0x02) {0x0E,0x04})
+ }
+ }
+ //
+ // System Wake up
+ //
+ Method(_WAK, 1, Serialized)
+ {
+ // Do nothing here
+ Return (0)
+ }
+
+ //
+ // System sleep down
+ //
+ Method (_PTS, 1, NotSerialized)
+ {
+ // Get ready for S3 sleep
+ if (Lequal(Arg0,3))
+ {
+ Store(0xffffffff,SMIS) // clear SMI status
+ Store(SMIE, Local0) // SMI Enable
+ Or(Local0,0x4,SMIE) // Generate SMI on sleep
+ }
+ }
+
+ //
+ // Determing PIC mode
+ //
+ Method(\_PIC, 1, NotSerialized)
+ {
+ Store(Arg0,\GPIC)
+ }
+
+ //
+ // System Bus
+ //
+ Scope(\_SB)
+ {
+ Device(PCI0)
+ {
+ Name(_HID,EISAID ("PNP0A08")) // PCI Express Root Bridge
+ Name(_CID,EISAID ("PNP0A03")) // Compatible PCI Root Bridge
+
+ Name(_ADR,0x00000000) // Device (HI WORD)=0, Func (LO WORD)=0
+ Method (_INI)
+ {
+ Store(LINUX, OSTP) // Set the default os is Linux
+ If (CondRefOf (_OSI, local0))
+ {
+ //
+ //_OSI is supported, so it is WinXp or Win2003Server
+ //
+ If (\_OSI("Windows 2001"))
+ {
+ Store (WINDOWS_XP, OSTP)
+ }
+ If (\_OSI("Windows 2001 SP1"))
+ {
+ Store (WINDOWS_XP_SP1, OSTP)
+ }
+ If (\_OSI("Windows 2001 SP2"))
+ {
+ Store (WINDOWS_XP_SP2, OSTP)
+ }
+ If (\_OSI("Windows 2001.1"))
+ {
+ Store (WINDOWS_2003, OSTP)
+ }
+ If (\_OSI("Windows 2006"))
+ {
+ Store (WINDOWS_Vista, OSTP)
+ }
+ If (\_OSI("Windows 2009"))
+ {
+ Store (WINDOWS_WIN7, OSTP)
+ }
+ If (\_OSI("Linux"))
+ {
+ Store (LINUX, OSTP)
+ }
+ }
+ }
+
+ Include ("PciHostBridge.asi") // PCI0 Host bridge
+ Include ("QNC.asi") // QNC miscellaneous
+ Include ("PcieExpansionPrt.asi") // PCIe expansion bridges/devices
+ Include ("QuarkSouthCluster.asi") // Quark South Cluster devices
+ Include ("QNCLpc.asi") // LPC bridge device
+ Include ("QNCApic.asi") // QNC I/O Apic device
+ }
+ Include ("Tpm.asi") // TPM device
+ }
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNC.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNC.asi
new file mode 100644
index 0000000..a6a77e2
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNC.asi
@@ -0,0 +1,80 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ QNC.asi
+
+ Abstract:
+
+ QNC devices
+
+--*/
+
+#ifndef QNC_ASI
+#define QNC_ASI
+
+Device(IOCM) // I/O controller miscellaneous
+{
+ Name(_HID,EISAID("PNP0C02")) // System board resources device node ID
+
+ Name(CRS, ResourceTemplate()
+ {
+
+ // PCIEXBAR memory range
+ Memory32Fixed(ReadOnly, 0, 0, FIX1)
+
+ // RCRB memory range
+ Memory32Fixed(ReadOnly, 0, 0, FIX2)
+
+ // Option ROM shadow memory range
+ Memory32Fixed(ReadOnly, 0x000C0000, 0x20000)
+
+ // BIOS ROM shadow memory range
+ Memory32Fixed(ReadOnly, 0x000E0000, 0x20000)
+
+ // BIOS Firmware just below 4GByte of memory 8MBytes
+ Memory32Fixed(ReadOnly, 0xFF800000, 0x800000)
+ }
+ )
+
+ Method (_CRS, 0, NotSerialized) {
+ CreateDWordField (CRS, ^FIX1._BAS, MBR0)
+ Store(\PEXB, MBR0)
+ CreateDWordField (CRS, ^FIX1._LEN, MBR1)
+ Store(\PEXS, MBR1)
+ CreateDWordField (CRS, ^FIX2._BAS, MBR2)
+ Store(\RCBB, MBR2)
+ CreateDWordField (CRS, ^FIX2._LEN, MBR3)
+ Store(\RCBS, MBR3)
+ Return (CRS)
+ }
+}
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCApic.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCApic.asi
new file mode 100644
index 0000000..b3ef54a
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCApic.asi
@@ -0,0 +1,63 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ QNCApic.asi
+
+ Abstract:
+
+ QNC I/O Apic devices
+
+--*/
+
+#ifndef QNC_APIC_ASI
+#define QNC_APIC_ASI
+
+Device(APIC)
+{
+ Name(_HID,EISAID("PNP0003")) // APIC resources
+
+ Name(CRS, ResourceTemplate()
+ {
+ Memory32Fixed(ReadOnly, 0, 0, FIX1) // IO APIC
+ }
+ )
+
+ Method (_CRS, 0, NotSerialized) {
+ CreateDWordField (CRS, ^FIX1._BAS, MBR0)
+ Store(\APCB, MBR0)
+ CreateDWordField (CRS, ^FIX1._LEN, MBR1)
+ Store(\APCS, MBR1)
+ Return (CRS)
+ }
+}
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCLpc.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCLpc.asi
new file mode 100644
index 0000000..f829248
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCLpc.asi
@@ -0,0 +1,54 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ QNCLpc.asi
+
+ Abstract:
+
+ Lpc devices and control methods
+
+--*/
+
+
+#ifndef QNC_LPC_ASI
+#define QNC_LPC_ASI
+
+Device(LPC)
+{
+ Name(_ADR,0x001f0000) // Device (HI WORD)=31, Func (LO WORD)=0
+
+ Include ("PciIrq.asi") // PCI routing control methods
+ Include ("LpcDev.asi") // Static Lpc device resource declaration
+}
+
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QuarkSouthCluster.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QuarkSouthCluster.asi
new file mode 100644
index 0000000..ea9bebb
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QuarkSouthCluster.asi
@@ -0,0 +1,121 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ QuarkSouthCluster.asi
+
+ Abstract:
+
+ Quark South Cluster Devices
+
+--*/
+
+#ifndef QuarkSouthCluster_asi
+#define QuarkSouthCluster_asi
+
+Device (SDIO) // SDIO [Bus 0, Device 20, Function 0]
+{
+ Name(_ADR,0x00140000) // Device (HI WORD)=20, Func (LO WORD)=0
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (URT0) // UART0 [Bus 0, Device 20, Function 1]
+{
+ Name(_ADR,0x00140001) // Device (HI WORD)=20, Func (LO WORD)=1
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (USBD) // USB Device [Bus 0, Device 20, Function 2]
+{
+ Name(_ADR,0x00140002) // Device (HI WORD)=20, Func (LO WORD)=2
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (EHCI) // EHCI [Bus 0, Device 20, Function 3]
+{
+ Name(_ADR,0x00140003) // Device (HI WORD)=20, Func (LO WORD)=3
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (OHCI) // OHCI [Bus 0, Device 20, Function 4]
+{
+ Name(_ADR,0x00140004) // Device (HI WORD)=20, Func (LO WORD)=4
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (URT1) // UART1 [Bus 0, Device 20, Function 5]
+{
+ Name(_ADR,0x00140005) // Device (HI WORD)=20, Func (LO WORD)=5
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (ENT0) // Ethernet0 [Bus 0, Device 20, Function 6]
+{
+ Name(_ADR,0x00140006) // Device (HI WORD)=20, Func (LO WORD)=6
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (ENT1) // Ethernet1 [Bus 0, Device 20, Function 7]
+{
+ Name(_ADR,0x00140007) // Device (HI WORD)=20, Func (LO WORD)=7
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (SPI0) // SPI0 [Bus 0, Device 21, Function 0]
+{
+ Name(_ADR,0x00150000) // Device (HI WORD)=21, Func (LO WORD)=0
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (SPI1) // SPI1 [Bus 0, Device 21, Function 1]
+{
+ Name(_ADR,0x00150001) // Device (HI WORD)=21, Func (LO WORD)=1
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (GIP0) // I2C/GPIO [Bus 0, Device 21, Function 2]
+{
+ Name(_ADR,0x00150002) // Device (HI WORD)=21, Func (LO WORD)=2
+ Name(_STA,0xF) // Enabled, do Display
+ Name(_PRW,Package(){0x0F,0x03}) // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Tpm.asi b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Tpm.asi
new file mode 100644
index 0000000..a893b82
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Tpm.asi
@@ -0,0 +1,70 @@
+/** @file
+ The Infineon SLB9645 TPM ACPI definition block.
+ Provides TPM device info. and TPM presence check only.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+Device (TPM)
+{
+ //
+ // Define _HID as Infineon TPM Device, _CID as "PNP0C31" (defined in
+ // "Secure Startup-FVE and TPM Admin BIOS and Platform Requirements").
+ //
+ Name(_HID ,EISAID("INT3493"))
+ Name(_CID, EISAID("PNP0C31"))
+
+ //
+ // Readable name of this device.
+ //
+ Name (_STR, Unicode ("Infineon TPM 1.2 Device (SLB9645TT1.2)"))
+
+ //
+ // Return the resource consumed by TPM device.
+ // Quark validated ACPI compiler does not support ACPI 5.0.
+ // Hence comment out _CRS!
+ //
+ //Name (_CRS, ResourceTemplate () {
+ // I2cSerialBus (0x20, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\_SB.TPM", 0, ResourceConsumer,,)
+ //})
+
+ //
+ // Check if TPM present.
+ //
+ Method (_STA, 0)
+ {
+ if (LEqual (TPMP, 0))
+ {
+ return (0)
+ }
+ Return (0x0f)
+ }
+
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.aslc b/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.aslc
new file mode 100644
index 0000000..56f406a
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.aslc
@@ -0,0 +1,104 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Facs.aslc
+
+
+Abstract:
+
+ This file contains the FACS structure definition.
+
+--*/
+
+//
+// Statements that include other files
+//
+#include "Facs.h"
+
+EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE FACS = {
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+ sizeof (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE),
+
+ //
+ // Hardware Signature will be updated at runtime
+ //
+ 0x00000000,
+ EFI_ACPI_FIRMWARE_WAKING_VECTOR,
+ EFI_ACPI_GLOBAL_LOCK,
+ EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS,
+ EFI_ACPI_X_FIRMWARE_WAKING_VECTOR,
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+};
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&FACS;
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.h b/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.h
new file mode 100644
index 0000000..716f543
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.h
@@ -0,0 +1,60 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Facs.h
+
+Abstract:
+
+ This file describes the contents of the ACPI Firmware ACPI Control Structure (FACS)
+ . Some additional ACPI values are defined in Acpi10.h, Acpi20.h, and Acpi30.h
+ All changes to the FACS contents should be done in this file.
+
+--*/
+
+#ifndef _FACS_H_
+#define _FACS_H_
+
+//
+// Statements that include other files
+//
+#include <IndustryStandard/Acpi.h>
+
+//
+// FACS Definitions
+//
+#define EFI_ACPI_FIRMWARE_WAKING_VECTOR 0x00000000
+#define EFI_ACPI_GLOBAL_LOCK 0x00000000
+
+#define EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS 0x00000000
+#define EFI_ACPI_X_FIRMWARE_WAKING_VECTOR 0x0000000000000000
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.h b/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.h
new file mode 100644
index 0000000..7403200
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.h
@@ -0,0 +1,133 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Fadt.h
+
+Abstract:
+
+ This file describes the contents of the ACPI Fixed ACPI Description Table (FADT)
+ . Some additional ACPI values are defined in Acpi10.h, Acpi20.h, and Acpi30.h
+ All changes to the FADT contents should be done in this file.
+
+--*/
+
+#ifndef _FADT_H_
+#define _FADT_H_
+
+//
+// Statements that include other files
+//
+#include <IndustryStandard/Acpi.h>
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID 'I','N','T','E','L',' ' // OEMID 6 bytes long
+#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('T','I','A','N','O',' ',' ',' ') // OEM table id 8 bytes long
+#define EFI_ACPI_OEM_REVISION 0x00000003
+#define EFI_ACPI_CREATOR_ID SIGNATURE_32('I','N','T','L')
+#define EFI_ACPI_CREATOR_REVISION 0x0100000D
+
+//
+// FADT Definitions
+//
+#define PM_PROFILE 0x01
+#define INT_MODEL 0x01
+#define SCI_INT_VECTOR 0x0009
+#define ACPI_ENABLE 0x0a0
+#define ACPI_DISABLE 0x0a1
+#define S4BIOS_REQ 0x00
+#define PM1_EVT_LEN 0x04
+#define PM1_CNT_LEN 0x02
+#define PM2_CNT_LEN 0x00
+#define PM_TM_LEN 0x04
+#define GPE0_BLK_LEN 0x08
+#define GPE1_BLK_LEN 0x00
+#define GPE1_BASE 0x00
+#define RESERVED 0x00
+#define P_LVL2_LAT 0x0065
+#define P_LVL3_LAT 0x03e9
+#define FLUSH_SIZE 0x0400
+#define FLUSH_STRIDE 0x0010
+#define DUTY_OFFSET 0x01
+#define DUTY_WIDTH 0x03
+#define DAY_ALRM 0x00
+#define MON_ALRM 0x00
+#define CENTURY 0x00
+#define IAPC_BOOT_ARCH EFI_ACPI_2_0_LEGACY_DEVICES
+#define FLAG (EFI_ACPI_1_0_WBINVD | EFI_ACPI_1_0_PROC_C1 | EFI_ACPI_1_0_SLP_BUTTON | EFI_ACPI_1_0_RTC_S4)
+#define FLAG2 (EFI_ACPI_2_0_WBINVD | EFI_ACPI_2_0_PROC_C1 | EFI_ACPI_2_0_PWR_BUTTON | EFI_ACPI_2_0_SLP_BUTTON | EFI_ACPI_2_0_RTC_S4 | EFI_ACPI_2_0_RESET_REG_SUP | EFI_ACPI_3_0_USE_PLATFORM_CLOCK)
+
+#define RESET_REG_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define RESET_REG_BIT_WIDTH 0x08
+#define RESET_REG_BIT_OFFSET 0x00
+#define RESET_REG_ADDRESS 0x0000000000000CF9
+#define RESET_VALUE 0x02
+
+#define ACPI_RUNTIME_UPDATE 0x00
+
+#define PM1a_EVT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define PM1a_EVT_BLK_BIT_WIDTH 0x20
+#define PM1a_EVT_BLK_BIT_OFFSET 0x00
+
+#define PM1b_EVT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define PM1b_EVT_BLK_BIT_WIDTH 0x00
+#define PM1b_EVT_BLK_BIT_OFFSET 0x00
+#define PM1b_EVT_BLK_ADDRESS 0x0000000000000000
+
+#define PM1a_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define PM1a_CNT_BLK_BIT_WIDTH 0x10
+#define PM1a_CNT_BLK_BIT_OFFSET 0x00
+
+#define PM1b_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define PM1b_CNT_BLK_BIT_WIDTH 0x00
+#define PM1b_CNT_BLK_BIT_OFFSET 0x00
+#define PM1b_CNT_BLK_ADDRESS 0x0000000000000000
+
+#define PM2_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define PM2_CNT_BLK_BIT_WIDTH 0x00
+#define PM2_CNT_BLK_BIT_OFFSET 0x00
+#define PM2_CNT_BLK_ADDRESS 0x0000000000000000
+
+#define PM_TMR_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define PM_TMR_BLK_BIT_WIDTH 0x20
+#define PM_TMR_BLK_BIT_OFFSET 0x00
+
+#define GPE0_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define GPE0_BLK_BIT_WIDTH 0x40
+#define GPE0_BLK_BIT_OFFSET 0x00
+
+#define GPE1_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define GPE1_BLK_BIT_WIDTH 0x00
+#define GPE1_BLK_BIT_OFFSET 0x00
+#define GPE1_BLK_ADDRESS 0x0000000000000000
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt1.0.aslc b/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt1.0.aslc
new file mode 100644
index 0000000..5269270
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt1.0.aslc
@@ -0,0 +1,106 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Fadt1.0.aslc
+
+Abstract:
+ This file describes the contents of the ACPI Fixed ACPI Description Table
+ (FADT). Some additional ACPI values are defined in Acpi1_0.h and Acpi2_0.h.
+ All changes to the FADT contents should be done in this file.
+
+--*/
+
+#include "Fadt.h"
+
+EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE FADT = {
+ EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE),
+ EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+ 0, // to make sum of entire table == 0
+ EFI_ACPI_OEM_ID, // OEMID is a 6 bytes long field
+ EFI_ACPI_OEM_TABLE_ID, // OEM table identification(8 bytes long)
+ EFI_ACPI_OEM_REVISION, // OEM revision number
+ EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID
+ EFI_ACPI_CREATOR_REVISION, // ASL compiler revision number
+ 0, // Physical addesss of FACS
+ 0, // Physical address of DSDT
+ INT_MODEL, // System Interrupt Model
+ RESERVED, // reserved
+ SCI_INT_VECTOR, // System vector of SCI interrupt
+ SMI_CMD_IO_PORT, // Port address of SMI command port
+ ACPI_ENABLE, // value to write to port smi_cmd to enable ACPI
+ ACPI_DISABLE, // value to write to port smi_cmd to disable ACPI
+ S4BIOS_REQ, // Value to write to SMI CMD port to enter the S4BIOS state
+ RESERVED, // reserved - must be zero
+ PM1a_EVT_BLK_ADDRESS, // Port address of Power Mgt 1a Event Reg Blk
+ PM1b_EVT_BLK_ADDRESS, // Port address of Power Mgt 1b Event Reg Blk
+ PM1a_CNT_BLK_ADDRESS, // Port address of Power Mgt 1a Ctrl Reg Blk
+ PM1b_CNT_BLK_ADDRESS, // Port address of Power Mgt 1b Ctrl Reg Blk
+ PM2_CNT_BLK_ADDRESS, // Port address of Power Mgt 2 Ctrl Reg Blk
+ PM_TMR_BLK_ADDRESS, // Port address of Power Mgt Timer Ctrl Reg Blk
+ GPE0_BLK_ADDRESS, // Port addr of General Purpose Event 0 Reg Blk
+ GPE1_BLK_ADDRESS, // Port addr of General Purpose Event 1 Reg Blk
+ PM1_EVT_LEN, // Byte Length of ports at pm1X_evt_blk
+ PM1_CNT_LEN, // Byte Length of ports at pm1X_cnt_blk
+ PM2_CNT_LEN, // Byte Length of ports at pm2_cnt_blk
+ PM_TM_LEN, // Byte Length of ports at pm_tm_blk
+ GPE0_BLK_LEN, // Byte Length of ports at gpe0_blk
+ GPE1_BLK_LEN, // Byte Length of ports at gpe1_blk
+ GPE1_BASE, // offset in gpe model where gpe1 events start
+ RESERVED, // reserved
+ P_LVL2_LAT, // worst case HW latency to enter/exit C2 state
+ P_LVL3_LAT, // worst case HW latency to enter/exit C3 state
+ FLUSH_SIZE, // Size of area read to flush caches
+ FLUSH_STRIDE, // Stride used in flushing caches
+ DUTY_OFFSET, // bit location of duty cycle field in p_cnt reg
+ DUTY_WIDTH, // bit width of duty cycle field in p_cnt reg
+ DAY_ALRM, // index to day-of-month alarm in RTC CMOS RAM
+ MON_ALRM, // index to month-of-year alarm in RTC CMOS RAM
+ CENTURY, // index to century in RTC CMOS RAM
+ RESERVED, // reserved
+ RESERVED, // reserved
+ RESERVED, // reserved
+ FLAG
+};
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&FADT;
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt2.0.aslc b/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt2.0.aslc
new file mode 100644
index 0000000..829de27
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt2.0.aslc
@@ -0,0 +1,166 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Fadt2.0.aslc
+
+Abstract:
+ This file describes the contents of the ACPI Fixed ACPI Description Table
+ (FADT). Some additional ACPI values are defined in Acpi1_0.h and Acpi2_0.h.
+ All changes to the FADT contents should be done in this file.
+
+--*/
+
+#include "Fadt.h"
+
+EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE FADT = {
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE),
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+ 0, // to make sum of entire table == 0
+ EFI_ACPI_OEM_ID, // OEMID is a 6 bytes long field
+ EFI_ACPI_OEM_TABLE_ID,// OEM table identification(8 bytes long)
+ EFI_ACPI_OEM_REVISION,// OEM revision number
+ EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID
+ EFI_ACPI_CREATOR_REVISION, // ASL compiler revision number
+ 0, // Physical addesss of FACS
+ 0, // Physical address of DSDT
+ RESERVED, // reserved
+ PM_PROFILE, // Preferred powermanagement profile
+ SCI_INT_VECTOR, // System vector of SCI interrupt
+ ACPI_RUNTIME_UPDATE, // Port address of SMI command port
+ ACPI_ENABLE, // value to write to port smi_cmd to enable ACPI
+ ACPI_DISABLE, // value to write to port smi_cmd to disable ACPI
+ S4BIOS_REQ, // Value to write to SMI CMD port to enter the S4BIOS state
+ RESERVED, // reserved - must be zero
+ ACPI_RUNTIME_UPDATE, // Port address of Power Mgt 1a Event Reg Blk
+ PM1b_EVT_BLK_ADDRESS, // Port address of Power Mgt 1b Event Reg Blk
+ ACPI_RUNTIME_UPDATE, // Port address of Power Mgt 1a Ctrl Reg Blk
+ PM1b_CNT_BLK_ADDRESS, // Port address of Power Mgt 1b Ctrl Reg Blk
+ ACPI_RUNTIME_UPDATE, // Port address of Power Mgt 2 Ctrl Reg Blk
+ ACPI_RUNTIME_UPDATE, // Port address of Power Mgt Timer Ctrl Reg Blk
+ ACPI_RUNTIME_UPDATE, // Port addr of General Purpose Event 0 Reg Blk
+ GPE1_BLK_ADDRESS, // Port addr of General Purpose Event 1 Reg Blk
+ PM1_EVT_LEN, // Byte Length of ports at pm1X_evt_blk
+ PM1_CNT_LEN, // Byte Length of ports at pm1X_cnt_blk
+ PM2_CNT_LEN, // Byte Length of ports at pm2_cnt_blk
+ PM_TM_LEN, // Byte Length of ports at pm_tm_blk
+ GPE0_BLK_LEN, // Byte Length of ports at gpe0_blk
+ GPE1_BLK_LEN, // Byte Length of ports at gpe1_blk
+ GPE1_BASE, // offset in gpe model where gpe1 events start
+ RESERVED, // reserved
+ P_LVL2_LAT, // worst case HW latency to enter/exit C2 state
+ P_LVL3_LAT, // worst case HW latency to enter/exit C3 state
+ FLUSH_SIZE, // Size of area read to flush caches
+ FLUSH_STRIDE, // Stride used in flushing caches
+ DUTY_OFFSET, // bit location of duty cycle field in p_cnt reg
+ DUTY_WIDTH, // bit width of duty cycle field in p_cnt reg
+ DAY_ALRM, // index to day-of-month alarm in RTC CMOS RAM
+ MON_ALRM, // index to month-of-year alarm in RTC CMOS RAM
+ CENTURY, // index to century in RTC CMOS RAM
+ IAPC_BOOT_ARCH, // IA-PC Boot Architecture Flags
+ RESERVED, // reserved
+ FLAG2, // Fixed feature flags
+
+ RESET_REG_ADDRESS_SPACE_ID, // Address of the reset register
+ RESET_REG_BIT_WIDTH,
+ RESET_REG_BIT_OFFSET,
+ RESERVED,
+ RESET_REG_ADDRESS,
+ RESET_VALUE, // Value to write to the RESET_REG port
+ RESERVED,
+ RESERVED,
+ RESERVED,
+
+ 0, // 64Bit physical addesss of FACS
+ 0, // 64Bit physical address of DSDT
+
+ PM1a_EVT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 1a Event Reg Blk
+ PM1a_EVT_BLK_BIT_WIDTH,
+ PM1a_EVT_BLK_BIT_OFFSET,
+ RESERVED,
+ ACPI_RUNTIME_UPDATE,
+
+ PM1b_EVT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 1b Event Reg Blk
+ PM1b_EVT_BLK_BIT_WIDTH,
+ PM1b_EVT_BLK_BIT_OFFSET,
+ RESERVED,
+ PM1b_EVT_BLK_ADDRESS,
+
+ PM1a_CNT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 1a Ctrl Reg Blk
+ PM1a_CNT_BLK_BIT_WIDTH,
+ PM1a_CNT_BLK_BIT_OFFSET,
+ RESERVED,
+ ACPI_RUNTIME_UPDATE,
+
+ PM1b_CNT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 1b Ctrl Reg Blk
+ PM1b_CNT_BLK_BIT_WIDTH,
+ PM1b_CNT_BLK_BIT_OFFSET,
+ RESERVED,
+ PM1b_CNT_BLK_ADDRESS,
+
+ PM2_CNT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 2 Ctrl Reg Blk
+ PM2_CNT_BLK_BIT_WIDTH,
+ PM2_CNT_BLK_BIT_OFFSET,
+ RESERVED,
+ ACPI_RUNTIME_UPDATE,
+
+ PM_TMR_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt Timer Ctrl Reg Blk
+ PM_TMR_BLK_BIT_WIDTH,
+ PM_TMR_BLK_BIT_OFFSET,
+ RESERVED,
+ ACPI_RUNTIME_UPDATE,
+
+ GPE0_BLK_ADDRESS_SPACE_ID, // Extended Port address of General Purpose Event 0 Reg Blk
+ GPE0_BLK_BIT_WIDTH,
+ GPE0_BLK_BIT_OFFSET,
+ RESERVED,
+ ACPI_RUNTIME_UPDATE,
+
+ GPE1_BLK_ADDRESS_SPACE_ID, // Extended Port address of General Purpose Event 1 Reg Blk
+ GPE1_BLK_BIT_WIDTH,
+ GPE1_BLK_BIT_OFFSET,
+ RESERVED,
+ GPE1_BLK_ADDRESS
+};
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&FADT;
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.aslc b/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.aslc
new file mode 100644
index 0000000..588a251
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.aslc
@@ -0,0 +1,96 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Hpet.aslc
+
+Abstract:
+
+ This file contains a structure definition for the ACPI 1.0 High Precision Event Timer
+ Description Table (HPET). The contents of this file should only be modified
+ for bug fixes, no porting is required. The table layout is defined in
+ HighPrecisionEventTimerTable.h and the table contents are defined in Acpi1.0.h and Hpet.h.
+
+--*/
+
+//
+// Statements that include other files
+//
+
+#include "Hpet.h"
+
+//
+// High Precision Event Timer Table
+// Please modify all values in Hpet.h only.
+//
+
+EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER Hpet = {
+ EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER),
+ EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION,
+
+ //
+ // Checksum will be updated at runtime
+ //
+ 0x00,
+
+ //
+ // It is expected that these values will be updated at runtime
+ //
+ ' ', ' ', ' ', ' ', ' ', ' ',
+
+ 0,
+ EFI_ACPI_OEM_HPET_REVISION,
+ 0,
+ 0,
+
+ EFI_ACPI_EVENT_TIMER_BLOCK_ID,
+ EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS_SPACE_ID,
+ EFI_ACPI_EVENT_TIMER_BLOCK_BIT_WIDTH,
+ EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET,
+ EFI_ACPI_EVENT_TIMER_ACCESS_SIZE,
+ ACPI_RUNTIME_UPDATE,
+ EFI_ACPI_HPET_NUMBER,
+ EFI_ACPI_MIN_CLOCK_TICK,
+ EFI_ACPI_HPET_ATTRIBUTES
+};
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&Hpet;
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.h b/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.h
new file mode 100644
index 0000000..f403d78
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.h
@@ -0,0 +1,76 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Hpet.h
+
+Abstract:
+
+ This file describes the contents of the ACPI High Precision Event Timer Description Table
+ (HPET). Some additional ACPI values are defined in Acpi10.h, Acpi20.h, and Acpi30.h
+ All changes to the HPET contents should be done in this file.
+
+--*/
+
+#ifndef _HPET_H_
+#define _HPET_H_
+
+//
+// Statements that include other files
+//
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+
+//
+// HPET Definitions
+//
+
+#define EFI_ACPI_OEM_HPET_REVISION 0x00000001
+
+#define EFI_ACPI_EVENT_TIMER_BLOCK_ID 0x8086A201
+
+#define ACPI_RUNTIME_UPDATE 0x00
+
+//
+// Event Timer Block Base Address Information
+//
+#define EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS_SPACE_ID EFI_ACPI_3_0_SYSTEM_MEMORY
+#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_WIDTH 0x00
+#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET 0x00
+#define EFI_ACPI_EVENT_TIMER_ACCESS_SIZE 0x00
+
+#define EFI_ACPI_HPET_NUMBER 0x00
+
+#define EFI_ACPI_MIN_CLOCK_TICK 0x0080
+
+#define EFI_ACPI_HPET_ATTRIBUTES 0x00
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.aslc b/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.aslc
new file mode 100644
index 0000000..7bcd1b4
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.aslc
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Mcfg.aslc
+
+Abstract:
+
+ This file contains a structure definition for the ACPI Memory Mapped Configuration
+ Address Space table (MCFG). Any changes to the number of entries in the table require
+ updating the structure count in Mcfg.h and then adding the structure to the
+ MCFG defined in this file. The table layout is defined in Mcfg.h and the
+ table contents are defined in the MemoryMappedConfigurationSpaceAccessTable.h.
+
+--*/
+
+//
+// Statements that include other files
+//
+
+#include "Mcfg.h"
+
+//
+// Multiple APIC Description Table
+//
+
+EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE Mcfg = {
+ EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE),
+ EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+
+ //
+ // Checksum will be updated at runtime
+ //
+ 0x00,
+
+ //
+ // It is expected that these values will be programmed at runtime
+ //
+ ' ', ' ', ' ', ' ', ' ', ' ',
+
+ 0,
+ EFI_ACPI_OEM_MCFG_REVISION,
+ 0,
+ 0,
+
+ //
+ // Reserved
+ //
+ 0x0000000000000000,
+
+ //
+ // MCFG specific fields
+ //
+
+ 0x00000000, // BaseAddress (will be updated at runtime)
+ 0x0000, // PciSegmentGroupNumber
+ 0x00, // StartBusNumber
+ 0x1F, // EndBusNumber
+ 0x00000000 // Reserved
+
+};
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&Mcfg;
+}
diff --git a/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.h b/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.h
new file mode 100644
index 0000000..380619e
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.h
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Mcfg.h
+
+Abstract:
+
+ This file describes the contents of the ACPI Memory Mapped Configuration
+ Space Access Table (MCFG). Some additional ACPI values are defined in Acpi10.h,
+ Acpi20.h, and Acpi30.h.
+
+--*/
+
+#ifndef _MCFG_H_
+#define _MCFG_H_
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+//
+// MCFG Definitions
+//
+
+#define EFI_ACPI_OEM_MCFG_REVISION 0x00000001
+
+//
+// Define the number of allocation structures so that we can build the table structure.
+//
+
+#define EFI_ACPI_ALLOCATION_STRUCTURE_COUNT 1
+
+//
+// MCFG structure
+//
+
+//
+// Ensure proper structure formats
+//
+#pragma pack (1)
+
+//
+// MCFG Table structure
+//
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT64 Reserved;
+#if EFI_ACPI_ALLOCATION_STRUCTURE_COUNT > 0
+ EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE AllocationStructure[EFI_ACPI_ALLOCATION_STRUCTURE_COUNT];
+#endif
+} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE;
+
+#pragma pack ()
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.c b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.c
new file mode 100644
index 0000000..4d92c01
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.c
@@ -0,0 +1,1435 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ AcpiPciUpdate.c
+
+Abstract:
+
+ Update the _PRT and _PRW method for pci devices
+
+--*/
+#include "AcpiPlatform.h"
+
+PCI_DEVICE_INFO *mQNCPciInfo = NULL;
+
+/**
+ Init Pci Device Structure
+ @param mConfigData - Pointer of Pci Device information Structure
+
+**/
+VOID
+InitPciDeviceInfoStructure (
+ PCI_DEVICE_SETTING *mConfigData
+ )
+{
+ //
+ // Return 0 given that function unsupported.
+ // Would need to parse ACPI tables and build mQNCPciInfo above
+ // with found _PRT & _PRW methods for PCI devices.
+ //
+ mConfigData->PciDeviceInfoNumber = 0;
+}
+
+/**
+ return Integer value.
+
+ @param Data - AML data buffer
+ @param Integer - integer value.
+
+ @return Data size processed.
+**/
+UINTN
+SdtGetInteger (
+ IN UINT8 *Data,
+ OUT UINT64 *Integer
+ )
+{
+ *Integer = 0;
+ switch (*Data) {
+ case AML_ZERO_OP:
+ return 1;
+ case AML_ONE_OP:
+ *Integer = 1;
+ return 1;
+ case AML_ONES_OP:
+ *Integer = (UINTN)-1;
+ return 1;
+ case AML_BYTE_PREFIX:
+ CopyMem (Integer, Data + 1, sizeof(UINT8));
+ return 1 + sizeof(UINT8);
+ case AML_WORD_PREFIX:
+ CopyMem (Integer, Data + 1, sizeof(UINT16));
+ return 1 + sizeof(UINT16);
+ case AML_DWORD_PREFIX:
+ CopyMem (Integer, Data + 1, sizeof(UINT32));
+ return 1 + sizeof(UINT32);
+ case AML_QWORD_PREFIX:
+ CopyMem (Integer, Data + 1, sizeof(UINT64));
+ return 1 + sizeof(UINT64);
+ default:
+ // Something wrong
+ ASSERT (FALSE);
+ return 1;
+ }
+}
+
+
+/**
+ Check if this handle has expected opcode.
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param Handle ACPI handle
+ @param OpCode Expected OpCode
+ @param SubOpCode Expected SubOpCode
+
+ @retval TURE This handle has expected opcode
+ @retval FALSE This handle does not have expected opcode
+**/
+BOOLEAN
+SdtIsThisTypeObject (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE Handle,
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+
+ Status = AcpiSdt->GetOption (Handle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+ if (OpCode == AML_EXT_OP) {
+ if (Data[1] == SubOpCode) {
+ return TRUE;
+ }
+ } else {
+ if (Data[0] == OpCode) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Check if this handle has expected name and name value.
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param Handle ACPI handle
+ @param Name Expected name
+ @param Value Expected name value
+
+ @retval TURE This handle has expected name and name value.
+ @retval FALSE This handle does not have expected name and name value.
+**/
+BOOLEAN
+SdtIsNameIntegerValueEqual (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE Handle,
+ IN CHAR8 *Name,
+ IN UINT64 Value
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINT64 Integer;
+
+ Status = AcpiSdt->GetOption (Handle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
+
+ if (CompareMem (Data, Name, 4) != 0) {
+ return FALSE;
+ }
+
+ //
+ // Name match check object
+ //
+ Status = AcpiSdt->GetOption (Handle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+
+ Integer = 0;
+ SdtGetInteger (Data, &Integer);
+ if (Integer != Value) {
+ return FALSE;
+ }
+
+ // All match
+ return TRUE;
+}
+
+/**
+ Check if this handle's children has expected name and name value.
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param ParentHandle ACPI parent handle
+ @param Name Expected name
+ @param Value Expected name value
+
+ @retval TURE This handle's children has expected name and name value.
+ @retval FALSE This handle's children does not have expected name and name value.
+**/
+BOOLEAN
+SdtCheckNameIntegerValue (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE ParentHandle,
+ IN CHAR8 *Name,
+ IN UINT64 Value
+ )
+{
+ EFI_ACPI_HANDLE PreviousHandle;
+ EFI_ACPI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ Handle = NULL;
+ while (TRUE) {
+ PreviousHandle = Handle;
+ Status = AcpiSdt->GetChild (ParentHandle, &Handle);
+ ASSERT_EFI_ERROR (Status);
+
+ if (PreviousHandle != NULL) {
+ Status = AcpiSdt->Close (PreviousHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Done
+ //
+ if (Handle == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Check this name
+ //
+ if (SdtIsThisTypeObject (AcpiSdt, Handle, AML_NAME_OP, 0)) {
+ if (SdtIsNameIntegerValueEqual (AcpiSdt, Handle, Name, Value)) {
+ return TRUE;
+ }
+ }
+ }
+
+ //
+ // Should not run here
+ //
+}
+
+/**
+ Convert the pci address from VPD (bus,dev,fun) into the address that acpi table
+ can recognize.
+
+ @param PciAddress Pci address from VPD
+
+ @retval return the address that acpi table can recognize
+**/
+UINT32
+SdtConvertToAcpiPciAdress (
+ IN UINT32 PciAddress
+ )
+{
+ UINT32 ReturnAddress;
+
+ ReturnAddress = ((PciAddress & 0x0000FF00) << 8) | (PciAddress & 0x000000FF);
+
+ if ((PciAddress & 0x000000FF) == 0x000000FF)
+ ReturnAddress |= 0x0000FFFF;
+
+ return ReturnAddress;
+}
+
+/**
+ return AML NameString size.
+
+ @param Buffer - AML name string
+
+ @return AML name string size
+**/
+UINTN
+SdtGetNameStringSize (
+ IN UINT8 *Buffer
+ )
+{
+ UINTN SegCount;
+ UINTN Length;
+ UINT8 *Name;
+
+ Name = Buffer;
+ Length = 0;
+
+ //
+ // Parse root or prefix
+ //
+ if (*Buffer == AML_ROOT_CHAR) {
+ //
+ // RootChar
+ //
+ Buffer ++;
+ Length ++;
+ } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
+ //
+ // ParentPrefixChar
+ //
+ Buffer ++;
+ Length ++;
+ while (*Buffer == AML_PARENT_PREFIX_CHAR) {
+ Buffer ++;
+ Length ++;
+ }
+ }
+
+ //
+ // Parse name segment
+ //
+ if (*Buffer == AML_DUAL_NAME_PREFIX) {
+ //
+ // DualName
+ //
+ Buffer ++;
+ Length ++;
+ SegCount = 2;
+ } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
+ //
+ // MultiName
+ //
+ Buffer ++;
+ Length ++;
+ SegCount = *Buffer;
+ Buffer ++;
+ Length ++;
+ } else if (*Buffer == 0) {
+ //
+ // NULL Name
+ //
+ SegCount = 0;
+ Length ++;
+ } else {
+ //
+ // NameSeg
+ //
+ SegCount = 1;
+ }
+
+ Buffer += 4 * SegCount;
+ Length += 4 * SegCount;
+
+ return Length;
+}
+
+/**
+ The routine to check if this device is PCI root bridge.
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param DeviceHandle ACPI device handle
+ @param Context Context info - not used here
+
+ @retval TRUE This is PCI root bridge
+ @retval FALSE This is not PCI root bridge
+**/
+BOOLEAN
+SdtFindRootBridgeHandle (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE CheckHandle,
+ IN VOID *Context
+ )
+{
+ BOOLEAN Result;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+ EFI_STATUS Status;
+
+ if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))
+ return FALSE;
+
+ Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_HID", (UINT64)0x080AD041); // PNP0A08
+ if (!Result) {
+ Result = SdtCheckNameIntegerValue (AcpiSdt, CheckHandle, "_CID", (UINT64)0x030AD041); // PNP0A03
+ if (!Result) {
+ return Result;
+ }
+ }
+
+ //
+ // Found
+ //
+ Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
+
+ return Result;
+}
+
+
+/**
+ The routine to check if this device is wanted.
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param DeviceHandle ACPI device handle
+ @param Context Context info - not used here
+
+ @retval TRUE This is PCI device wanted
+ @retval FALSE This is not PCI device wanted
+**/
+BOOLEAN
+SdtFindPciDeviceHandle (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE CheckHandle,
+ IN VOID *Context
+ )
+{
+ BOOLEAN Result;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+ EFI_STATUS Status;
+
+ if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))
+ return FALSE;
+
+ Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_ADR", (UINT64)*(UINT32 *)Context);
+ if (!Result) {
+ return Result;
+ }
+
+ //
+ // Found
+ //
+ Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
+
+ return Result;
+}
+
+/**
+ Go through the parent handle and find the handle which pass CheckHandleInfo.
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param ParentHandle ACPI parent handle
+ @param CheckHandleInfo The callback routine to check if this handle meet the requirement
+ @param Context The context of CheckHandleInfo
+
+ @return the handle which is first one can pass CheckHandleInfo.
+**/
+EFI_ACPI_HANDLE
+SdtGetHandleByScanAllChilds (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE ParentHandle,
+ IN CHECK_HANDLE_INFO CheckHandleInfo,
+ IN VOID *Context
+ )
+{
+ EFI_ACPI_HANDLE PreviousHandle;
+ EFI_ACPI_HANDLE Handle;
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE ReturnHandle;
+
+ //
+ // Use deep first algo to enumerate all ACPI object
+ //
+ Handle = NULL;
+ while (TRUE) {
+ PreviousHandle = Handle;
+ Status = AcpiSdt->GetChild (ParentHandle, &Handle);
+ ASSERT_EFI_ERROR (Status);
+
+ if (PreviousHandle != NULL) {
+ Status = AcpiSdt->Close (PreviousHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Done
+ //
+ if (Handle == NULL) {
+ return NULL;
+ }
+
+ //
+ // Check this handle
+ //
+ if (CheckHandleInfo (AcpiSdt, Handle, Context)) {
+ return Handle;
+ }
+
+ //
+ // Enumerate
+ //
+ ReturnHandle = SdtGetHandleByScanAllChilds (AcpiSdt, Handle, CheckHandleInfo, Context);
+ if (ReturnHandle != NULL) {
+ return ReturnHandle;
+ }
+ }
+
+ //
+ // Should not run here
+ //
+}
+
+
+/**
+ Check whether the INTx package is matched
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param INTxPkgHandle ACPI INTx package handle
+ @param PciAddress Acpi pci address
+ @param INTx Index of INTx pin
+ @param IsAPIC Tell whether the returned INTx package is for APIC or not
+
+ @retval TRUE the INTx package is matched
+ @retval FALSE the INTx package is not matched
+
+**/
+BOOLEAN
+SdtCheckINTxPkgIsMatch (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE INTxPkgHandle,
+ IN UINT32 PciAddress,
+ IN UINT8 INTx,
+ IN BOOLEAN *IsAPIC
+ )
+{
+ EFI_ACPI_HANDLE PreviousHandle;
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE MemberHandle;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINT64 CurrentPciAddress;
+ UINT64 CurrentINTx;
+ UINTN ChildSize;
+
+
+ //
+ // Check the pci address
+ //
+ MemberHandle = NULL;
+ Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (MemberHandle != NULL);
+
+ Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+ CurrentPciAddress = 0;
+ SdtGetInteger (Data, &CurrentPciAddress);
+
+ if (CurrentPciAddress != PciAddress) {
+
+ Status = AcpiSdt->Close (MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+ return FALSE;
+ }
+
+ //
+ // Check the pci interrupt pin
+ //
+ PreviousHandle = MemberHandle;
+ Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (MemberHandle != NULL);
+
+ if (PreviousHandle != NULL) {
+ Status = AcpiSdt->Close (PreviousHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+ CurrentINTx = 0;
+ ChildSize = SdtGetInteger (Data, &CurrentINTx);
+
+ Status = AcpiSdt->Close (MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ if (CurrentINTx != INTx)
+ return FALSE;
+
+ Data += ChildSize;
+
+ if (*Data == AML_BYTE_PREFIX)
+ Data += 1;
+
+ //
+ // Check the pci interrupt source
+ //
+ if (*Data != 0)
+ *IsAPIC = FALSE;
+ else
+ *IsAPIC = TRUE;
+
+ return TRUE;
+}
+
+
+
+
+/**
+ Get the wanted INTx package inside the parent package
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param ParentPkgHandle ACPI parent package handle
+ @param PciAddress Acpi pci address
+ @param INTx Index of INTx pin
+ @param INTxPkgHandle ACPI INTx package handle
+ @param IsAPIC Tell whether the returned INTx package is for APIC or not
+
+**/
+VOID
+SdtGetINTxPkgHandle (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE ParentPkgHandle,
+ IN UINT32 PciAddress,
+ IN UINT8 INTx,
+ IN EFI_ACPI_HANDLE *INTxPkgHandle,
+ IN BOOLEAN *IsAPIC
+ )
+{
+ EFI_ACPI_HANDLE PreviousHandle;
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE ChildPkgHandle;
+
+ ChildPkgHandle = NULL;
+ while (TRUE) {
+ PreviousHandle = ChildPkgHandle;
+ Status = AcpiSdt->GetChild (ParentPkgHandle, &ChildPkgHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ if (PreviousHandle != NULL) {
+ Status = AcpiSdt->Close (PreviousHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (ChildPkgHandle == NULL) {
+ break;
+ }
+
+ if (SdtCheckINTxPkgIsMatch(AcpiSdt, ChildPkgHandle, PciAddress, INTx, IsAPIC)) {
+ *INTxPkgHandle = ChildPkgHandle;
+ return;
+ }
+ }
+
+ return;
+}
+
+/**
+ Update the INTx package with the correct pirq value
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param INTxPkgHandle ACPI INTx package handle
+ @param PirqValue Correct pirq value
+ @param IsAPIC Tell whether the INTx package is for APIC or not
+
+**/
+VOID
+SdtUpdateINTxPkg (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE INTxPkgHandle,
+ IN UINT8 PirqValue,
+ IN BOOLEAN IsAPIC
+ )
+{
+ EFI_ACPI_HANDLE PreviousHandle;
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE MemberHandle;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINT64 TempValue;
+ UINTN ChildSize;
+
+
+ //
+ // Check the pci address
+ //
+ MemberHandle = NULL;
+ Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (MemberHandle != NULL);
+
+ //
+ // Check the pci interrupt pin
+ //
+ PreviousHandle = MemberHandle;
+ Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (MemberHandle != NULL);
+
+ if (PreviousHandle != NULL) {
+ Status = AcpiSdt->Close (PreviousHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+ ChildSize = SdtGetInteger (Data, &TempValue);
+
+ Status = AcpiSdt->Close (MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ Data += ChildSize;
+
+ //
+ // update the pci interrupt source or source index
+ //
+ if (!IsAPIC) {
+ ChildSize = SdtGetNameStringSize (Data);
+ Data += (ChildSize - 1);
+
+ PirqValue += 0x40; // change to ascii char
+ if (*Data != PirqValue)
+ *Data = PirqValue;
+ } else {
+
+ ChildSize = SdtGetInteger (Data, &TempValue);
+ Data += ChildSize;
+
+ Data += 1;
+
+ if (*Data != PirqValue)
+ *Data = PirqValue;
+ }
+}
+
+/**
+ Check every child package inside this interested parent package for update PRT
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param ParentPkgHandle ACPI parent package handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+VOID
+SdtCheckParentPackage (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE ParentPkgHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ )
+{
+ EFI_ACPI_HANDLE INTAPkgHandle;
+ EFI_ACPI_HANDLE INTBPkgHandle;
+ EFI_ACPI_HANDLE INTCPkgHandle;
+ EFI_ACPI_HANDLE INTDPkgHandle;
+ UINT32 PciAddress = 0;
+ BOOLEAN IsAllFunctions = FALSE;
+ UINT8 IsAPIC = 0;
+ EFI_STATUS Status;
+
+ INTAPkgHandle = INTBPkgHandle = INTCPkgHandle = INTDPkgHandle = NULL;
+
+ PciAddress = SdtConvertToAcpiPciAdress(PciDeviceInfo->DeviceAddress);
+
+ if ((PciAddress & 0xFFFF) == 0xFFFF) {
+ IsAllFunctions = TRUE;
+ } else {
+ IsAllFunctions = FALSE;
+ PciAddress = (PciAddress | 0xFFFF);
+ }
+
+ SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 0, &INTAPkgHandle, (BOOLEAN *)&IsAPIC);
+ SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 1, &INTBPkgHandle, (BOOLEAN *)&IsAPIC);
+ SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 2, &INTCPkgHandle, (BOOLEAN *)&IsAPIC);
+ SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 3, &INTDPkgHandle, (BOOLEAN *)&IsAPIC);
+
+ //
+ // Check INTA
+ //
+ if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle != NULL)) {
+ //
+ // Find INTA package and there is valid INTA update item, update it
+ //
+ SdtUpdateINTxPkg (AcpiSdt, INTAPkgHandle, (PciDeviceInfo->INTA[IsAPIC]), IsAPIC);
+ } else if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle == NULL)) {
+ //
+ // There is valid INTA update item, but no INA package exist, should add it
+ //
+ DEBUG ((EFI_D_ERROR, "\n\nShould add INTA item for this device(0x%x)\n\n", PciAddress));
+
+ } else if ((PciDeviceInfo->INTA[IsAPIC] == 0xFF) && (INTAPkgHandle != NULL) && IsAllFunctions) {
+ //
+ // For all functions senario, if there is invalid INTA update item, but INTA package does exist, should delete it
+ //
+ DEBUG ((EFI_D_ERROR, "\n\nShould remove INTA item for this device(0x%x)\n\n", PciAddress));
+
+ }
+
+ //
+ // Check INTB
+ //
+ if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle != NULL)) {
+ //
+ // Find INTB package and there is valid INTB update item, update it
+ //
+ SdtUpdateINTxPkg (AcpiSdt, INTBPkgHandle, (PciDeviceInfo->INTB[IsAPIC]), IsAPIC);
+ } else if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle == NULL)) {
+ //
+ // There is valid INTB update item, but no INTB package exist, should add it
+ //
+ DEBUG ((EFI_D_ERROR, "\n\nShould add INTB item for this device(0x%x)\n\n", PciAddress));
+
+ } else if ((PciDeviceInfo->INTB[IsAPIC] == 0xFF) && (INTBPkgHandle != NULL) && IsAllFunctions) {
+ //
+ // For all functions senario, if there is invalid INTB update item, but INTB package does exist, should delete it
+ //
+ DEBUG ((EFI_D_ERROR, "\n\nShould remove INTB item for this device(0x%x)\n\n", PciAddress));
+
+ }
+
+ //
+ // Check INTC
+ //
+ if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle != NULL)) {
+ //
+ // Find INTC package and there is valid INTC update item, update it
+ //
+ SdtUpdateINTxPkg (AcpiSdt, INTCPkgHandle, (PciDeviceInfo->INTC[IsAPIC]), IsAPIC);
+ } else if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle == NULL)) {
+ //
+ // There is valid INTC update item, but no INTC package exist, should add it
+ //
+ DEBUG ((EFI_D_ERROR, "\n\nShould add INTC item for this device(0x%x)\n\n", PciAddress));
+
+ } else if ((PciDeviceInfo->INTC[IsAPIC] == 0xFF) && (INTCPkgHandle != NULL) && IsAllFunctions) {
+ //
+ // For all functions senario, if there is invalid INTC update item, but INTC package does exist, should delete it
+ //
+ DEBUG ((EFI_D_ERROR, "\n\nShould remove INTC item for this device(0x%x)\n\n", PciAddress));
+ }
+
+ //
+ // Check INTD
+ //
+ if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle != NULL)) {
+ //
+ // Find INTD package and there is valid INTD update item, update it
+ //
+ SdtUpdateINTxPkg (AcpiSdt, INTDPkgHandle, (PciDeviceInfo->INTD[IsAPIC]), IsAPIC);
+ } else if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle == NULL)) {
+ //
+ // There is valid INTD update item, but no INTD package exist, should add it
+ //
+ DEBUG ((EFI_D_ERROR, "\n\nShould add INTD item for this device(0x%x)\n\n", PciAddress));
+
+ } else if ((PciDeviceInfo->INTD[IsAPIC] == 0xFF) && (INTDPkgHandle != NULL) && IsAllFunctions) {
+ //
+ // For all functions senario, if there is invalid INTD update item, but INTD package does exist, should delete it
+ //
+ DEBUG ((EFI_D_ERROR, "\n\nShould remove INTD item for this device(0x%x)\n\n", PciAddress));
+ }
+
+
+ if (INTAPkgHandle != NULL) {
+ Status = AcpiSdt->Close (INTAPkgHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (INTBPkgHandle != NULL) {
+ Status = AcpiSdt->Close (INTBPkgHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (INTCPkgHandle != NULL) {
+ Status = AcpiSdt->Close (INTCPkgHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (INTDPkgHandle != NULL) {
+ Status = AcpiSdt->Close (INTDPkgHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
+
+/**
+ Check every return package for update PRT
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param ParentHandle ACPI pci device handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+VOID
+SdtCheckReturnPackage (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE MethodHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ )
+{
+ EFI_ACPI_HANDLE PreviousHandle;
+ EFI_ACPI_HANDLE ReturnHandle;
+ EFI_ACPI_HANDLE PackageHandle;
+ EFI_ACPI_HANDLE NamePkgHandle;
+ EFI_STATUS Status;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+ CHAR8 NameStr[128];
+
+ ReturnHandle = NULL;
+ while (TRUE) {
+ PreviousHandle = ReturnHandle;
+ Status = AcpiSdt->GetChild (MethodHandle, &ReturnHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ if (PreviousHandle != NULL) {
+ Status = AcpiSdt->Close (PreviousHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (ReturnHandle == NULL) {
+ break;
+ }
+
+ Status = AcpiSdt->GetOption (ReturnHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+ if (*Data == AML_RETURN_OP) {
+ //
+ // Find the return method handle, then look for the returned package data
+ //
+ Status = AcpiSdt->GetOption (ReturnHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+
+
+ if (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING) {
+ ZeroMem (NameStr, 128);
+ AsciiStrCpy (NameStr, "\\_SB.");
+ DataSize = SdtGetNameStringSize (Data);
+ AsciiStrnCat (NameStr, (CHAR8 *)Data, DataSize);
+
+ NamePkgHandle = NULL;
+ Status = AcpiSdt->FindPath (mDsdtHandle, NameStr, &NamePkgHandle);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (NamePkgHandle != NULL);
+
+ Status = AcpiSdt->GetOption (NamePkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+ ASSERT (*Data == AML_NAME_OP);
+
+ Status = AcpiSdt->GetOption (NamePkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
+ }
+
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
+
+ //
+ // Get the parent package handle
+ //
+ PackageHandle = NULL;
+ Status = AcpiSdt->Open (Data, &PackageHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Check the parent package for update pci routing
+ //
+ SdtCheckParentPackage (AcpiSdt, PackageHandle, PciDeviceInfo);
+
+ Status = AcpiSdt->Close (PackageHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = AcpiSdt->Close (ReturnHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ break;
+ }
+
+ //
+ // Not ReturnOp, search it as parent
+ //
+ SdtCheckReturnPackage (AcpiSdt, ReturnHandle, PciDeviceInfo);
+ }
+
+ //
+ // Done
+ //
+ return;
+
+}
+
+/**
+ update interrupt info inside the PRT method for the given pci device handle
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param PciHandle ACPI pci device handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePrtMethod (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE PciHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE PrtMethodHandle;
+
+ //
+ // Find the PRT method under this pci device
+ //
+ PrtMethodHandle = NULL;
+ Status = AcpiSdt->FindPath (PciHandle, "_PRT", &PrtMethodHandle);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PrtMethodHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SdtCheckReturnPackage(AcpiSdt, PrtMethodHandle, PciDeviceInfo);
+
+ Status = AcpiSdt->Close (PrtMethodHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ Update the package inside name op with correct wakeup resources
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param InPkgHandle ACPI inside package handle
+ @param GPEPin Correct gpe pin
+ @param SxNum Correct system state the device can wake up from
+
+**/
+VOID
+SdtUpdatePackageInName (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE INTxPkgHandle,
+ IN UINT8 GPEPin,
+ IN UINT8 SxNum
+ )
+{
+ EFI_ACPI_HANDLE PreviousHandle;
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE MemberHandle;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+
+ //
+ // Check the gpe pin
+ //
+ MemberHandle = NULL;
+ Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (MemberHandle != NULL);
+
+ Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+ //
+ // Skip byte prefix
+ //
+ Data += 1;
+
+ if (*Data != GPEPin) {
+
+ *Data = GPEPin;
+ }
+
+ //
+ // Check the sx number
+ //
+ PreviousHandle = MemberHandle;
+ Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (MemberHandle != NULL);
+
+ if (PreviousHandle != NULL) {
+ Status = AcpiSdt->Close (PreviousHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+ //
+ // Skip byte prefix
+ //
+ Data += 1;
+
+ if (*Data != SxNum) {
+
+ *Data = SxNum;
+ }
+
+ Status = AcpiSdt->Close (MemberHandle);
+ ASSERT_EFI_ERROR (Status);
+
+}
+
+/**
+ Check the name package belonged to PRW
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param PrwPkgHandle ACPI PRW package handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+VOID
+SdtCheckNamePackage (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE PrwPkgHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ )
+{
+ EFI_ACPI_HANDLE InPkgHandle;
+ EFI_STATUS Status;
+ EFI_ACPI_DATA_TYPE DataType;
+ UINT8 *Data;
+ UINTN DataSize;
+
+ Status = AcpiSdt->GetOption (PrwPkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+ ASSERT (*Data == AML_NAME_OP);
+
+ Status = AcpiSdt->GetOption (PrwPkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
+
+ //
+ // Get the inside package handle
+ //
+ InPkgHandle = NULL;
+ Status = AcpiSdt->Open (Data, &InPkgHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // update the package in name op for wakeup info
+ //
+ if ((PciDeviceInfo->GPEPin != 0xFF) && (PciDeviceInfo->SxNum != 0xFF))
+ SdtUpdatePackageInName (AcpiSdt, InPkgHandle, PciDeviceInfo->GPEPin, PciDeviceInfo->SxNum);
+
+ Status = AcpiSdt->Close (InPkgHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ return;
+
+}
+
+/**
+ update wakeup info inside the PRW method for the given pci device handle
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param PciHandle ACPI pci device handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePrwPackage (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE PciHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE PrwPkgHandle;
+
+ //
+ // Find the PRT method under this pci device
+ //
+ PrwPkgHandle = NULL;
+ Status = AcpiSdt->FindPath (PciHandle, "_PRW", &PrwPkgHandle);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PrwPkgHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SdtCheckNamePackage(AcpiSdt, PrwPkgHandle, PciDeviceInfo);
+
+ Status = AcpiSdt->Close (PrwPkgHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ update pci routing information in acpi table based on pcd settings
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param PciRootHandle ACPI root bridge handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePciRouting (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE PciRootHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE PciBridgeHandle;
+ UINT32 PciAddress;
+
+
+ PciBridgeHandle = NULL;
+ if (PciDeviceInfo->BridgeAddress == 0x00000000) {
+ //
+ // Its bridge is the host root bridge
+ //
+ PciBridgeHandle = PciRootHandle;
+
+ } else {
+
+ //
+ // Its bridge is just a pci device under the host bridge
+ //
+
+ //
+ // Conver the bridge address into one that acpi table can recognize
+ //
+ PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);
+
+ //
+ // Scan the whole table to find the pci device
+ //
+ PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);
+ if (PciBridgeHandle == NULL) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Status = SdtUpdatePrtMethod(AcpiSdt, PciBridgeHandle, PciDeviceInfo);
+
+ if (PciDeviceInfo->BridgeAddress != 0x00000000) {
+ Status = AcpiSdt->Close (PciBridgeHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+
+/**
+ update power resource wake up information in acpi table based on pcd settings
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param PciRootHandle ACPI root bridge handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePowerWake (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE PciRootHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE PciBridgeHandle;
+ EFI_ACPI_HANDLE PciDeviceHandle;
+ UINT32 PciAddress;
+
+ PciBridgeHandle = NULL;
+ if (PciDeviceInfo->BridgeAddress == 0x00000000) {
+ //
+ // Its bridge is the host root bridge
+ //
+ PciBridgeHandle = PciRootHandle;
+
+ } else {
+
+ //
+ // Its bridge is just a pci device under the host bridge
+ //
+
+ //
+ // Conver the bridge address into one that acpi table can recognize
+ //
+ PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);
+
+ //
+ // Scan the whole table to find the pci device
+ //
+ PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);
+
+ if (PciBridgeHandle == NULL) {
+
+ Status = AcpiSdt->Close (PciRootHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ PciDeviceHandle = NULL;
+
+ //
+ // Conver the device address into one that acpi table can recognize
+ //
+ PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->DeviceAddress);
+
+ //
+ // Scan the whole table to find the pci device
+ //
+ PciDeviceHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciBridgeHandle, SdtFindPciDeviceHandle, &PciAddress);
+
+ if (PciDeviceHandle == NULL) {
+ if (PciDeviceInfo->BridgeAddress != 0x00000000) {
+ Status = AcpiSdt->Close (PciBridgeHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = SdtUpdatePrwPackage(AcpiSdt, PciDeviceHandle, PciDeviceInfo);
+
+ Status = AcpiSdt->Close (PciDeviceHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ if (PciDeviceInfo->BridgeAddress != 0x00000000) {
+ Status = AcpiSdt->Close (PciBridgeHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+
+/**
+ Get the root bridge handle by scanning the acpi table
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param DsdtHandle ACPI root handle
+
+ @retval EFI_ACPI_HANDLE the handle of the root bridge
+**/
+EFI_ACPI_HANDLE
+SdtGetRootBridgeHandle (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE DsdtHandle
+ )
+{
+ EFI_ACPI_HANDLE PciRootHandle;
+
+ //
+ // Scan the whole table to find the root bridge
+ //
+ PciRootHandle = NULL;
+ PciRootHandle = SdtGetHandleByScanAllChilds(AcpiSdt, DsdtHandle, SdtFindRootBridgeHandle, NULL);
+ ASSERT (PciRootHandle != NULL);
+
+ return PciRootHandle;
+}
+
+
+/**
+ Check input Pci device info is changed from the default values
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+ @param UpdatePRT Pointer to BOOLEAN
+ @param UpdatePRW Pointer to BOOLEAN
+
+**/
+VOID
+SdtCheckPciDeviceInfoChanged (
+ IN PCI_DEVICE_INFO *PciDeviceInfo,
+ IN BOOLEAN *UpdatePRT,
+ IN BOOLEAN *UpdatePRW
+ )
+{
+ UINTN Index = 0;
+
+ if (mQNCPciInfo == NULL) {
+ *UpdatePRT = FALSE;
+ *UpdatePRW = FALSE;
+ return;
+ }
+
+ *UpdatePRT = TRUE;
+ *UpdatePRW = TRUE;
+
+ for (Index = 0;Index < CURRENT_PCI_DEVICE_NUM; Index++) {
+ if ((mQNCPciInfo[Index].BridgeAddress == PciDeviceInfo->BridgeAddress)
+ && (mQNCPciInfo[Index].DeviceAddress == PciDeviceInfo->DeviceAddress)) {
+ //
+ // Find one matched entry
+ //
+ if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 10) == 0) {
+ *UpdatePRT = FALSE;
+ *UpdatePRW = FALSE;
+ //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and no change\n", Index));
+ } else {
+ if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 8) == 0)
+ *UpdatePRT = FALSE;
+
+ if (CompareMem (&(mQNCPciInfo[Index].GPEPin), &PciDeviceInfo->GPEPin, 2) == 0)
+ *UpdatePRW = FALSE;
+
+ if (*(UINT64 *)(&PciDeviceInfo->INTA[0]) == 0xFFFFFFFFFFFFFFFF)
+ *UpdatePRT = FALSE;
+
+ if (*(UINT16 *)(&PciDeviceInfo->GPEPin) == 0xFFFF)
+ *UpdatePRW = FALSE;
+
+ //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and but need update PRT:0x%x PRW:0x%x\n", Index, *UpdatePRT, *UpdatePRW));
+ }
+ break;
+ }
+ }
+
+ //if (Index == 42) {
+ // DEBUG ((EFI_D_ERROR, "Find No matched entry\n"));
+ //}
+
+ return;
+}
diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.h b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.h
new file mode 100644
index 0000000..281f6af
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.h
@@ -0,0 +1,347 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ AcpiPciUpdate.h
+
+Abstract:
+
+ Update the _PRT and _PRW method for pci devices
+
+--*/
+#ifndef _ACPI_PCI_UPDATE_H_
+#define _ACPI_PCI_UPDATE_H_
+
+
+//
+// Primary OpCode
+//
+#define AML_ZERO_OP 0x00
+#define AML_ONE_OP 0x01
+#define AML_ALIAS_OP 0x06
+#define AML_NAME_OP 0x08
+#define AML_BYTE_PREFIX 0x0a
+#define AML_WORD_PREFIX 0x0b
+#define AML_DWORD_PREFIX 0x0c
+#define AML_STRING_PREFIX 0x0d
+#define AML_QWORD_PREFIX 0x0e
+#define AML_SCOPE_OP 0x10
+#define AML_BUFFER_OP 0x11
+#define AML_PACKAGE_OP 0x12
+#define AML_VAR_PACKAGE_OP 0x13
+#define AML_METHOD_OP 0x14
+#define AML_DUAL_NAME_PREFIX 0x2e
+#define AML_MULTI_NAME_PREFIX 0x2f
+#define AML_NAME_CHAR_A 0x41
+#define AML_NAME_CHAR_B 0x42
+#define AML_NAME_CHAR_C 0x43
+#define AML_NAME_CHAR_D 0x44
+#define AML_NAME_CHAR_E 0x45
+#define AML_NAME_CHAR_F 0x46
+#define AML_NAME_CHAR_G 0x47
+#define AML_NAME_CHAR_H 0x48
+#define AML_NAME_CHAR_I 0x49
+#define AML_NAME_CHAR_J 0x4a
+#define AML_NAME_CHAR_K 0x4b
+#define AML_NAME_CHAR_L 0x4c
+#define AML_NAME_CHAR_M 0x4d
+#define AML_NAME_CHAR_N 0x4e
+#define AML_NAME_CHAR_O 0x4f
+#define AML_NAME_CHAR_P 0x50
+#define AML_NAME_CHAR_Q 0x51
+#define AML_NAME_CHAR_R 0x52
+#define AML_NAME_CHAR_S 0x53
+#define AML_NAME_CHAR_T 0x54
+#define AML_NAME_CHAR_U 0x55
+#define AML_NAME_CHAR_V 0x56
+#define AML_NAME_CHAR_W 0x57
+#define AML_NAME_CHAR_X 0x58
+#define AML_NAME_CHAR_Y 0x59
+#define AML_NAME_CHAR_Z 0x5a
+#define AML_ROOT_CHAR 0x5c
+#define AML_PARENT_PREFIX_CHAR 0x5e
+#define AML_NAME_CHAR__ 0x5f
+#define AML_LOCAL0 0x60
+#define AML_LOCAL1 0x61
+#define AML_LOCAL2 0x62
+#define AML_LOCAL3 0x63
+#define AML_LOCAL4 0x64
+#define AML_LOCAL5 0x65
+#define AML_LOCAL6 0x66
+#define AML_LOCAL7 0x67
+#define AML_ARG0 0x68
+#define AML_ARG1 0x69
+#define AML_ARG2 0x6a
+#define AML_ARG3 0x6b
+#define AML_ARG4 0x6c
+#define AML_ARG5 0x6d
+#define AML_ARG6 0x6e
+#define AML_STORE_OP 0x70
+#define AML_REF_OF_OP 0x71
+#define AML_ADD_OP 0x72
+#define AML_CONCAT_OP 0x73
+#define AML_SUBTRACT_OP 0x74
+#define AML_INCREMENT_OP 0x75
+#define AML_DECREMENT_OP 0x76
+#define AML_MULTIPLY_OP 0x77
+#define AML_DIVIDE_OP 0x78
+#define AML_SHIFT_LEFT_OP 0x79
+#define AML_SHIFT_RIGHT_OP 0x7a
+#define AML_AND_OP 0x7b
+#define AML_NAND_OP 0x7c
+#define AML_OR_OP 0x7d
+#define AML_NOR_OP 0x7e
+#define AML_XOR_OP 0x7f
+#define AML_NOT_OP 0x80
+#define AML_FIND_SET_LEFT_BIT_OP 0x81
+#define AML_FIND_SET_RIGHT_BIT_OP 0x82
+#define AML_DEREF_OF_OP 0x83
+#define AML_CONCAT_RES_OP 0x84
+#define AML_MOD_OP 0x85
+#define AML_NOTIFY_OP 0x86
+#define AML_SIZE_OF_OP 0x87
+#define AML_INDEX_OP 0x88
+#define AML_MATCH_OP 0x89
+#define AML_CREATE_DWORD_FIELD_OP 0x8a
+#define AML_CREATE_WORD_FIELD_OP 0x8b
+#define AML_CREATE_BYTE_FIELD_OP 0x8c
+#define AML_CREATE_BIT_FIELD_OP 0x8d
+#define AML_OBJECT_TYPE_OP 0x8e
+#define AML_CREATE_QWORD_FIELD_OP 0x8f
+#define AML_LAND_OP 0x90
+#define AML_LOR_OP 0x91
+#define AML_LNOT_OP 0x92
+#define AML_LEQUAL_OP 0x93
+#define AML_LGREATER_OP 0x94
+#define AML_LLESS_OP 0x95
+#define AML_TO_BUFFER_OP 0x96
+#define AML_TO_DEC_STRING_OP 0x97
+#define AML_TO_HEX_STRING_OP 0x98
+#define AML_TO_INTEGER_OP 0x99
+#define AML_TO_STRING_OP 0x9c
+#define AML_COPY_OBJECT_OP 0x9d
+#define AML_MID_OP 0x9e
+#define AML_CONTINUE_OP 0x9f
+#define AML_IF_OP 0xa0
+#define AML_ELSE_OP 0xa1
+#define AML_WHILE_OP 0xa2
+#define AML_NOOP_OP 0xa3
+#define AML_RETURN_OP 0xa4
+#define AML_BREAK_OP 0xa5
+#define AML_BREAK_POINT_OP 0xcc
+#define AML_ONES_OP 0xff
+
+//
+// Extended OpCode
+//
+#define AML_EXT_OP 0x5b
+
+#define AML_EXT_MUTEX_OP 0x01
+#define AML_EXT_EVENT_OP 0x02
+#define AML_EXT_COND_REF_OF_OP 0x12
+#define AML_EXT_CREATE_FIELD_OP 0x13
+#define AML_EXT_LOAD_TABLE_OP 0x1f
+#define AML_EXT_LOAD_OP 0x20
+#define AML_EXT_STALL_OP 0x21
+#define AML_EXT_SLEEP_OP 0x22
+#define AML_EXT_ACQUIRE_OP 0x23
+#define AML_EXT_SIGNAL_OP 0x24
+#define AML_EXT_WAIT_OP 0x25
+#define AML_EXT_RESET_OP 0x26
+#define AML_EXT_RELEASE_OP 0x27
+#define AML_EXT_FROM_BCD_OP 0x28
+#define AML_EXT_TO_BCD_OP 0x29
+#define AML_EXT_UNLOAD_OP 0x2a
+#define AML_EXT_REVISION_OP 0x30
+#define AML_EXT_DEBUG_OP 0x31
+#define AML_EXT_FATAL_OP 0x32
+#define AML_EXT_TIMER_OP 0x33
+#define AML_EXT_REGION_OP 0x80
+#define AML_EXT_FIELD_OP 0x81
+#define AML_EXT_DEVICE_OP 0x82
+#define AML_EXT_PROCESSOR_OP 0x83
+#define AML_EXT_POWER_RES_OP 0x84
+#define AML_EXT_THERMAL_ZONE_OP 0x85
+#define AML_EXT_INDEX_FIELD_OP 0x86
+#define AML_EXT_BANK_FIELD_OP 0x87
+#define AML_EXT_DATA_REGION_OP 0x88
+
+#pragma pack(1)
+
+typedef struct {
+ UINT32 BridgeAddress;
+ UINT32 DeviceAddress;
+ UINT8 INTA[2]; // the first member record the 8259 link, the second member record the io apic irq number
+ UINT8 INTB[2];
+ UINT8 INTC[2];
+ UINT8 INTD[2];
+
+ UINT8 GPEPin;
+ UINT8 SxNum;
+} PCI_DEVICE_INFO;
+
+#pragma pack()
+
+#define PCI_DEVICE_INFO_MAX_NUM 50
+#define CURRENT_PCI_DEVICE_NUM 13
+
+#define PIRQ_LINKA 1
+#define PIRQ_LINKB 2
+#define PIRQ_LINKC 3
+#define PIRQ_LINKD 4
+#define PIRQ_LINKE 5
+#define PIRQ_LINKF 6
+#define PIRQ_LINKG 7
+#define PIRQ_LINKH 8
+#define PIRQ_INVALID 0xFF
+
+typedef struct _PCI_DEVICE_SETTING{
+ UINT8 PciDeviceInfoNumber;
+ PCI_DEVICE_INFO PciDeviceInfo[PCI_DEVICE_INFO_MAX_NUM];
+}PCI_DEVICE_SETTING;
+
+typedef struct _AML_BYTE_ENCODING AML_BYTE_ENCODING;
+
+//
+// AML Handle Entry definition.
+//
+// Signature must be set to EFI_AML_HANDLE_SIGNATURE or EFI_AML_ROOT_HANDLE_SIGNATURE
+// Buffer is the ACPI node buffer pointer, the first/second bytes are opcode.
+// This buffer should not be freed.
+// Size is the total size of this ACPI node buffer.
+//
+typedef struct {
+ UINT32 Signature;
+ UINT8 *Buffer;
+ UINTN Size;
+ AML_BYTE_ENCODING *AmlByteEncoding;
+ BOOLEAN Modified;
+} EFI_AML_HANDLE;
+
+typedef UINT32 AML_OP_PARSE_INDEX;
+
+typedef UINT32 AML_OP_PARSE_FORMAT;
+
+typedef UINT32 AML_OP_ATTRIBUTE;
+
+struct _AML_BYTE_ENCODING {
+ UINT8 OpCode;
+ UINT8 SubOpCode;
+ AML_OP_PARSE_INDEX MaxIndex;
+ AML_OP_PARSE_FORMAT Format[6];
+ AML_OP_ATTRIBUTE Attribute;
+};
+
+
+//
+// Check device info fucntion prototype
+//
+typedef
+BOOLEAN
+(* CHECK_HANDLE_INFO) (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE CheckHandle,
+ IN VOID *Context
+ );
+
+extern EFI_ACPI_HANDLE mDsdtHandle;
+extern EFI_ACPI_SDT_PROTOCOL *mAcpiSdt;
+
+/**
+ Init Pci Device Structure
+
+ @param mConfigData - Pointer of Pci Device information Structure
+
+**/
+VOID
+InitPciDeviceInfoStructure (
+ PCI_DEVICE_SETTING *mConfigData
+ );
+/**
+ update pci routing information in acpi table based on pcd settings
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param DsdtHandle ACPI root handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePciRouting (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE DsdtHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ );
+
+
+/**
+ update power resource wake up information in acpi table based on pcd settings
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param DsdtHandle ACPI root handle
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePowerWake (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE DsdtHandle,
+ IN PCI_DEVICE_INFO *PciDeviceInfo
+ );
+
+/**
+ Get the root bridge handle by scanning the acpi table
+
+ @param AcpiSdt Pointer to Acpi SDT protocol
+ @param DsdtHandle ACPI root handle
+
+ @retval EFI_ACPI_HANDLE the handle of the root bridge
+**/
+EFI_ACPI_HANDLE
+SdtGetRootBridgeHandle (
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+ IN EFI_ACPI_HANDLE DsdtHandle
+ );
+
+/**
+ Check input Pci device info is changed from the default values
+ @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+ @param UpdatePRT Pointer to BOOLEAN
+ @param UpdatePRW Pointer to BOOLEAN
+
+**/
+VOID
+SdtCheckPciDeviceInfoChanged (
+ IN PCI_DEVICE_INFO *PciDeviceInfo,
+ IN BOOLEAN *UpdatePRT,
+ IN BOOLEAN *UpdatePRW
+ );
+#endif
diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c
new file mode 100644
index 0000000..f80584c
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c
@@ -0,0 +1,819 @@
+/*++
+ ACPI Platform Driver
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--*/
+
+#include <Protocol/AcpiTable.h>
+#include <IndustryStandard/Pci22.h>
+#include "AcpiPlatform.h"
+
+//
+// Global Variable
+//
+STATIC EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea;
+EFI_ACPI_SDT_PROTOCOL *mAcpiSdt;
+
+EFI_ACPI_HANDLE mDsdtHandle = NULL;
+
+
+EFI_STATUS
+LocateSupportProtocol (
+ IN EFI_GUID *Protocol,
+ OUT VOID **Instance,
+ IN UINT32 Type
+ )
+/*++
+
+Routine Description:
+
+ Locate the first instance of a protocol. If the protocol requested is an
+ FV protocol, then it will return the first FV that contains the ACPI table
+ storage file.
+
+Arguments:
+
+ Protocol The protocol to find.
+ Instance Return pointer to the first instance of the protocol
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_NOT_FOUND The protocol could not be located.
+ EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+
+ FvStatus = 0;
+
+ //
+ // Locate protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Protocol,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+
+ //
+ // Defined errors at this time are not found and out of resources.
+ //
+ return Status;
+ }
+
+
+
+ //
+ // Looking for FV with ACPI storage file
+ //
+
+ for (i = 0; i < NumberOfHandles; i++) {
+ //
+ // Get the protocol on this handle
+ // This should not fail because of LocateHandleBuffer
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ Protocol,
+ Instance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!Type) {
+ //
+ // Not looking for the FV protocol, so find the first instance of the
+ // protocol. There should not be any errors because our handle buffer
+ // should always contain at least one or LocateHandleBuffer would have
+ // returned not found.
+ //
+ break;
+ }
+
+ //
+ // See if it has the ACPI storage file
+ //
+
+ Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,
+ (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+ 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
+ //
+ gBS->FreePool (HandleBuffer);
+
+ return Status;
+}
+
+
+VOID
+DsdtTableUpdate (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+/*++
+
+ Routine Description:
+
+ Update the DSDT table
+
+ Arguments:
+
+ Table - The table to be set
+ Version - Version to publish
+
+ Returns:
+
+ None
+
+--*/
+{
+
+ UINT8 *CurrPtr;
+ UINT8 *DsdtPointer;
+ UINT32 *Signature;
+ UINT8 *Operation;
+ UINT32 *Address;
+ UINT16 *Size;
+ //
+ // Loop through the ASL looking for values that we must fix up.
+ //
+ CurrPtr = (UINT8 *) TableHeader;
+ for (DsdtPointer = CurrPtr;
+ DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+ DsdtPointer++
+ )
+ {
+ Signature = (UINT32 *) DsdtPointer;
+ switch (*Signature) {
+ //
+ // MNVS operation region
+ //
+ case (SIGNATURE_32 ('M', 'N', 'V', 'S')):
+ //
+ // 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 (*Operation == AML_OPREGION_OP) {
+ Address = (UINT32 *) (DsdtPointer + 6);
+ *Address = (UINT32) (UINTN) mGlobalNvsArea.Area;
+ Size = (UINT16 *) (DsdtPointer + 11);
+ *Size = sizeof (EFI_GLOBAL_NVS_AREA);
+ }
+ break;
+
+ //
+ // Update processor PBLK register I/O base address
+ //
+ case (SIGNATURE_32 ('P', 'R', 'I', 'O')):
+ //
+ // Conditional match. Update the following ASL code:
+ // Processor (CPU0, 0x01, 0x4F495250, 0x06) {}
+ // The 3rd parameter will be updated to the actual PBLK I/O base address.
+ // the Operator.
+ //
+ Operation = DsdtPointer - 8;
+ if ((*Operation == AML_EXT_OP) && (*(Operation + 1) == AML_EXT_PROCESSOR_OP)) {
+ *(UINT32 *)DsdtPointer = PcdGet16(PcdPmbaIoBaseAddress);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+VOID
+ApicTableUpdate (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+/*++
+
+ Routine Description:
+
+ Update the processors information in the APIC table
+
+ Arguments:
+
+ Table - The table to be set
+ Version - Version to publish
+
+ Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+ UINT8 *CurrPtr;
+ UINT8 *EndPtr;
+ UINT8 CurrIoApic;
+ UINT8 CurrProcessor;
+ UINTN NumberOfCPUs;
+ UINTN NumberOfEnabledCPUs;
+ UINTN BufferSize;
+ EFI_PROCESSOR_INFORMATION MpContext;
+ ACPI_APIC_STRUCTURE_PTR *ApicPtr;
+
+ CurrIoApic = 0;
+ CurrProcessor = 0;
+ //
+ // Find the MP Protocol. This is an MP platform, so MP protocol must be
+ // there.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID**)&MpService
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Failed to get MP information, doesn't publish the invalid table
+ //
+ *Version = EFI_ACPI_TABLE_VERSION_NONE;
+ return;
+ }
+
+ //
+ // Determine the number of processors
+ //
+ MpService->GetNumberOfProcessors (
+ MpService,
+ &NumberOfCPUs,
+ &NumberOfEnabledCPUs
+ );
+
+ CurrPtr = (UINT8*) &(TableHeader[1]);
+ CurrPtr = CurrPtr + 8; // Size of Local APIC Address & Flag
+ EndPtr = (UINT8*) TableHeader;
+ EndPtr = EndPtr + TableHeader->Length;
+
+ while (CurrPtr < EndPtr) {
+
+ ApicPtr = (ACPI_APIC_STRUCTURE_PTR*) CurrPtr;
+ switch (ApicPtr->AcpiApicCommon.Type) {
+
+ case EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC:
+ BufferSize = sizeof (EFI_PROCESSOR_INFORMATION);
+ ApicPtr->AcpiLocalApic.Flags = 0;
+ ApicPtr->AcpiLocalApic.ApicId = 0;
+ Status = MpService->GetProcessorInfo (
+ MpService,
+ CurrProcessor,
+ &MpContext
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (MpContext.StatusFlag & PROCESSOR_ENABLED_BIT) {
+ ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_3_0_LOCAL_APIC_ENABLED;
+ }
+ ApicPtr->AcpiLocalApic.ApicId = (UINT8)MpContext.ProcessorId;
+ }
+ CurrProcessor++;
+ break;
+
+ case EFI_ACPI_1_0_IO_APIC:
+ //
+ // IO APIC entries can be patched here
+ //
+ if (CurrIoApic == 0) {
+ //
+ // Update SOC internel IOAPIC base
+ //
+ ApicPtr->AcpiIoApic.IoApicId = PcdGet8 (PcdIoApicSettingIoApicId);
+ ApicPtr->AcpiIoApic.IoApicAddress = (UINT32)FixedPcdGet64(PcdIoApicBaseAddress);
+ ApicPtr->AcpiIoApic.GlobalSystemInterruptBase = 0;
+ } else {
+ //
+ // Porting is required to update other IOAPIC entries if available
+ //
+ ASSERT (0);
+ }
+ CurrIoApic++;
+ break;
+
+ default:
+ break;
+ };
+ CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length;
+ }
+}
+
+VOID
+AcpiUpdateTable (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+/*++
+
+ Routine Description:
+
+ Set the correct table revision upon the setup value
+
+ Arguments:
+
+ Table - The table to be set
+ Version - Version to publish
+
+ Returns:
+
+ None
+
+--*/
+
+{
+ EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader1;
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader2;
+ EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader3;
+ EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *AllocationStructurePtr;
+
+ if (TableHeader != NULL && Version != NULL) {
+
+ *Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+ //
+ // Here we use all 3.0 signature because all version use same signature if they supported
+ //
+ switch (TableHeader->Signature) {
+ //
+ // "APIC" Multiple APIC Description Table
+ //
+ case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+ ApicTableUpdate (TableHeader, Version);
+ break;
+ //
+ // "DSDT" Differentiated System Description Table
+ //
+ case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ DsdtTableUpdate (TableHeader, Version);
+ break;
+
+ //
+ // "FACP" Fixed ACPI Description Table (FADT)
+ //
+ case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+ *Version = EFI_ACPI_TABLE_VERSION_NONE;
+ if (TableHeader->Revision == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
+ *Version = EFI_ACPI_TABLE_VERSION_1_0B;
+ FadtHeader1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
+ FadtHeader1->SmiCmd = PcdGet16(PcdSmmActivationPort);
+ FadtHeader1->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
+ FadtHeader1->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
+ FadtHeader1->PmTmrBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
+ FadtHeader1->Gpe0Blk = PcdGet16(PcdGpe0blkIoBaseAddress);
+ } else if (TableHeader->Revision == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
+ *Version = EFI_ACPI_TABLE_VERSION_2_0;
+ FadtHeader2 = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
+ FadtHeader2->SmiCmd = PcdGet16(PcdSmmActivationPort);
+ FadtHeader2->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
+ FadtHeader2->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
+ FadtHeader2->PmTmrBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
+ FadtHeader2->Gpe0Blk = PcdGet16(PcdGpe0blkIoBaseAddress);
+ FadtHeader2->XPm1aEvtBlk.Address = FadtHeader2->Pm1aEvtBlk;
+ FadtHeader2->XPm1aCntBlk.Address = FadtHeader2->Pm1aCntBlk;
+ FadtHeader2->XPmTmrBlk.Address = FadtHeader2->PmTmrBlk;
+ FadtHeader2->XGpe0Blk.Address = FadtHeader2->Gpe0Blk;
+ } else if (TableHeader->Revision == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
+ *Version = EFI_ACPI_TABLE_VERSION_3_0;
+ FadtHeader3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
+ FadtHeader3->SmiCmd = PcdGet16(PcdSmmActivationPort);
+ FadtHeader3->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
+ FadtHeader3->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
+ FadtHeader3->PmTmrBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
+ FadtHeader3->Gpe0Blk = PcdGet16(PcdGpe0blkIoBaseAddress);
+ FadtHeader3->XPm1aEvtBlk.Address = FadtHeader3->Pm1aEvtBlk;
+ FadtHeader3->XPm1aCntBlk.Address = FadtHeader3->Pm1aCntBlk;
+ FadtHeader3->XPmTmrBlk.Address = FadtHeader3->PmTmrBlk;
+ FadtHeader3->XGpe0Blk.Address = FadtHeader3->Gpe0Blk;
+ }
+ break;
+ //
+ // "FACS" Firmware ACPI Control Structure
+ //
+ case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
+ break;
+ //
+ // "SSDT" Secondary System Description Table
+ //
+ case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ break;
+ //
+ // "HPET" IA-PC High Precision Event Timer Table
+ //
+ case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
+ //
+ // If HPET is disabled in setup, don't publish the table.
+ //
+ if (mGlobalNvsArea.Area->HpetEnable == 0) {
+ *Version = EFI_ACPI_TABLE_VERSION_NONE;
+ }
+ ((EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) TableHeader)->BaseAddressLower32Bit.Address
+ = PcdGet64 (PcdHpetBaseAddress);
+ break;
+ //
+ // "SPCR" Serial Port Concole Redirection Table
+ //
+ case EFI_ACPI_3_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
+ break;
+ //
+ // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
+ //
+ case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
+ AllocationStructurePtr = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)
+ ((UINT8 *)TableHeader + sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER));
+ AllocationStructurePtr->BaseAddress = PcdGet64(PcdPciExpressBaseAddress);
+ break;
+ // Lakeport platform doesn't support the following table
+ /*
+ //
+ // "ECDT" Embedded Controller Boot Resources Table
+ //
+ case EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE:
+ break;
+ //
+ // "PSDT" Persistent System Description Table
+ //
+ case EFI_ACPI_3_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ break;
+ //
+ // "SBST" Smart Battery Specification Table
+ //
+ case EFI_ACPI_3_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE:
+ break;
+ //
+ // "SLIT" System Locality Information Table
+ //
+ case EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
+ break;
+ //
+ // "SRAT" Static Resource Affinity Table
+ //
+ case EFI_ACPI_3_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE:
+ break;
+ //
+ // "XSDT" Extended System Description Table
+ //
+ case EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ break;
+ //
+ // "BOOT" MS Simple Boot Spec
+ //
+ case EFI_ACPI_3_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE:
+ break;
+ //
+ // "CPEP" Corrected Platform Error Polling Table
+ //
+ case EFI_ACPI_3_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE:
+ break;
+ //
+ // "DBGP" MS Debug Port Spec
+ //
+ case EFI_ACPI_3_0_DEBUG_PORT_TABLE_SIGNATURE:
+ break;
+ //
+ // "ETDT" Event Timer Description Table
+ //
+ case EFI_ACPI_3_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE:
+ break;
+ //
+ // "SPMI" Server Platform Management Interface Table
+ //
+ case EFI_ACPI_3_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE:
+ break;
+ //
+ // "TCPA" Trusted Computing Platform Alliance Capabilities Table
+ //
+ case EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE:
+ break;
+ */
+ default:
+ break;
+ }
+ }
+}
+
+//
+// Description:
+// Entrypoint of Acpi Platform driver
+// In:
+// ImageHandle
+// SystemTable
+// Out:
+// EFI_SUCCESS
+// EFI_LOAD_ERROR
+// EFI_OUT_OF_RESOURCES
+//
+
+EFI_STATUS
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ INTN Instance;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN TableHandle;
+ UINT32 FvStatus;
+ UINTN Size;
+ EFI_ACPI_TABLE_VERSION Version;
+ QNC_DEVICE_ENABLES QNCDeviceEnables;
+ EFI_HANDLE Handle;
+ UINTN Index;
+ PCI_DEVICE_INFO *PciDeviceInfo;
+ EFI_ACPI_HANDLE PciRootHandle;
+ BOOLEAN UpdatePRT;
+ BOOLEAN UpdatePRW;
+ PCI_DEVICE_SETTING *mConfigData;
+
+ Instance = 0;
+ TableHandle = 0;
+ CurrentTable = NULL;
+ mConfigData = NULL;
+ QNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);
+
+ //
+ // Initialize the EFI Driver Library
+ //
+
+ ASSERT (sizeof (EFI_GLOBAL_NVS_AREA) == 512);
+
+ Status = gBS->AllocatePool (
+ EfiACPIMemoryNVS,
+ sizeof (EFI_GLOBAL_NVS_AREA),
+ (VOID**)&mGlobalNvsArea.Area
+ );
+
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiGlobalNvsAreaProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mGlobalNvsArea
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ SetMem (
+ mGlobalNvsArea.Area,
+ sizeof (EFI_GLOBAL_NVS_AREA),
+ 0
+ );
+ }
+
+ //
+ // Initialize the data. Eventually, this will be controlled by setup options.
+ //
+ mGlobalNvsArea.Area->HpetEnable = PcdGetBool (PcdHpetEnable);
+ mGlobalNvsArea.Area->Pm1blkIoBaseAddress = PcdGet16(PcdPm1blkIoBaseAddress);
+ mGlobalNvsArea.Area->PmbaIoBaseAddress = PcdGet16(PcdPmbaIoBaseAddress);
+ mGlobalNvsArea.Area->Gpe0blkIoBaseAddress = PcdGet16(PcdGpe0blkIoBaseAddress);
+ mGlobalNvsArea.Area->GbaIoBaseAddress = PcdGet16(PcdGbaIoBaseAddress);
+ mGlobalNvsArea.Area->SmbaIoBaseAddress = PcdGet16(PcdSmbaIoBaseAddress);
+ mGlobalNvsArea.Area->SpiDmaIoBaseAddress = PcdGet16(PcdSpiDmaIoBaseAddress);
+ mGlobalNvsArea.Area->WdtbaIoBaseAddress = PcdGet16(PcdWdtbaIoBaseAddress);
+ mGlobalNvsArea.Area->HpetBaseAddress = (UINT32)PcdGet64(PcdHpetBaseAddress);
+ mGlobalNvsArea.Area->HpetSize = (UINT32)PcdGet64(PcdHpetSize);
+ mGlobalNvsArea.Area->PciExpressBaseAddress= (UINT32)PcdGet64(PcdPciExpressBaseAddress);
+ mGlobalNvsArea.Area->PciExpressSize = (UINT32)PcdGet64(PcdPciExpressSize);
+ mGlobalNvsArea.Area->RcbaMmioBaseAddress = (UINT32)PcdGet64(PcdRcbaMmioBaseAddress);
+ mGlobalNvsArea.Area->RcbaMmioSize = (UINT32)PcdGet64(PcdRcbaMmioSize);
+ mGlobalNvsArea.Area->IoApicBaseAddress = (UINT32)PcdGet64(PcdIoApicBaseAddress);
+ mGlobalNvsArea.Area->IoApicSize = (UINT32)PcdGet64(PcdIoApicSize);
+ mGlobalNvsArea.Area->TpmPresent = (UINT32)(FALSE);
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ //
+ // Initialize MADT table
+ //
+ Status = MadtTableInitialize (&CurrentTable, &Size);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Perform any table specific updates.
+ //
+ AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
+
+ //
+ // Update the check sum
+ // It needs to be zeroed before the checksum calculation
+ //
+ ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
+ ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
+ CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
+
+ //
+ // Add the table
+ //
+ TableHandle = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ CurrentTable,
+ CurrentTable->Length,
+ &TableHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ CurrentTable = NULL;
+
+ //
+ // Init Pci Device PRT PRW information structure from PCD
+ //
+ mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING));
+ ASSERT_EFI_ERROR (mConfigData);
+ InitPciDeviceInfoStructure (mConfigData);
+ //
+ // Get the Acpi SDT protocol for manipulation on acpi table
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mAcpiSdt);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Read tables from the storage file.
+ //
+
+ while (Status == EFI_SUCCESS) {
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID**)&CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Perform any table specific updates.
+ //
+ AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
+
+ //
+ // Update the check sum
+ // It needs to be zeroed before the checksum calculation
+ //
+ ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
+ ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
+ CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
+
+ //
+ // Add the table
+ //
+ TableHandle = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ CurrentTable,
+ ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length,
+ &TableHandle
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // If this table is the DSDT table, then update the _PRT and _PRW based on
+ // the settings from pcds
+ //
+ if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ //
+ // Create the root handle for DSDT table
+ //
+ Status = mAcpiSdt->OpenSdt (TableHandle, &mDsdtHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ PciRootHandle = NULL;
+ PciRootHandle = SdtGetRootBridgeHandle (mAcpiSdt, mDsdtHandle);
+ ASSERT (PciRootHandle != NULL);
+
+ PciDeviceInfo = NULL;
+ for (Index = 0; Index < mConfigData->PciDeviceInfoNumber; Index++) {
+ PciDeviceInfo = &(mConfigData->PciDeviceInfo[Index]);
+
+ //
+ // Check whether this is a valid item
+ //
+ if ((PciDeviceInfo->BridgeAddress != 0xFFFFFFFF) && (PciDeviceInfo->DeviceAddress != 0xFFFFFFFF)) {
+
+ //DEBUG ((EFI_D_ERROR, "Valid pci info structure: bridge address:0x%x, device address:0x%x\n", PciDeviceInfo->BridgeAddress, PciDeviceInfo->DeviceAddress));
+
+ UpdatePRT = FALSE;
+ UpdatePRW = FALSE;
+
+ SdtCheckPciDeviceInfoChanged (PciDeviceInfo, &UpdatePRT, &UpdatePRW);
+ //
+ // Check whether there is any valid pci routing item
+ //
+ if (UpdatePRT) {
+ //
+ // Update the pci routing information
+ //
+ //DEBUG ((EFI_D_ERROR, "Update _PRT\n"));
+ SdtUpdatePciRouting (mAcpiSdt, PciRootHandle, PciDeviceInfo);
+ }
+ //
+ // Check whether there is any valid pci routing item
+ //
+ if (UpdatePRW) {
+ //
+ // Update the pci wakeup information
+ //
+ //DEBUG ((EFI_D_ERROR, "Update _PRW\n"));
+ SdtUpdatePowerWake (mAcpiSdt, PciRootHandle, PciDeviceInfo);
+ }
+ }
+ }
+ Status = mAcpiSdt->Close (PciRootHandle);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Mark the root handle as modified , let SDT protocol recaculate the checksum
+ //
+ ((EFI_AML_HANDLE *)mDsdtHandle)->Modified = TRUE;
+ Status = mAcpiSdt->Close (mDsdtHandle);
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // Increment the instance
+ //
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+ gBS->FreePool (mConfigData);
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.h b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.h
new file mode 100644
index 0000000..8af6070
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.h
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ AcpiPlatform.h
+
+Abstract:
+
+ This is an implementation of the ACPI platform driver. Requirements for
+ this driver are defined in the Tiano ACPI External Product Specification,
+ revision 0.3.6.
+
+--*/
+
+#ifndef _ACPI_PLATFORM_H_
+#define _ACPI_PLATFORM_H_
+
+//
+// Statements that include other header files
+//
+
+#include <PiDxe.h>
+#include <IntelQNCDxe.h>
+#include <QuarkPlatformDxe.h>
+
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/MpService.h>
+#include <Protocol/AcpiSupport.h>
+#include <Protocol/FirmwareVolume2.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#include "Madt.h"
+#include "AcpiPciUpdate.h"
+
+#pragma pack(1)
+typedef struct {
+ UINT8 StartByte;
+ UINT32 NameStr;
+ UINT8 OpCode;
+ UINT16 Size; // Hardcode to 16bit width because the table we use is fixed size
+ UINT8 NumEntries;
+} EFI_ACPI_NAME_COMMAND;
+
+typedef struct {
+ UINT8 PackageOp;
+ UINT8 PkgLeadByte;
+ UINT8 NumEntries;
+ UINT8 DwordPrefix0;
+ UINT32 CoreFreq;
+ UINT8 DwordPrefix1;
+ UINT32 Power;
+ UINT8 DwordPrefix2;
+ UINT32 TransLatency;
+ UINT8 DwordPrefix3;
+ UINT32 BMLatency;
+ UINT8 DwordPrefix4;
+ UINT32 Control;
+ UINT8 DwordPrefix5;
+ UINT32 Status;
+} EFI_PSS_PACKAGE;
+#pragma pack()
+
+
+#define AML_NAME_OP 0x08
+#define AML_METHOD_OP 0x14
+#define AML_OPREGION_OP 0x80
+#define AML_PACKAGE_OP 0x12 // Package operator.
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID "INTEL "
+#define EFI_ACPI_OEM_TABLE_ID 0x2020204F4E414954 // "TIANO "
+#define EFI_ACPI_OEM_REVISION 0x00000002
+#define EFI_ACPI_CREATOR_ID 0x5446534D // "MSFT"
+#define EFI_ACPI_CREATOR_REVISION 0x01000013
+
+#define ACPI_COMPATIBLE_1_0 0
+#define ACPI_COMPATIBLE_2_0 1
+#define ACPI_COMPATIBLE_3_0 2
+
+
+
+
+//
+// Private Driver Data
+//
+
+//
+// Define Union of IO APIC & Local APIC structure;
+//
+
+typedef union {
+ EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE AcpiLocalApic;
+ EFI_ACPI_2_0_IO_APIC_STRUCTURE AcpiIoApic;
+ struct {
+ UINT8 Type;
+ UINT8 Length;
+ } AcpiApicCommon;
+} ACPI_APIC_STRUCTURE_PTR;
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf
new file mode 100644
index 0000000..8a003c3
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf
@@ -0,0 +1,221 @@
+## @file
+# Component description file for AcpiPlatform module.
+#
+# This is an implementation of the ACPI platform driver,
+# whose requirements are from ACPI External Product Specification.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = 368B3649-F204-4cd0-89A8-091077C070FA
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AcpiPlatformEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ AcpiPlatform.c
+ AcpiPlatform.h
+ MadtPlatform.c
+ Madt.h
+ AcpiPciUpdate.c
+ AcpiPciUpdate.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ DxeServicesLib
+ PcdLib
+ IoLib
+ BaseMemoryLib
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DevicePathLib
+
+[Protocols]
+ gEfiGlobalNvsAreaProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiMpServiceProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+ gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[FixedPcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14GlobalIrq
+
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15Enable
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15SourceIrq
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15Polarity
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15GlobalIrq
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingIoApicAddress
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingGlobalInterruptBase
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingIoApicId
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingNmiEnable
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingNmiSource
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingPolarity
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingTrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingNmiEnabelApicIdMask
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingAddressOverrideEnable
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingPolarity
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingTrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingLocalApicLint
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicAddressOverride
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicSize
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciExpressSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSpiDmaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdWdtbaIoBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdHpetEnable
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
+
+[Depex]
+ gEfiMpServiceProtocolGuid AND gEfiAcpiTableProtocolGuid
+
diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/Madt.h b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/Madt.h
new file mode 100644
index 0000000..67f70f4
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/Madt.h
@@ -0,0 +1,238 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ Madt.h
+
+Abstract:
+
+ This file describes the contents of the ACPI Multiple APIC Description
+ Table (MADT). Some additional ACPI values are defined in Acpi10.h and
+ Acpi20.h.
+ To make changes to the MADT, it is necessary to update the count for the
+ APIC structure being updated, and to modify table found in Madt.c.
+
+--*/
+
+#ifndef _MADT_H
+#define _MADT_H
+
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/PcdLib.h>
+
+//
+// MADT Definitions
+//
+
+#define EFI_ACPI_OEM_MADT_REVISION 0x00000001
+
+//
+// Local APIC address
+//
+
+#define EFI_ACPI_LOCAL_APIC_ADDRESS 0xFEE00000
+
+//
+// Multiple APIC Flags are defined in AcpiX.0.h
+//
+#define EFI_ACPI_1_0_MULTIPLE_APIC_FLAGS (EFI_ACPI_1_0_PCAT_COMPAT)
+#define EFI_ACPI_2_0_MULTIPLE_APIC_FLAGS (EFI_ACPI_2_0_PCAT_COMPAT)
+
+//
+// Define the number of each table type.
+// This is where the table layout is modified.
+//
+
+#define EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT 2
+#define EFI_ACPI_IO_APIC_COUNT 1
+#define EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT 2
+#define EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT 0
+#define EFI_ACPI_LOCAL_APIC_NMI_COUNT 2
+#define EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT 0
+#define EFI_ACPI_IO_SAPIC_COUNT 0
+#define EFI_ACPI_PROCESSOR_LOCAL_SAPIC_COUNT 0
+#define EFI_ACPI_PLATFORM_INTERRUPT_SOURCES_COUNT 0
+
+#define EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX 16
+
+//
+// MADT structure
+//
+
+//
+// Ensure proper structure formats
+//
+#pragma pack (1)
+
+//
+// ACPI 1.0 Table structure
+//
+typedef struct {
+ EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
+
+#if EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT > 0
+ EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE LocalApic[EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_IO_APIC_COUNT > 0
+ EFI_ACPI_1_0_IO_APIC_STRUCTURE IoApic[EFI_ACPI_IO_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT > 0
+ EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE Iso[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT];
+#endif
+
+#if EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT > 0
+ EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE NmiSource[EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT];
+#endif
+
+#if EFI_ACPI_LOCAL_APIC_NMI_COUNT > 0
+ EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE LocalApicNmi[EFI_ACPI_LOCAL_APIC_NMI_COUNT];
+#endif
+
+#if EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT > 0
+ EFI_ACPI_1_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE LocalApicOverride[EFI_ACPI_LOCAL_APIC_OVERRIDE_COUNT];
+#endif
+
+} EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE;
+
+//
+// ACPI 2.0 Table structure
+//
+typedef struct {
+ EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
+
+#if EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT > 0
+ EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE LocalApic[EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_IO_APIC_COUNT > 0
+ EFI_ACPI_2_0_IO_APIC_STRUCTURE IoApic[EFI_ACPI_IO_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT > 0
+ EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE Iso[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT];
+#endif
+
+#if EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT > 0
+ EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE NmiSource[EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT];
+#endif
+
+#if EFI_ACPI_LOCAL_APIC_NMI_COUNT > 0
+ EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE LocalApicNmi[EFI_ACPI_LOCAL_APIC_NMI_COUNT];
+#endif
+
+#if EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT > 0
+ EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE LocalApicOverride[EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT];
+#endif
+
+#if EFI_ACPI_IO_SAPIC_COUNT > 0
+ EFI_ACPI_2_0_IO_SAPIC_STRUCTURE IoSapic[EFI_ACPI_IO_SAPIC_COUNT];
+#endif
+
+#if EFI_ACPI_PROCESSOR_LOCAL_SAPIC_COUNT > 0
+ EFI_ACPI_2_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE LocalSapic[EFI_ACPI_PROCESSOR_LOCAL_SAPIC_COUNT];
+#endif
+
+#if EFI_ACPI_PLATFORM_INTERRUPT_SOURCES_COUNT > 0
+ EFI_ACPI_2_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE PlatformInterruptSources[EFI_ACPI_PLATFORM_INTERRUPT_SOURCES_COUNT];
+#endif
+
+} EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE;
+
+#define _PcdIntSettingTblEnable(x) PcdGet8 (PcdInterruptOverrideSettingTable##x##Enable)
+#define PcdIntSettingTblEnable(x) _PcdIntSettingTblEnable(x)
+
+#define _PcdIntSettingTblSourceIrq(x) PcdGet8 (PcdInterruptOverrideSettingTable##x##Enable)
+#define PcdIntSettingTblSourceIrq(x) _PcdIntSettingTblSourceIrq(x)
+
+#define _PcdIntSettingTblPolarity(x) PcdGet8 (PcdInterruptOverrideSettingTable##x##Polarity)
+#define PcdIntSettingTblPolarity(x) _PcdIntSettingTblPolarity(x)
+
+#define _PcdIntSettingTableTrigerMode(x) PcdGet8 (PcdInterruptOverrideSettingTable##x##TrigerMode)
+#define PcdIntSettingTableTrigerMode(x) _PcdIntSettingTableTrigerMode(x)
+
+#define _PcdIntSettingTableGlobalIrq(x) PcdGet32 (PcdInterruptOverrideSettingTable##x##GlobalIrq)
+#define PcdIntSettingTableGlobalIrq(x) _PcdIntSettingTableGlobalIrq(x)
+
+typedef struct {
+ UINT8 Enable;
+ UINT8 SourceIrq;
+ UINT8 Polarity;
+ UINT8 TrigerMode;
+ UINT32 GlobalIrq;
+} INTERRUPT_OVERRIDE_SETTING;
+
+
+typedef struct {
+ UINT32 IoApicAddress;
+ UINT32 GlobalInterruptBase;
+ UINT8 IoApicId;
+ UINT8 NmiEnable;
+ UINT8 NmiSource;
+ UINT8 Polarity;
+ UINT8 TrigerMode;
+} IO_APIC_SETTING;
+
+typedef struct {
+ UINT8 NmiEnabelApicIdMask;
+ UINT8 AddressOverrideEnable;
+ UINT8 Polarity;
+ UINT8 TrigerMode;
+ UINT8 LocalApicLint;
+ UINT8 Reserve[3];
+ UINT32 LocalApicAddress;
+ UINT64 LocalApicAddressOverride;
+} LOCAL_APIC_SETTING;
+
+typedef struct _MADT_CONFIG_DATA {
+ INTERRUPT_OVERRIDE_SETTING MadtInterruptSetting[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX];
+ IO_APIC_SETTING MadtIoApicSetting;
+ LOCAL_APIC_SETTING MadtLocalApicSetting;
+}MADT_CONFIG_DATA;
+
+#pragma pack ()
+
+EFI_STATUS
+EFIAPI
+MadtTableInitialize (
+ OUT EFI_ACPI_COMMON_HEADER **MadtTable,
+ OUT UINTN *Size
+ );
+
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c
new file mode 100644
index 0000000..f8fe225
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c
@@ -0,0 +1,331 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MadtPlatform.c
+
+Abstract:
+
+ This file contains Madt Talbe initialized work.
+
+--*/
+
+//
+// Statements that include other files
+//
+
+#include "AcpiPlatform.h"
+
+VOID
+InitMadtConfigData (MADT_CONFIG_DATA *mConfigData)
+{
+ mConfigData->MadtInterruptSetting[0].Enable = PcdGet8 (PcdInterruptOverrideSettingTable0Enable);
+ mConfigData->MadtInterruptSetting[0].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable0SourceIrq);
+ mConfigData->MadtInterruptSetting[0].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable0Polarity);
+ mConfigData->MadtInterruptSetting[0].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable0TrigerMode);
+ mConfigData->MadtInterruptSetting[0].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable0GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[1].Enable = PcdGet8 (PcdInterruptOverrideSettingTable1Enable);
+ mConfigData->MadtInterruptSetting[1].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable1SourceIrq);
+ mConfigData->MadtInterruptSetting[1].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable1Polarity);
+ mConfigData->MadtInterruptSetting[1].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable1TrigerMode);
+ mConfigData->MadtInterruptSetting[1].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable1GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[2].Enable = PcdGet8 (PcdInterruptOverrideSettingTable2Enable);
+ mConfigData->MadtInterruptSetting[2].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable2SourceIrq);
+ mConfigData->MadtInterruptSetting[2].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable2Polarity);
+ mConfigData->MadtInterruptSetting[2].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable2TrigerMode);
+ mConfigData->MadtInterruptSetting[2].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable2GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[3].Enable = PcdGet8 (PcdInterruptOverrideSettingTable3Enable);
+ mConfigData->MadtInterruptSetting[3].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable3SourceIrq);
+ mConfigData->MadtInterruptSetting[3].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable3Polarity);
+ mConfigData->MadtInterruptSetting[3].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable3TrigerMode);
+ mConfigData->MadtInterruptSetting[3].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable3GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[4].Enable = PcdGet8 (PcdInterruptOverrideSettingTable4Enable);
+ mConfigData->MadtInterruptSetting[4].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable4SourceIrq);
+ mConfigData->MadtInterruptSetting[4].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable4Polarity);
+ mConfigData->MadtInterruptSetting[4].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable4TrigerMode);
+ mConfigData->MadtInterruptSetting[4].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable4GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[5].Enable = PcdGet8 (PcdInterruptOverrideSettingTable5Enable);
+ mConfigData->MadtInterruptSetting[5].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable5SourceIrq);
+ mConfigData->MadtInterruptSetting[5].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable5Polarity);
+ mConfigData->MadtInterruptSetting[5].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable5TrigerMode);
+ mConfigData->MadtInterruptSetting[5].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable5GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[6].Enable = PcdGet8 (PcdInterruptOverrideSettingTable6Enable);
+ mConfigData->MadtInterruptSetting[6].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable6SourceIrq);
+ mConfigData->MadtInterruptSetting[6].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable6Polarity);
+ mConfigData->MadtInterruptSetting[6].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable6TrigerMode);
+ mConfigData->MadtInterruptSetting[6].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable6GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[7].Enable = PcdGet8 (PcdInterruptOverrideSettingTable7Enable);
+ mConfigData->MadtInterruptSetting[7].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable7SourceIrq);
+ mConfigData->MadtInterruptSetting[7].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable7Polarity);
+ mConfigData->MadtInterruptSetting[7].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable7TrigerMode);
+ mConfigData->MadtInterruptSetting[7].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable7GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[8].Enable = PcdGet8 (PcdInterruptOverrideSettingTable8Enable);
+ mConfigData->MadtInterruptSetting[8].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable8SourceIrq);
+ mConfigData->MadtInterruptSetting[8].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable8Polarity);
+ mConfigData->MadtInterruptSetting[8].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable8TrigerMode);
+ mConfigData->MadtInterruptSetting[8].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable8GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[9].Enable = PcdGet8 (PcdInterruptOverrideSettingTable9Enable);
+ mConfigData->MadtInterruptSetting[9].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable9SourceIrq);
+ mConfigData->MadtInterruptSetting[9].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable9Polarity);
+ mConfigData->MadtInterruptSetting[9].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable9TrigerMode);
+ mConfigData->MadtInterruptSetting[9].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable9GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[10].Enable = PcdGet8 (PcdInterruptOverrideSettingTable10Enable);
+ mConfigData->MadtInterruptSetting[10].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable10SourceIrq);
+ mConfigData->MadtInterruptSetting[10].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable10Polarity);
+ mConfigData->MadtInterruptSetting[10].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable10TrigerMode);
+ mConfigData->MadtInterruptSetting[10].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable10GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[11].Enable = PcdGet8 (PcdInterruptOverrideSettingTable11Enable);
+ mConfigData->MadtInterruptSetting[11].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable11SourceIrq);
+ mConfigData->MadtInterruptSetting[11].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable11Polarity);
+ mConfigData->MadtInterruptSetting[11].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable11TrigerMode);
+ mConfigData->MadtInterruptSetting[11].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable11GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[12].Enable = PcdGet8 (PcdInterruptOverrideSettingTable12Enable);
+ mConfigData->MadtInterruptSetting[12].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable12SourceIrq);
+ mConfigData->MadtInterruptSetting[12].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable12Polarity);
+ mConfigData->MadtInterruptSetting[12].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable12TrigerMode);
+ mConfigData->MadtInterruptSetting[12].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable12GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[13].Enable = PcdGet8 (PcdInterruptOverrideSettingTable13Enable);
+ mConfigData->MadtInterruptSetting[13].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable13SourceIrq);
+ mConfigData->MadtInterruptSetting[13].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable13Polarity);
+ mConfigData->MadtInterruptSetting[13].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable13TrigerMode);
+ mConfigData->MadtInterruptSetting[13].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable13GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[14].Enable = PcdGet8 (PcdInterruptOverrideSettingTable14Enable);
+ mConfigData->MadtInterruptSetting[14].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable14SourceIrq);
+ mConfigData->MadtInterruptSetting[14].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable14Polarity);
+ mConfigData->MadtInterruptSetting[14].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable14TrigerMode);
+ mConfigData->MadtInterruptSetting[14].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable14GlobalIrq);
+
+ mConfigData->MadtInterruptSetting[15].Enable = PcdGet8 (PcdInterruptOverrideSettingTable15Enable);
+ mConfigData->MadtInterruptSetting[15].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable15SourceIrq);
+ mConfigData->MadtInterruptSetting[15].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable15Polarity);
+ mConfigData->MadtInterruptSetting[15].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable15TrigerMode);
+ mConfigData->MadtInterruptSetting[15].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable15GlobalIrq);
+
+ mConfigData->MadtIoApicSetting.IoApicAddress = (UINT32)PcdGet64(PcdIoApicBaseAddress);
+ mConfigData->MadtIoApicSetting.GlobalInterruptBase = PcdGet32 (PcdIoApicSettingGlobalInterruptBase);
+ mConfigData->MadtIoApicSetting.IoApicId = PcdGet8 (PcdIoApicSettingIoApicId);
+ mConfigData->MadtIoApicSetting.NmiEnable = PcdGet8 (PcdIoApicSettingNmiEnable);
+ mConfigData->MadtIoApicSetting.NmiSource = PcdGet8 (PcdIoApicSettingNmiSource);
+ mConfigData->MadtIoApicSetting.Polarity = PcdGet8 (PcdIoApicSettingPolarity);
+ mConfigData->MadtIoApicSetting.TrigerMode = PcdGet8 (PcdIoApicSettingTrigerMode);
+
+ mConfigData->MadtLocalApicSetting.NmiEnabelApicIdMask = PcdGet8 (PcdLocalApicSettingNmiEnabelApicIdMask);
+ mConfigData->MadtLocalApicSetting.AddressOverrideEnable = PcdGet8 (PcdLocalApicSettingAddressOverrideEnable);
+ mConfigData->MadtLocalApicSetting.Polarity = PcdGet8 (PcdLocalApicSettingPolarity);
+ mConfigData->MadtLocalApicSetting.TrigerMode = PcdGet8 (PcdLocalApicSettingTrigerMode);
+ mConfigData->MadtLocalApicSetting.LocalApicLint = PcdGet8 (PcdLocalApicSettingLocalApicLint);
+ mConfigData->MadtLocalApicSetting.LocalApicAddressOverride = PcdGet64 (PcdLocalApicAddressOverride);
+ mConfigData->MadtLocalApicSetting.LocalApicAddress = PcdGet32 (PcdCpuLocalApicBaseAddress);
+}
+UINT32
+GetAcutalMadtTableSize (
+ IN MADT_CONFIG_DATA * MadtConfigData,
+ IN INTN NumberOfCPUs
+ )
+{
+ UINT32 MadtSize;
+ UINT8 Index;
+ MadtSize = (UINT32)(sizeof (EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) +
+ sizeof (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE) * NumberOfCPUs +
+ sizeof (EFI_ACPI_2_0_IO_APIC_STRUCTURE) +
+ sizeof (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE) * (MadtConfigData->MadtLocalApicSetting.AddressOverrideEnable != 0?1:0)
+ );
+ for (Index = 0; Index < EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX; Index ++ ) {
+ if (MadtConfigData->MadtInterruptSetting[Index].Enable != 0) {
+ MadtSize += sizeof (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE);
+ }
+ }
+ for (Index = 0; Index < NumberOfCPUs; Index ++ ) {
+ if (0 != (MadtConfigData->MadtLocalApicSetting.NmiEnabelApicIdMask & (1 << Index))) {
+ MadtSize += sizeof (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE);
+ }
+ }
+ if (0 != MadtConfigData->MadtIoApicSetting.NmiEnable) {
+ MadtSize += sizeof (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE);
+ }
+ return MadtSize;
+}
+
+//
+// Init Multiple APIC Description Table
+//
+EFI_STATUS
+MadtTableInitialize (
+ OUT EFI_ACPI_COMMON_HEADER **MadtTable,
+ OUT UINTN *Size
+ )
+{
+ EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;
+ EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *ProcLocalApic;
+ EFI_ACPI_2_0_IO_APIC_STRUCTURE *IoApic;
+ EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *InterruptSourceOverride;
+ EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *IoApicNmiSource;
+ EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNmiSource;
+ EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *LocalApicAddressOverride;
+
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+ UINTN NumberOfCPUs;
+ UINTN NumberOfEnabledCPUs;
+ MADT_CONFIG_DATA MadtConfigData;
+
+ UINT32 MadtSize;
+ UINTN Index;
+ EFI_STATUS Status;
+
+
+ ASSERT (NULL != MadtTable);
+ ASSERT (NULL != Size);
+ //
+ // Init Madt table data
+ //
+ InitMadtConfigData (&MadtConfigData);
+ //
+ // Find the MP Protocol. This is an MP platform, so MP protocol must be
+ // there.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **)&MpService
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Determine the number of processors
+ //
+ MpService->GetNumberOfProcessors (
+ MpService,
+ &NumberOfCPUs,
+ &NumberOfEnabledCPUs
+ );
+ //ASSERT (NumberOfCPUs <= 2 && NumberOfCPUs > 0);
+ MadtSize = GetAcutalMadtTableSize (&MadtConfigData, NumberOfCPUs);
+ Madt = (EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)AllocateZeroPool (MadtSize);
+ ASSERT_EFI_ERROR (Madt);
+ //
+ // Initialize MADT Header information
+ //
+ Madt->Header.Signature = EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE;
+ Madt->Header.Length = MadtSize;
+ Madt->Header.Revision = EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION;
+ Madt->Header.OemTableId = EFI_ACPI_OEM_TABLE_ID;
+ Madt->Header.OemRevision = EFI_ACPI_OEM_MADT_REVISION;
+ Madt->Header.CreatorId = EFI_ACPI_CREATOR_ID;
+ Madt->LocalApicAddress = MadtConfigData.MadtLocalApicSetting.LocalApicAddress;
+ Madt->Flags = EFI_ACPI_2_0_MULTIPLE_APIC_FLAGS;
+ CopyMem (Madt->Header.OemId, EFI_ACPI_OEM_ID, 6);
+
+ ProcLocalApic = (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *) (Madt + 1);
+ //
+ // Initialization of Processor's local APICs
+ //
+ for (Index = 0;Index < NumberOfCPUs; Index++) {
+ ProcLocalApic[Index].Type = EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC;
+ ProcLocalApic[Index].Length = sizeof (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE);
+ ProcLocalApic[Index].AcpiProcessorId = (UINT8)(Index + 1);
+ ProcLocalApic[Index].ApicId = 0xff;
+ ProcLocalApic[Index].Flags = 0;
+ }
+ //
+ // Initialization of IO APIC.
+ // Note: Here assumes that there must be one and only one IO APIC in platform.
+ //
+ IoApic = (EFI_ACPI_2_0_IO_APIC_STRUCTURE *) (&ProcLocalApic[Index]);
+ IoApic->Type = EFI_ACPI_2_0_IO_APIC;
+ IoApic->Length = sizeof (EFI_ACPI_2_0_IO_APIC_STRUCTURE);
+ IoApic->IoApicId = MadtConfigData.MadtIoApicSetting.IoApicId;
+ IoApic->IoApicAddress = MadtConfigData.MadtIoApicSetting.IoApicAddress;
+ IoApic->GlobalSystemInterruptBase = MadtConfigData.MadtIoApicSetting.GlobalInterruptBase;
+
+ InterruptSourceOverride = (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *) (IoApic + 1);
+ for (Index = 0;Index < EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX; Index++ ){
+ if (MadtConfigData.MadtInterruptSetting[Index].Enable) {
+ InterruptSourceOverride->Type = EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE;
+ InterruptSourceOverride->Length = sizeof (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE);
+ InterruptSourceOverride->Bus = 0;
+ InterruptSourceOverride->Source = MadtConfigData.MadtInterruptSetting[Index].SourceIrq;
+ InterruptSourceOverride->Flags = ((MadtConfigData.MadtInterruptSetting[Index].TrigerMode & 0x03) << 2) | (MadtConfigData.MadtInterruptSetting[Index].Polarity & 0x03);
+ InterruptSourceOverride->GlobalSystemInterrupt = MadtConfigData.MadtInterruptSetting[Index].GlobalIrq;
+ InterruptSourceOverride++;
+ }
+ }
+ //
+ // support NMI source configuration.
+ //
+ IoApicNmiSource = (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *) InterruptSourceOverride;
+ if ((BOOLEAN) MadtConfigData.MadtIoApicSetting.NmiEnable) {
+ IoApicNmiSource->Type = EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE;
+ IoApicNmiSource->Length = sizeof (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE);
+ IoApicNmiSource->Flags = ((MadtConfigData.MadtIoApicSetting.TrigerMode & 0x03) << 2) | (MadtConfigData.MadtIoApicSetting.Polarity & 0x03);
+ IoApicNmiSource->GlobalSystemInterrupt = MadtConfigData.MadtIoApicSetting.NmiSource;
+ IoApicNmiSource ++;
+ }
+ //
+ // Assume each processor has same NMI interrupt source.
+ //
+ LocalApicNmiSource = (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE *) IoApicNmiSource;
+ for (Index = 0;Index < NumberOfCPUs; Index++) {
+ if (0 != (MadtConfigData.MadtLocalApicSetting.NmiEnabelApicIdMask & (1 << Index))){
+ LocalApicNmiSource->Type = EFI_ACPI_2_0_LOCAL_APIC_NMI;
+ LocalApicNmiSource->Length = sizeof (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE);
+ LocalApicNmiSource->LocalApicLint = MadtConfigData.MadtLocalApicSetting.LocalApicLint;
+ LocalApicNmiSource->Flags = ((MadtConfigData.MadtLocalApicSetting.TrigerMode & 0x03) << 2) | (MadtConfigData.MadtLocalApicSetting.Polarity & 0x03);
+ LocalApicNmiSource->AcpiProcessorId = (UINT8)(Index + 1);
+ LocalApicNmiSource++;
+ }
+ }
+
+ LocalApicAddressOverride = (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *) LocalApicNmiSource;
+ if ((BOOLEAN) MadtConfigData.MadtLocalApicSetting.AddressOverrideEnable) {
+ LocalApicAddressOverride->Type = EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE;
+ LocalApicAddressOverride->Length = sizeof (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE);
+ LocalApicAddressOverride->LocalApicAddress = MadtConfigData.MadtLocalApicSetting.LocalApicAddressOverride;
+ LocalApicAddressOverride++;
+ }
+ *Size = MadtSize;
+ *MadtTable = (EFI_ACPI_COMMON_HEADER *) Madt;
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
new file mode 100755
index 0000000..d7e1427
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
@@ -0,0 +1,100 @@
+## @file
+# Boot Script Executor Module
+#
+# This is a standalone Boot Script Executor. Standalone means it does not
+# depends on any PEI or DXE service.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BootScriptExecutorDxe
+ FILE_GUID = FA20568B-548B-4b2b-81EF-1BA08D4A3CEC
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BootScriptExecutorEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ ScriptExecute.h
+ ScriptExecute.c
+
+[Sources.Ia32]
+ IA32/SetIdtEntry.c
+ IA32/S3Asm.asm
+ IA32/S3Asm.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ TimerLib
+ PcdLib
+ BaseMemoryLib
+ SmbusLib
+ UefiDriverEntryPoint
+ BaseLib
+ PciLib
+ IoLib
+ S3BootScriptLib
+ PeCoffLib
+ DxeServicesLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ CacheMaintenanceLib
+ UefiLib
+ DebugAgentLib
+ LockBoxLib
+ IntelQNCLib
+ QNCAccessLib
+
+[Guids]
+ gEfiBootScriptExecutorVariableGuid
+ gEfiBootScriptExecutorContextGuid
+ gPerformanceProtocolGuid
+ gEfiEventExitBootServicesGuid
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+
+[Depex]
+ gEfiLockBoxProtocolGuid
+
diff --git a/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.S b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.S
new file mode 100755
index 0000000..5d74f54
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.S
@@ -0,0 +1,68 @@
+## @file
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#-----------------------------------------
+#VOID
+#AsmTransferControl (
+# IN UINT32 S3WakingVector,
+# IN UINT32 AcpiLowMemoryBase
+# );
+#-----------------------------------------
+
+ASM_GLOBAL ASM_PFX(AsmTransferControl)
+ASM_PFX(AsmTransferControl):
+ # S3WakingVector :DWORD
+ # AcpiLowMemoryBase :DWORD
+ pushl %ebp
+ movl %esp,%ebp
+ leal LABLE, %eax
+ pushl $0x28 # CS
+ pushl %eax
+ movl 8(%ebp),%ecx
+ shrdl $20,%ecx,%ebx
+ andl $0xf,%ecx
+ movw %cx,%bx
+ movl %ebx, jmp_addr
+ lret
+LABLE:
+ .byte 0xb8,0x30,0 # mov ax, 30h as selector
+ movw %ax,%ds
+ movw %ax,%es
+ movw %ax,%fs
+ movw %ax,%gs
+ movw %ax,%ss
+ movl %cr0, %eax # Get control register 0
+ .byte 0x66
+ .byte 0x83,0xe0,0xfe # and eax, 0fffffffeh ; Clear PE bit (bit #0)
+ .byte 0xf,0x22,0xc0 # mov cr0, eax ; Activate real mode
+ .byte 0xea # jmp far @jmp_addr
+jmp_addr:
+ .long 0
+
diff --git a/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.asm b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.asm
new file mode 100755
index 0000000..14b2909
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.asm
@@ -0,0 +1,75 @@
+;; @file
+; This is the assembly code for transferring to control to OS S3 waking vector
+; for IA32 platform
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ .586P
+ .model flat,C
+ .code
+
+;-----------------------------------------
+;VOID
+;AsmTransferControl (
+; IN UINT32 S3WakingVector,
+; IN UINT32 AcpiLowMemoryBase
+; );
+;-----------------------------------------
+
+AsmTransferControl PROC
+ ; S3WakingVector :DWORD
+ ; AcpiLowMemoryBase :DWORD
+ push ebp
+ mov ebp, esp
+ lea eax, @F
+ push 28h ; CS
+ push eax
+ mov ecx, [ebp + 8]
+ shrd ebx, ecx, 20
+ and ecx, 0fh
+ mov bx, cx
+ mov @jmp_addr, ebx
+ retf
+@@:
+ DB 0b8h, 30h, 0 ; mov ax, 30h as selector
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ mov eax, cr0 ; Get control register 0
+ DB 66h
+ DB 83h, 0e0h, 0feh ; and eax, 0fffffffeh ; Clear PE bit (bit #0)
+ DB 0fh, 22h, 0c0h ; mov cr0, eax ; Activate real mode
+ DB 0eah ; jmp far @jmp_addr
+@jmp_addr DD ?
+
+AsmTransferControl ENDP
+
+ END \ No newline at end of file
diff --git a/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/SetIdtEntry.c b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/SetIdtEntry.c
new file mode 100755
index 0000000..8d7f699
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/SetIdtEntry.c
@@ -0,0 +1,81 @@
+/** @file
+ Set a IDT entry for debug purpose
+
+ Set a IDT entry for interrupt vector 3 for debug purpose for IA32 platform
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "ScriptExecute.h"
+//
+// INTERRUPT_GATE_DESCRIPTOR and SetIdtEntry () are used to setup IDT to do debug
+//
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 OffsetLow;
+ UINT16 SegmentSelector;
+ UINT16 Attributes;
+ UINT16 OffsetHigh;
+} INTERRUPT_GATE_DESCRIPTOR;
+
+#define INTERRUPT_GATE_ATTRIBUTE 0x8e00
+
+#pragma pack()
+/**
+ Set a IDT entry for interrupt vector 3 for debug purpose.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+
+**/
+VOID
+SetIdtEntry (
+ IN ACPI_S3_CONTEXT *AcpiS3Context
+ )
+{
+ INTERRUPT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR *IdtDescriptor;
+ UINTN S3DebugBuffer;
+
+ //
+ // Restore IDT for debug
+ //
+ IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);
+ IdtEntry = (INTERRUPT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (INTERRUPT_GATE_DESCRIPTOR)));
+ S3DebugBuffer = (UINTN) (AcpiS3Context->S3DebugBufferAddress);
+
+ IdtEntry->OffsetLow = (UINT16)S3DebugBuffer;
+ IdtEntry->SegmentSelector = (UINT16)AsmReadCs ();
+ IdtEntry->Attributes = (UINT16)INTERRUPT_GATE_ATTRIBUTE;
+ IdtEntry->OffsetHigh = (UINT16)(S3DebugBuffer >> 16);
+
+ AsmWriteIdtr (IdtDescriptor);
+}
+
diff --git a/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.c b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.c
new file mode 100755
index 0000000..738cd9c
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.c
@@ -0,0 +1,403 @@
+/** @file
+ This is the code for Boot Script Executer module.
+
+ This driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory
+ in the entry point. The functionality is to interpret and restore the S3 boot script
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "ScriptExecute.h"
+
+#pragma pack(1)
+typedef union {
+ struct {
+ UINT32 LimitLow : 16;
+ UINT32 BaseLow : 16;
+ UINT32 BaseMid : 8;
+ UINT32 Type : 4;
+ UINT32 System : 1;
+ UINT32 Dpl : 2;
+ UINT32 Present : 1;
+ UINT32 LimitHigh : 4;
+ UINT32 Software : 1;
+ UINT32 Reserved : 1;
+ UINT32 DefaultSize : 1;
+ UINT32 Granularity : 1;
+ UINT32 BaseHigh : 8;
+ } Bits;
+ UINT64 Uint64;
+} IA32_GDT;
+
+#pragma pack()
+
+EFI_GUID mBootScriptExecutorImageGuid = {
+ 0x9a8d3433, 0x9fe8, 0x42b6, 0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b
+};
+
+//
+// Global Descriptor Table (GDT)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
+/* selector { Global Segment Descriptor } */
+/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x08 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x10 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}},
+/* 0x18 */ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}},
+/* 0x20 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x28 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 0, 1, 0}},
+/* 0x30 */ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 0, 1, 0}},
+/* 0x38 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}},
+/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+};
+
+//
+// IA32 Gdt register
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
+ sizeof (mGdtEntries) - 1,
+ (UINTN) mGdtEntries
+ };
+
+/**
+ Entry function of Boot script exector. This function will be executed in
+ S3 boot path.
+ This function should not return, because it is invoked by switch stack.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+ @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
+
+ @retval EFI_INVALID_PARAMETER - OS waking vector not found
+ @retval EFI_UNSUPPORTED - something wrong when we resume to OS
+**/
+EFI_STATUS
+EFIAPI
+S3BootScriptExecutorEntryFunction (
+ IN ACPI_S3_CONTEXT *AcpiS3Context,
+ IN PEI_S3_RESUME_STATE *PeiS3ResumeState
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Disable interrupt of Debug timer, since new IDT table cannot handle it.
+ //
+ SaveAndSetDebugTimerInterrupt (FALSE);
+
+ //
+ // Restore IDT for debug
+ //
+ SetIdtEntry (AcpiS3Context);
+
+ //
+ // Initialize Debug Agent to support source level debug in S3 path.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_S3, NULL, NULL);
+
+ //
+ // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL
+ // for that parameter.
+ //
+ Status = S3BootScriptExecute ();
+
+ AsmWbinvd ();
+
+ //
+ // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume.
+ //
+ if (PeiS3ResumeState != 0) {
+ //
+ // Need report status back to S3ResumePeim.
+ // If boot script execution is failed, S3ResumePeim wil report the error status code.
+ //
+ PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status;
+ //
+ // IA32 S3 Resume
+ //
+ DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));
+ PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformTransferControl16;
+
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint,
+ (VOID *)(UINTN)AcpiS3Context,
+ (VOID *)(UINTN)PeiS3ResumeState,
+ (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer
+ );
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop();
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop();
+ return EFI_UNSUPPORTED;
+}
+/**
+ Entrypoint of Boot script exector driver, this function will be executed in
+ normal boot phase and invoked by DXE dispatch.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+**/
+EFI_STATUS
+EFIAPI
+BootScriptExecutorEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINT8 *Buffer;
+ UINTN BufferSize;
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS FfsBuffer;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
+ EFI_PHYSICAL_ADDRESS BootScriptExecutorBuffer;
+ EFI_STATUS Status;
+ VOID *DevicePath;
+ EFI_HANDLE NewImageHandle;
+
+ //
+ // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
+ // point is loaded by DXE code which is the first time loaded. or else, it is already
+ // be reloaded be itself.This is a work-around
+ //
+ Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
+ if (EFI_ERROR (Status)) {
+
+ //
+ // This is the first-time loaded by DXE core. reload itself to NVS mem
+ //
+ //
+ // A workarouond: Here we install a dummy handle
+ //
+ NewImageHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewImageHandle,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+
+ Status = GetSectionFromAnyFv (
+ &gEfiCallerIdGuid,
+ EFI_SECTION_PE32,
+ 0,
+ (VOID **) &Buffer,
+ &BufferSize
+ );
+ ImageContext.Handle = Buffer;
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+ //
+ // Get information about the image being loaded
+ //
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Pages = EFI_SIZE_TO_PAGES(BufferSize + ImageContext.SectionAlignment);
+ FfsBuffer = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &FfsBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
+ //
+ // Align buffer on section boundry
+ //
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+ ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (FfsBuffer, Pages);
+ return Status;
+ }
+
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+
+ if (EFI_ERROR (Status)) {
+ PeCoffLoaderUnloadImage (&ImageContext);
+ gBS->FreePages (FfsBuffer, Pages);
+ return Status;
+ }
+ //
+ // Flush the instruction cache so the image data is written before we execute it
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+ Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (FfsBuffer, Pages);
+ return Status;
+ }
+ //
+ // Additional step for BootScript integrity
+ // Save BootScriptExecutor image
+ //
+ Status = SaveLockBox (
+ &mBootScriptExecutorImageGuid,
+ (VOID *)(UINTN)ImageContext.ImageAddress,
+ (UINTN)ImageContext.ImageSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ ASSERT_EFI_ERROR (Status);
+
+ } else {
+ //
+ // the entry point is invoked after reloading. following code only run in ACPI NVS
+ //
+ BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
+
+ BootScriptExecutorBuffer = 0xFFFFFFFF;
+ Pages = EFI_SIZE_TO_PAGES(BufferSize);
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &BootScriptExecutorBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer;
+ EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN) S3BootScriptExecutorEntryFunction ;
+
+ Status = SaveLockBox (
+ &gEfiBootScriptExecutorVariableGuid,
+ &BootScriptExecutorBuffer,
+ sizeof(BootScriptExecutorBuffer)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Additional step for BootScript integrity
+ // Save BootScriptExecutor context
+ //
+ Status = SaveLockBox (
+ &gEfiBootScriptExecutorContextGuid,
+ EfiBootScriptExecutorVariable,
+ sizeof(*EfiBootScriptExecutorVariable)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ ASSERT_EFI_ERROR (Status);
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Platform specific mechanism to transfer control to 16bit OS waking vector
+
+ @param[in] AcpiWakingVector The 16bit OS waking vector
+ @param[in] AcpiLowMemoryBase A buffer under 1M which could be used during the transfer
+
+**/
+VOID
+PlatformTransferControl16 (
+ IN UINT32 AcpiWakingVector,
+ IN UINT32 AcpiLowMemoryBase
+ )
+{
+ UINT32 NewValue;
+ UINT64 BaseAddress;
+ UINT64 SmramLength;
+ UINTN Index;
+
+ DEBUG (( EFI_D_INFO, "PlatformTransferControl - Entry\r\n"));
+
+ //
+ // Need to make sure the GDT is loaded with values that support long mode and real mode.
+ //
+ AsmWriteGdtr (&mGdt);
+
+ //
+ // Disable eSram block (this will also clear/zero eSRAM)
+ // We only use eSRAM in the PEI phase. Disable now that we are resuming the OS
+ //
+ NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK);
+ NewValue |= BLOCK_DISABLE_PG;
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK, NewValue);
+
+ //
+ // Update HMBOUND to top of DDR3 memory and LOCK
+ // We disabled eSRAM so now we move HMBOUND down to top of DDR3
+ //
+ QNCGetTSEGMemoryRange (&BaseAddress, &SmramLength);
+ NewValue = (UINT32)(BaseAddress + SmramLength);
+ DEBUG ((EFI_D_INFO,"Locking HMBOUND at: = 0x%8x\n",NewValue));
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG, (NewValue | HMBOUND_LOCK));
+
+ //
+ // Lock all IMR regions now that HMBOUND is locked
+ //
+ for (Index = (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL); Index <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL); Index += 4) {
+ NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index);
+ NewValue |= IMR_LOCK;
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index, NewValue);
+ }
+
+ //
+ // Call ASM routine to switch to real mode and jump to 16bit OS waking vector
+ //
+ AsmTransferControl(AcpiWakingVector, 0);
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop();
+}
+
+
+
+
diff --git a/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.h b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.h
new file mode 100755
index 0000000..60bea54
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.h
@@ -0,0 +1,94 @@
+/** @file
+ The header file for Boot Script Executer module.
+
+ This driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory
+ in the entry point. The functionality is to interpret and restore the S3 boot script
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef _SCRIPT_EXECUTE_H_
+#define _SCRIPT_EXECUTE_H_
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/QNCAccessLib.h>
+
+#include <Guid/AcpiS3Context.h>
+#include <Guid/BootScriptExecutorVariable.h>
+#include <Guid/EventGroup.h>
+#include <IndustryStandard/Acpi.h>
+
+/**
+ a ASM function to transfer control to OS.
+
+ @param S3WakingVector The S3 waking up vector saved in ACPI Facs table
+ @param AcpiLowMemoryBase a buffer under 1M which could be used during the transfer
+**/
+VOID
+AsmTransferControl (
+ IN UINT32 S3WakingVector,
+ IN UINT32 AcpiLowMemoryBase
+ );
+
+VOID
+SetIdtEntry (
+ IN ACPI_S3_CONTEXT *AcpiS3Context
+ );
+
+/**
+ Platform specific mechanism to transfer control to 16bit OS waking vector
+
+ @param[in] AcpiWakingVector The 16bit OS waking vector
+ @param[in] AcpiLowMemoryBase A buffer under 1M which could be used during the transfer
+
+**/
+VOID
+PlatformTransferControl16 (
+ IN UINT32 AcpiWakingVector,
+ IN UINT32 AcpiLowMemoryBase
+ );
+
+#endif //_SCRIPT_EXECUTE_H_
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c
new file mode 100755
index 0000000..7172f50
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c
@@ -0,0 +1,1040 @@
+/*++
+
+ This is QNC Smm platform driver
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ AcpiSmmPlatform.c
+
+Abstract:
+
+ ACPISMM Driver implementation file.
+
+--*/
+
+#include <AcpiSmmPlatform.h>
+
+#define PCILIB_TO_COMMON_ADDRESS(Address) \
+ ((UINT64) ((((UINTN) ((Address>>20) & 0xff)) << 24) + (((UINTN) ((Address>>15) & 0x1f)) << 16) + (((UINTN) ((Address>>12) & 0x07)) << 8) + ((UINTN) (Address & 0xfff ))))
+
+//
+// Modular variables needed by this driver
+//
+EFI_ACPI_SMM_DEV mAcpiSmm;
+
+STATIC UINT8 mPciCfgRegTable[] = {
+ //
+ // Logic to decode the table masks to arrive at the registers saved
+ // Dword Registers are saved. For a given mask, the Base+offset register
+ // will be saved as in the table below.
+ // (example) To save register 0x24, 0x28 the mask at the Base 0x20 will be 0x06
+ // Base 0x00 0x20 0x40 0x60 0x80 0xA0 0xC0 0xE0
+ // Mask offset
+ // 0x01 0x00
+ // 0x02 0x04
+ // 0x04 0x08
+ // 0x08 0x0C
+ // 0x10 0x10
+ // 0x20 0x14
+ // 0x40 0x18
+ // 0x80 0x1C
+ //
+
+ //
+ // Bus, Dev, Func,
+ // 00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ // Only Bus 0 device is supported now
+ //
+
+ //
+ // Quark South Cluster devices
+ //
+ PCI_DEVICE (0, 20, 0),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 1),
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 2),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 3),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00),
+
+ PCI_DEVICE (0, 20, 4),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 5),
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 6),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 7),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 21, 0),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 21, 1),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 21, 2),
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ //
+ // Quark North Cluster devices
+ //
+ PCI_DEVICE (0, 0, 0),
+ PCI_REG_MASK (0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 23, 0),
+ PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 23, 1),
+ PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 31, 0),
+ PCI_REG_MASK (0x00, 0x08, 0x4E, 0x03, 0x02, 0x00, 0x60, 0x10),
+
+ PCI_DEVICE_END
+};
+
+EFI_PLATFORM_TYPE mPlatformType;
+
+ // These registers have to set in byte order
+const UINT8 QNCS3SaveExtReg[] = {
+ QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, // SMRAM settings
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_END_MEM_REG, // ECC Scrub settings
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_START_MEM_REG,
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_NEXT_READ_REG,
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG,
+
+ 0xFF
+ };
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+ @param Size Size of memory to allocate.
+
+ @return Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+ IN UINTN Size
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ VOID* Buffer;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xffffffff;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &Address
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Buffer = (VOID *) (UINTN) Address;
+ ZeroMem (Buffer, Size);
+
+ return Buffer;
+}
+
+EFI_STATUS
+EFIAPI
+ReservedS3Memory (
+ UINTN SystemMemoryLength
+
+ )
+/*++
+
+Routine Description:
+
+ Reserved S3 memory for InstallS3Memory
+
+Arguments:
+
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+{
+
+ VOID *GuidHob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+ VOID *AcpiReservedBase;
+
+ UINTN TsegIndex;
+ UINTN TsegSize;
+ UINTN TsegBase;
+ RESERVED_ACPI_S3_RANGE *AcpiS3Range;
+ //
+ // Get Hob list for SMRAM desc
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
+ ASSERT (GuidHob);
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (DescriptorBlock);
+
+ //
+ // Use the hob to get SMRAM capabilities
+ //
+ TsegIndex = DescriptorBlock->NumberOfSmmReservedRegions - 1;
+ ASSERT (TsegIndex <= (MAX_SMRAM_RANGES - 1));
+ TsegBase = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalStart;
+ TsegSize = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalSize;
+
+ DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", TsegBase));
+ DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", TsegSize));
+
+ //
+ // Now find the location of the data structure that is used to store the address
+ // of the S3 reserved memory.
+ //
+ AcpiS3Range = (RESERVED_ACPI_S3_RANGE*) (UINTN) (TsegBase + RESERVED_ACPI_S3_RANGE_OFFSET);
+
+ //
+ // Allocate reserved ACPI memory for S3 resume. Pointer to this region is
+ // stored in SMRAM in the first page of TSEG.
+ //
+ AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));
+ if (AcpiReservedBase != NULL) {
+ AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN) AcpiReservedBase;
+ AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);
+ }
+ AcpiS3Range->SystemMemoryLength = (UINT32)SystemMemoryLength;
+
+ DEBUG ((EFI_D_INFO, "S3 Memory Base: %08X\n", AcpiS3Range->AcpiReservedMemoryBase));
+ DEBUG ((EFI_D_INFO, "S3 Memory Size: %08X\n", AcpiS3Range->AcpiReservedMemorySize));
+ DEBUG ((EFI_D_INFO, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+InitAcpiSmmPlatform (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initializes the SMM S3 Handler Driver.
+
+Arguments:
+
+ ImageHandle - The image handle of Sleep State Wake driver.
+ SystemTable - The starndard EFI system table.
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.
+ EFI_SUCCESS - Function has completed successfully.
+ Other - Error occured during execution.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *AcpiNvsProtocol = NULL;
+ UINTN MemoryLength;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_PLATFORM_TYPE_PROTOCOL *PlatformTypeProtocol;
+
+ Status = gBS->LocateProtocol (
+ &gEfiGlobalNvsAreaProtocolGuid,
+ NULL,
+ &AcpiNvsProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mAcpiSmm.BootScriptSaved = 0;
+
+ Status = gBS->LocateProtocol (&gEfiPlatformTypeProtocolGuid, NULL, (VOID **) &PlatformTypeProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPlatformType = (EFI_PLATFORM_TYPE) PlatformTypeProtocol->Type;
+
+ //
+ // Calculate the system memory length by memory hobs
+ //
+ MemoryLength = 0x100000;
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+ ASSERT (Hob.Raw != NULL);
+ while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ //
+ // Skip the memory region below 1MB
+ //
+ if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {
+ MemoryLength += (UINTN)Hob.ResourceDescriptor->ResourceLength;
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
+ }
+
+ ReservedS3Memory(MemoryLength);
+
+ //
+ // Locate and Register to Parent driver
+ //
+ Status = RegisterToDispatchDriver ();
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RegisterToDispatchDriver (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Register to dispatch driver.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - Successfully init the device.
+ Other - Error occured whening calling Dxe lib functions.
+
+--*/
+{
+ UINTN Length;
+ EFI_STATUS Status;
+ EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryDispatchContext;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS1DispatchContext;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS3DispatchContext;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS4DispatchContext;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS5DispatchContext;
+ EFI_SMM_SW_REGISTER_CONTEXT *SwContext;
+ EFI_SMM_SW_REGISTER_CONTEXT *AcpiDisableSwContext;
+ EFI_SMM_SW_REGISTER_CONTEXT *AcpiEnableSwContext;
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ NULL,
+ &SxDispatch
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ &SwDispatch
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Length = sizeof (EFI_SMM_SX_REGISTER_CONTEXT) * 4 + sizeof (EFI_SMM_SW_REGISTER_CONTEXT) * 2;
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ Length,
+ &EntryDispatchContext
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SetMem (EntryDispatchContext, Length, 0);
+
+ EntryS1DispatchContext = EntryDispatchContext++;
+ EntryS3DispatchContext = EntryDispatchContext++;
+ EntryS4DispatchContext = EntryDispatchContext++;
+ EntryS5DispatchContext = EntryDispatchContext++;
+
+ SwContext = (EFI_SMM_SW_REGISTER_CONTEXT *)EntryDispatchContext;
+ AcpiDisableSwContext = SwContext++;
+ AcpiEnableSwContext = SwContext++;
+
+ //
+ // Register the enable handler
+ //
+ AcpiEnableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_ENABLE;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ EnableAcpiCallback,
+ AcpiEnableSwContext,
+ &(mAcpiSmm.DisableAcpiHandle)
+ );
+
+ //
+ // Register the disable handler
+ //
+ AcpiDisableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_DISABLE;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ DisableAcpiCallback,
+ AcpiDisableSwContext,
+ &(mAcpiSmm.EnableAcpiHandle)
+ );
+
+
+ //
+ // Register entry phase call back function for S1
+ //
+ EntryS1DispatchContext->Type = SxS1;
+ EntryS1DispatchContext->Phase = SxEntry;
+ Status = SxDispatch->Register (
+ SxDispatch,
+ SxSleepEntryCallBack,
+ EntryS1DispatchContext,
+ &(mAcpiSmm.S1SleepEntryHandle)
+ );
+
+ //
+ // Register entry phase call back function
+ //
+ EntryS3DispatchContext->Type = SxS3;
+ EntryS3DispatchContext->Phase = SxEntry;
+ Status = SxDispatch->Register (
+ SxDispatch,
+ SxSleepEntryCallBack,
+ EntryS3DispatchContext,
+ &(mAcpiSmm.S3SleepEntryHandle)
+ );
+
+ //
+ // Register entry phase call back function for S4
+ //
+ EntryS4DispatchContext->Type = SxS4;
+ EntryS4DispatchContext->Phase = SxEntry;
+ Status = SxDispatch->Register (
+ SxDispatch,
+ SxSleepEntryCallBack,
+ EntryS4DispatchContext,
+ &(mAcpiSmm.S4SleepEntryHandle)
+ );
+
+ //
+ // Register callback for S5 in order to workaround the LAN shutdown issue
+ //
+ EntryS5DispatchContext->Type = SxS5;
+ EntryS5DispatchContext->Phase = SxEntry;
+ Status = SxDispatch->Register (
+ SxDispatch,
+ SxSleepEntryCallBack,
+ EntryS5DispatchContext,
+ &(mAcpiSmm.S5SoftOffEntryHandle)
+ );
+
+ return Status;
+}
+
+
+EFI_STATUS
+RestoreQncS3SwCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+/*++
+
+Routine Description:
+ SMI handler to retore QncS3 code & context for S3 path
+ This will be only triggered when BootScript got executed during resume
+
+Arguments:
+ DispatchHandle - EFI Handle
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+ Nothing
+
+--*/
+{
+ //
+ // Restore to original address by default
+ //
+ RestoreLockBox(&gQncS3CodeInLockBoxGuid, NULL, NULL);
+ RestoreLockBox(&gQncS3ContextInLockBoxGuid, NULL, NULL);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DisableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+/*++
+
+Routine Description:
+ SMI handler to disable ACPI mode
+
+ Dispatched on reads from APM port with value 0xA1
+
+ ACPI events are disabled and ACPI event status is cleared.
+ SCI mode is then disabled.
+ Clear all ACPI event status and disable all ACPI events
+ Disable PM sources except power button
+ Clear status bits
+ Disable GPE0 sources
+ Clear status bits
+ Disable GPE1 sources
+ Clear status bits
+ Disable SCI
+
+Arguments:
+ DispatchHandle - EFI Handle
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+ Nothing
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 Pm1Cnt;
+
+ Status = GetAllQncPmBase (gSmst);
+ ASSERT_EFI_ERROR (Status);
+ Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);
+
+ //
+ // Disable SCI
+ //
+ Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SCIEN;
+
+ IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EnableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+/*++
+
+Routine Description:
+ SMI handler to enable ACPI mode
+
+ Dispatched on reads from APM port with value 0xA0
+
+ Disables the SW SMI Timer.
+ ACPI events are disabled and ACPI event status is cleared.
+ SCI mode is then enabled.
+
+ Disable SW SMI Timer
+
+ Clear all ACPI event status and disable all ACPI events
+ Disable PM sources except power button
+ Clear status bits
+
+ Disable GPE0 sources
+ Clear status bits
+
+ Disable GPE1 sources
+ Clear status bits
+
+ Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
+
+ Enable SCI
+
+Arguments:
+ DispatchHandle - EFI Handle
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+ Nothing
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 SmiEn;
+ UINT16 Pm1Cnt;
+ UINT8 Data8;
+
+ Status = GetAllQncPmBase (gSmst);
+ ASSERT_EFI_ERROR (Status);
+
+ SmiEn = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);
+
+ //
+ // Disable SW SMI Timer
+ //
+ SmiEn &= ~(B_QNC_GPE0BLK_SMIE_SWT);
+ IoWrite32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE, SmiEn);
+
+ //
+ // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
+ //
+ Data8 = RTC_ADDRESS_REGISTER_D;
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);
+ Data8 = 0x0;
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_DATA, Data8);
+
+ //
+ // Enable SCI
+ //
+ Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);
+ Pm1Cnt |= B_QNC_PM1BLK_PM1C_SCIEN;
+ IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);
+
+ //
+ // Do platform specific stuff for ACPI enable SMI
+ //
+
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SxSleepEntryCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+/*++
+
+Routine Description:
+
+ Callback function entry for Sx sleep state.
+
+Arguments:
+
+ DispatchHandle - The handle of this callback, obtained when registering.
+ DispatchContext - The predefined context which contained sleep type and phase.
+
+Returns:
+
+ EFI_SUCCESS - Operation successfully performed.
+ EFI_INVALID_PARAMETER - Invalid parameter passed in.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 Data8;
+ UINT16 Data16;
+ UINT32 Data32;
+
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeS3SuspendStart));
+
+ //
+ // Reget QNC power mgmr regs base in case of OS changing it at runtime
+ //
+ Status = GetAllQncPmBase (gSmst);
+
+ //
+ // Clear RTC Alarm (if set)
+ //
+ Data8 = RTC_ADDRESS_REGISTER_C;
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);
+ Data8 = IoRead8 (R_IOPORT_CMOS_STANDARD_DATA);
+
+ //
+ // Clear all ACPI status bits
+ //
+ Data32 = B_QNC_GPE0BLK_GPE0S_ALL;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0S, 1, &Data32 );
+ Data16 = B_QNC_PM1BLK_PM1S_ALL;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1S, 1, &Data16 );
+
+ //
+ // Handling S1 - setting appropriate wake bits in GPE0_EN
+ //
+ if ((DispatchHandle == mAcpiSmm.S1SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS1)) {
+ //
+ // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+ //
+ // Enable bit10 (RTC) in PM1E
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Handling S4, S5 and WOL - setting appropriate wake bits in GPE0_EN
+ //
+ if (((DispatchHandle == mAcpiSmm.S4SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS4)) ||
+ ((DispatchHandle == mAcpiSmm.S5SoftOffEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS5))
+ ) {
+ //
+ // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN
+ // Enable the WOL bits in GPE0_EN reg here for PME
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+ //
+ // Enable bit10 (RTC) in PM1E
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+
+ } else {
+
+ if ((DispatchHandle != mAcpiSmm.S3SleepEntryHandle) || (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type != SxS3)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = SaveRuntimeScriptTable (gSmst);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Enable bit13 (EGPE), 14 (GPIO), 17 (PCIE) in GPE0_EN
+ // Enable the WOL bits in GPE0_EN reg here for PME
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+ //
+ // Enable bit10 (RTC) in PM1E
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+ }
+
+ //
+ // When entering a power-managed state like S3,
+ // PERST# must be asserted in advance of power-off.
+ //
+ if (mPlatformType != GalileoFabE) {
+ PlatformPERSTAssert (mPlatformType);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetAllQncPmBase (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ )
+/*++
+
+Routine Description:
+
+ Get QNC chipset LPC Power Management I/O Base at runtime.
+
+Arguments:
+
+ Smst - The standard SMM system table.
+
+Returns:
+
+ EFI_SUCCESS - Successfully init the device.
+ Other - Error occured whening calling Dxe lib functions.
+
+--*/
+{
+ mAcpiSmm.QncPmBase = PciRead16 (PCI_LIB_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, R_QNC_LPC_PM1BLK)) & B_QNC_LPC_PM1BLK_MASK;
+ mAcpiSmm.QncGpe0Base = PciRead16 (PCI_LIB_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, R_QNC_LPC_GPE0BLK)) & B_QNC_LPC_GPE0BLK_MASK;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ )
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
+ UINT32 Data32;
+ UINT16 Data16;
+ UINT8 Mask;
+ UINTN Index;
+ UINTN Offset;
+ UINT16 DeviceId;
+
+ //
+ // Check what Soc we are running on (read Host bridge DeviceId)
+ //
+ DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
+
+ //
+ // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
+ // and vital to S3 resume. That's why we put save code here
+ //
+ Index = 0;
+ while (mPciCfgRegTable[Index] != PCI_DEVICE_END) {
+
+ PciAddress.Bus = mPciCfgRegTable[Index++];
+ PciAddress.Device = mPciCfgRegTable[Index++];
+ PciAddress.Function = mPciCfgRegTable[Index++];
+ PciAddress.Register = 0;
+ PciAddress.ExtendedRegister = 0;
+
+ Data16 = PciRead16 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
+ if (Data16 == 0xFFFF) {
+ Index += 8;
+ continue;
+ }
+
+ for (Offset = 0, Mask = 0x01; Offset < 256; Offset += 4, Mask <<= 1) {
+
+ if (Mask == 0x00) {
+ Mask = 0x01;
+ }
+
+ if (mPciCfgRegTable[Index + Offset / 32] & Mask) {
+
+ PciAddress.Register = (UINT8) Offset;
+ Data32 = PciRead32 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
+
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)),
+ 1,
+ &Data32
+ );
+ }
+ }
+
+ Index += 8;
+
+ }
+
+ //
+ // Save message bus registers
+ //
+ Index = 0;
+ while (QNCS3SaveExtReg[Index] != 0xFF) {
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ //
+ // Save IMR settings with IMR protection disabled initially
+ // HMBOUND and IMRs will be locked just before jumping to the OS waking vector
+ //
+ if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {
+ if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {
+ Data32 &= ~IMR_LOCK;
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {
+ Data32 &= ~IMR_EN;
+ }
+ }
+ if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {
+ Data32 = (UINT32)IMRX_ALL_ACCESS;
+ }
+ }
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+ 1,
+ &Data32
+ );
+
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+ 1,
+ &Data32
+ );
+ Index += 2;
+ }
+
+ Index = 0;
+ while (QNCS3SaveExtReg[Index] != 0xFF) {
+ //
+ // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable)
+ //
+ if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {
+ if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+ Data32 &= ~IMR_LOCK;
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+ 1,
+ &Data32
+ );
+
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+ 1,
+ &Data32
+ );
+ }
+ } else {
+ if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+ 1,
+ &Data32
+ );
+
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+ 1,
+ &Data32
+ );
+ }
+ }
+ }
+ Index += 2;
+ }
+
+ // Check if ECC scrub enabled and need re-enabling on resume
+ // All scrub related configuration registers are saved on suspend
+ // as part of QNCS3SaveExtReg configuration table script.
+ // The code below extends the S3 resume script with scrub reactivation
+ // message (if needed only)
+ Data32 = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG);
+ if( 0 != (Data32 & SCRUB_CFG_ACTIVE)) {
+
+ Data32 = SCRUB_RESUME_MSG();
+
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+ 1,
+ &Data32
+ );
+ }
+
+ //
+ // Save I/O ports to S3 script table
+ //
+
+ //
+ // Important to trap Sx for SMM
+ //
+ Data32 = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);
+ S3BootScriptSaveIoWrite(S3BootScriptWidthUint32, (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE), 1, &Data32);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h
new file mode 100755
index 0000000..36355e0
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h
@@ -0,0 +1,199 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ AcpiSmmPlatform.h
+
+Abstract:
+
+ Header file for SMM S3 Handler Driver.
+
+--*/
+
+#ifndef _ACPI_SMM_DRIVER_H
+#define _ACPI_SMM_DRIVER_H
+//
+// Include files
+//
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/FirmwareVolume.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PlatformType.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Protocol/Spi.h>
+#include <Library/SmmScriptLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/S3IoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Guid/Acpi.h>
+#include <Guid/GlobalVariable.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/HobLib.h>
+#include <QNCAccess.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformPcieHelperLib.h>
+#include "Platform.h"
+#include <IndustryStandard/Pci22.h>
+
+#define EFI_ACPI_ACPI_ENABLE 0xA0
+#define EFI_ACPI_ACPI_DISABLE 0xA1
+
+#define R_IOPORT_CMOS_STANDARD_INDEX 0x70
+#define R_IOPORT_CMOS_STANDARD_DATA 0x71
+#define RTC_ADDRESS_REGISTER_C 12
+#define RTC_ADDRESS_REGISTER_D 13
+
+#define PCI_DEVICE(Bus, Dev, Func) \
+ Bus, Dev, Func
+
+#define PCI_REG_MASK(Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7) \
+ Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7
+
+#define PCI_DEVICE_END 0xFF
+
+//
+// Related data structures definition
+//
+typedef struct _EFI_ACPI_SMM_DEV {
+
+ //
+ // Parent dispatch driver returned sleep handle
+ //
+ EFI_HANDLE S3SleepEntryHandle;
+
+ EFI_HANDLE S4SleepEntryHandle;
+
+ EFI_HANDLE S1SleepEntryHandle;
+
+ EFI_HANDLE S5SoftOffEntryHandle;
+
+ EFI_HANDLE EnableAcpiHandle;
+
+ EFI_HANDLE DisableAcpiHandle;
+
+ EFI_HANDLE PpCallbackHandle;
+
+ EFI_HANDLE MorCallbackHandle;
+
+ //
+ // QNC Power Management I/O register base
+ //
+ UINT32 QncPmBase;
+
+ //
+ // QNC General Purpose Event0 register base
+ //
+ UINT32 QncGpe0Base;
+
+ UINT32 BootScriptSaved;
+
+} EFI_ACPI_SMM_DEV;
+
+//
+// Prototypes
+//
+EFI_STATUS
+InitPlatformAcpiSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+EFI_STATUS
+SxSleepEntryCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+EFI_STATUS
+DisableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+EFI_STATUS
+EnableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+EFI_STATUS
+RegisterToDispatchDriver (
+ VOID
+ );
+
+EFI_STATUS
+GetAllQncPmBase (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ );
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ );
+
+EFI_STATUS
+RestoreQncS3SwCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+extern EFI_GUID gQncS3CodeInLockBoxGuid;
+extern EFI_GUID gQncS3ContextInLockBoxGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf
new file mode 100644
index 0000000..4d099cf
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf
@@ -0,0 +1,109 @@
+#/*++
+#
+# This is QNC Smm platform driver .
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Module Name:
+#
+# AcpiSmmPlatform.inf
+#
+# Abstract:
+#
+# Component description file for ACPI SMM Platform handler module
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiSmmPlatform
+ FILE_GUID = F5AC7057-5650-466e-B692-76A47223EFB0
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = InitAcpiSmmPlatform
+
+[Sources]
+ AcpiSmmPlatform.c
+ AcpiSmmPlatform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ ReportStatusCodeLib
+ UefiDriverEntryPoint
+ DebugLib
+ IoLib
+ PciLib
+ BaseMemoryLib
+ BaseLib
+ SmmServicesTableLib
+ PcdLib
+ HobLib
+ S3BootScriptLib
+ LockBoxLib
+ PlatformHelperLib
+ PlatformPcieHelperLib
+
+[Protocols]
+ gEfiSmmSxDispatch2ProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiVariableArchProtocolGuid
+ gEfiVariableWriteArchProtocolGuid
+ gEfiGlobalNvsAreaProtocolGuid
+ gEfiSmmSwDispatch2ProtocolGuid
+ gEfiPlatformTypeProtocolGuid
+
+[Guids]
+ gEfiAcpiVariableCompatiblityGuid
+ gEfiSetupVariableGuid
+ gEfiSmmPeiSmramMemoryReserveGuid
+ gQncS3CodeInLockBoxGuid
+ gQncS3ContextInLockBoxGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize
+
+[Depex]
+ gEfiSmmSxDispatch2ProtocolGuid AND
+ gEfiPciRootBridgeIoProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiGlobalNvsAreaProtocolGuid AND
+ gEfiQncS3SupportProtocolGuid
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c
new file mode 100644
index 0000000..071fbb0
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c
@@ -0,0 +1,408 @@
+/*++
+
+ Processor power management initialization code.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+--*/
+
+#include "SmmPowerManagement.h"
+
+//
+// Global variables
+//
+UINT32 mPpmFlags = 0; // Processor Power Management Flags
+CPU_CONFIG_CONTEXT_BUFFER *mCpuConfigConextBuffer;
+extern EFI_ACPI_SDT_PROTOCOL *mAcpiSdt;
+extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+
+extern EFI_GUID gPowerManagementAcpiTableStorageGuid;
+
+/**
+ This function is the entry of processor power management initialization code.
+ It initializes the processor's power management features based on the user
+ configurations and hardware capablities.
+**/
+VOID
+PpmInit (
+ VOID
+ )
+{
+ mGlobalNvsAreaPtr->Cfgd = mPpmFlags;
+
+ //
+ // Patch and publish power management related acpi tables
+ //
+ PpmPatchAndPublishAcpiTables();
+
+}
+
+/**
+ This function is to patch and publish power management related acpi tables.
+**/
+VOID
+PpmPatchAndPublishAcpiTables (
+ VOID
+ )
+{
+ //
+ // Patch FADT table to enable C2,C3
+ //
+ PpmPatchFadtTable();
+
+ //
+ // Load all the power management acpi tables and patch IST table
+ //
+ PpmLoadAndPatchPMTables();
+}
+
+/**
+ This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.
+**/
+VOID
+PpmPatchFadtTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_ACPI_SDT_HEADER *CurrentTable;
+ EFI_ACPI_TABLE_VERSION Version;
+ UINTN Index;
+ UINTN Handle;
+ EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtPointer;
+
+ //
+ // Scan all the acpi tables to find FADT 2.0
+ //
+ Index = 0;
+ do {
+ Status = mAcpiSdt->GetAcpiTable (
+ Index,
+ &CurrentTable,
+ &Version,
+ &Handle
+ );
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while (CurrentTable->Signature != EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE || CurrentTable->Revision != 0x03);
+
+ ASSERT (CurrentTable->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);
+
+ Table = NULL;
+ Status = gBS->AllocatePool (EfiBootServicesData, CurrentTable->Length, (VOID **) &Table);
+ ASSERT (Table != NULL);
+ CopyMem (Table, CurrentTable, CurrentTable->Length);
+
+ FadtPointer = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE*) Table;
+
+ //
+ // Update the ACPI table and recalculate checksum
+ //
+ Status = mAcpiTable->UninstallAcpiTable (mAcpiTable, Handle);
+ if (EFI_ERROR (Status)) {
+ //
+ // Should not get an error here ever, but abort if we do.
+ //
+ return ;
+ }
+
+ //
+ // Update the check sum
+ // It needs to be zeroed before the checksum calculation
+ //
+ ((EFI_ACPI_SDT_HEADER *)Table)->Checksum = 0;
+ ((EFI_ACPI_SDT_HEADER *)Table)->Checksum =
+ CalculateCheckSum8 ((VOID *)Table, Table->Length);
+
+ //
+ // Add the table
+ //
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ Table,
+ Table->Length,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ gBS->FreePool (Table);
+}
+
+VOID
+SsdtTableUpdate (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader
+ )
+/*++
+
+ Routine Description:
+
+ Update the SSDT table
+
+ Arguments:
+
+ Table - The SSDT table to be patched
+
+ Returns:
+
+ None
+
+--*/
+{
+ UINT8 *CurrPtr;
+ UINT8 *SsdtPointer;
+ UINT32 *Signature;
+
+ //
+ // Loop through the ASL looking for values that we must fix up.
+ //
+ CurrPtr = (UINT8 *) TableHeader;
+ for (SsdtPointer = CurrPtr;
+ SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+ SsdtPointer++
+ )
+ {
+ Signature = (UINT32 *) SsdtPointer;
+ if ((*Signature) == SIGNATURE_32 ('P', 'M', 'B', 'A')) {
+ switch (*(Signature+1)) {
+ case (SIGNATURE_32 ('L', 'V', 'L', '0')):
+ Signature[0] = PcdGet16(PcdPmbaIoBaseAddress);
+ Signature[1] = 0;
+ break;
+ case (SIGNATURE_32 ('L', 'V', 'L', '2')):
+ Signature[0] = PcdGet16(PcdPmbaIoLVL2);
+ Signature[1] = 0;
+ break;
+ }
+ }
+ }
+}
+
+EFI_STATUS
+LocateSupportProtocol (
+ IN EFI_GUID *Protocol,
+ OUT VOID **Instance,
+ IN UINT32 Type
+ )
+/*++
+
+Routine Description:
+
+ Locate the first instance of a protocol. If the protocol requested is an
+ FV protocol, then it will return the first FV that contains the ACPI table
+ storage file.
+
+Arguments:
+
+ Protocol The protocol to find.
+ Instance Return pointer to the first instance of the protocol
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_NOT_FOUND The protocol could not be located.
+ EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+
+ FvStatus = 0;
+
+ //
+ // Locate protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Protocol,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+
+ //
+ // Defined errors at this time are not found and out of resources.
+ //
+ return Status;
+ }
+
+
+
+ //
+ // Looking for FV with ACPI storage file
+ //
+
+ for (i = 0; i < NumberOfHandles; i++) {
+ //
+ // Get the protocol on this handle
+ // This should not fail because of LocateHandleBuffer
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ Protocol,
+ Instance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!Type) {
+ //
+ // Not looking for the FV protocol, so find the first instance of the
+ // protocol. There should not be any errors because our handle buffer
+ // should always contain at least one or LocateHandleBuffer would have
+ // returned not found.
+ //
+ break;
+ }
+
+ //
+ // See if it has the ACPI storage file
+ //
+
+ Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,
+ &gPowerManagementAcpiTableStorageGuid,
+ 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
+ //
+ gBS->FreePool (HandleBuffer);
+
+ return Status;
+}
+
+/**
+ This function is to load all the power management acpi tables and patch IST table.
+**/
+VOID
+PpmLoadAndPatchPMTables (
+ VOID
+ )
+{
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ EFI_STATUS Status;
+ INTN Instance;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN TableHandle;
+ UINT32 FvStatus;
+ UINTN Size;
+ EFI_ACPI_TABLE_VERSION Version;
+
+ Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Read tables from the storage file.
+ //
+ Instance = 0;
+ CurrentTable = NULL;
+
+ while (Status == EFI_SUCCESS) {
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gPowerManagementAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID**)&CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR(Status)) {
+ Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+
+ if(((EFI_ACPI_DESCRIPTION_HEADER*) CurrentTable)->OemTableId == SIGNATURE_64 ('C', 'p', 'u', '0', 'I', 's', 't', 0)) {
+ Version = EFI_ACPI_TABLE_VERSION_NONE;
+ } else if(((EFI_ACPI_DESCRIPTION_HEADER*) CurrentTable)->OemTableId == SIGNATURE_64 ('C', 'p', 'u', '1', 'I', 's', 't', 0)) {
+ Version = EFI_ACPI_TABLE_VERSION_NONE;
+ }
+
+ SsdtTableUpdate ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable);
+
+ //
+ // Update the check sum
+ // It needs to be zeroed before the checksum calculation
+ //
+ ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
+ ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = (UINT8)
+ CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
+
+ //
+ // Add the table
+ //
+ TableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ CurrentTable,
+ CurrentTable->Length,
+ &TableHandle
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Increment the instance
+ //
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h
new file mode 100644
index 0000000..9b7444e
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h
@@ -0,0 +1,174 @@
+/*++
+
+ Processor power management initialization code.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+--*/
+
+#ifndef _PPM_H
+#define _PPM_H
+
+//
+// Bit definitions of PPMFlags
+//
+#define PPM_GV3 (1 << 0) // Geyserville 3
+#define PPM_TURBO (1 << 1) // Turbo Mode
+#define PPM_SUPER_LFM (1 << 2) // N/2 Ratio
+#define PPM_C1 (1 << 4) // C1 Capable, Enabled
+#define PPM_C2 (1 << 5) // C2 Capable, Enabled
+#define PPM_C3 (1 << 6) // C3 Capable, Enabled
+#define PPM_C4 (1 << 7) // C4 Capable, Enabled
+#define PPM_C5 (1 << 8) // C5/Deep C4 Capable, Enabled
+#define PPM_C6 (1 << 9) // C6 Capable, Enabled
+#define PPM_C1E (1 << 10) // C1E Enabled
+#define PPM_C2E (1 << 11) // C2E Enabled
+#define PPM_C3E (1 << 12) // C3E Enabled
+#define PPM_C4E (1 << 13) // C4E Enabled
+#define PPM_HARD_C4E (1 << 14) // Hard C4E Capable, Enabled
+#define PPM_TM1 (1 << 16) // Thermal Monitor 1
+#define PPM_TM2 (1 << 17) // Thermal Monitor 2
+#define PPM_PHOT (1 << 19) // Bi-directional ProcHot
+#define PPM_MWAIT_EXT (1 << 21) // MWAIT extensions supported
+#define PPM_CMP (1 << 24) // CMP supported, Enabled
+#define PPM_TSTATE (1 << 28) // CPU T states supported
+
+#define PPM_C_STATES (PPM_C1 + PPM_C2 + PPM_C3 + PPM_C4 + PPM_C5 + PPM_C6)
+#define PPM_CE_STATES (PPM_C1E + PPM_C2E + PPM_C3E + PPM_C4E + PPM_HARD_C4E)
+
+
+#define MAX_P_STATES_NUM 12
+
+#define AML_NAME_OP 0x08
+#define AML_SCOPE_OP 0x10
+#define AML_PACKAGE_OP 0x12
+#define AML_METHOD_OP 0x14
+
+#define S3_CPU_REGISTER_TABLE_GUID \
+ { \
+ 0xc4ef988d, 0xe5e, 0x4403, { 0xbe, 0xeb, 0xf1, 0xbb, 0x6, 0x79, 0x6e, 0xdf } \
+ }
+
+#pragma pack(1)
+typedef struct {
+ UINT8 StartByte;
+ UINT32 NameStr;
+ UINT8 OpCode;
+ UINT16 Size; // Hardcode to 16bit width because the table we use is fixed size
+ UINT8 NumEntries;
+} EFI_ACPI_NAME_COMMAND;
+
+typedef struct {
+ UINT8 PackageOp;
+ UINT8 PkgLeadByte;
+ UINT8 NumEntries;
+ UINT8 DwordPrefix0;
+ UINT32 CoreFreq;
+ UINT8 DwordPrefix1;
+ UINT32 Power;
+ UINT8 DwordPrefix2;
+ UINT32 TransLatency;
+ UINT8 DwordPrefix3;
+ UINT32 BMLatency;
+ UINT8 DwordPrefix4;
+ UINT32 Control;
+ UINT8 DwordPrefix5;
+ UINT32 Status;
+} EFI_PSS_PACKAGE;
+#pragma pack()
+
+typedef struct {
+ UINT32 Index;
+ UINT64 Value;
+} S3_CPU_REGISTER;
+
+//
+// Function prototypes
+//
+
+/**
+ This function is the entry of processor power management initialization code.
+ It initializes the processor's power management features based on the user
+ configurations and hardware capablities.
+**/
+VOID
+PpmInit (
+ VOID
+ );
+
+/**
+ This function is to determine the Processor Power Management Flags
+ based on the hardware capability.
+**/
+VOID
+PpmDetectCapability (
+ VOID
+ );
+
+/**
+ This function is to determine the user configuration mask
+**/
+VOID
+PpmGetUserConfigurationMask (
+ VOID
+ );
+
+/**
+ This function is to patch and publish power management related acpi tables.
+**/
+VOID
+PpmPatchAndPublishAcpiTables (
+ VOID
+ );
+
+/**
+ This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.
+**/
+VOID
+PpmPatchFadtTable (
+ VOID
+ );
+
+/**
+ This function is to load all the power management acpi tables and patch IST table.
+**/
+VOID
+PpmLoadAndPatchPMTables (
+ VOID
+ );
+
+/**
+ This function is to save cpu registers for s3 resume.
+**/
+VOID
+PpmS3SaveRegisters (
+ VOID
+ );
+#endif
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c
new file mode 100644
index 0000000..6a77d1d
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c
@@ -0,0 +1,137 @@
+/*++
+
+ This is QNC Smm Power Management driver
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+--*/
+
+#include "SmmPowerManagement.h"
+
+//
+// Global variables
+//
+EFI_SMM_CPU_PROTOCOL *mSmmCpu = NULL;
+EFI_GLOBAL_NVS_AREA *mGlobalNvsAreaPtr = NULL;
+EFI_MP_SERVICES_PROTOCOL *mMpService = NULL;
+EFI_ACPI_SDT_PROTOCOL *mAcpiSdt = NULL;
+EFI_ACPI_TABLE_PROTOCOL *mAcpiTable = NULL;
+
+EFI_GUID mS3CpuRegisterTableGuid = S3_CPU_REGISTER_TABLE_GUID;
+
+EFI_STATUS
+EFIAPI
+InitializePowerManagement (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initializes the SMM Handler Driver
+
+Arguments:
+
+ ImageHandle -
+
+ SystemTable -
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsAreaProtocol;
+
+ //
+ // Get SMM CPU protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmCpuProtocolGuid,
+ NULL,
+ (VOID **)&mSmmCpu
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get the Sw dispatch protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ (VOID**)&SwDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Global NVS Area Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiGlobalNvsAreaProtocolGuid, NULL, (VOID **)&GlobalNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mGlobalNvsAreaPtr = GlobalNvsAreaProtocol->Area;
+
+ //
+ // Locate and cache PI AcpiSdt Protocol.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiSdtProtocolGuid,
+ NULL,
+ (VOID **) &mAcpiSdt
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Locate and cache PI AcpiSdt Protocol.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID **) &mAcpiTable
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Get MpService protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&mMpService);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Initialize power management features on processors
+ //
+ PpmInit();
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h
new file mode 100644
index 0000000..ae5bf16
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h
@@ -0,0 +1,90 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmmPowerManagement.h
+
+Abstract:
+
+ Header file for QNC Smm Power Management driver
+
+Revision History
+
+++*/
+
+#ifndef _SMM_POWER_MANAGEMENT_H_
+#define _SMM_POWER_MANAGEMENT_H_
+
+#include <PiSmm.h>
+#include <AcpiCpuData.h>
+#include <QuarkPlatformDxe.h>
+#include <IntelQNCDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/SmmCpu.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/AcpiSupport.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/MpService.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/SocketLga775Lib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CpuConfigLib.h>
+
+#include <IndustryStandard/Acpi.h>
+
+
+#include "Ppm.h"
+
+//
+// Module global variable
+//
+extern EFI_SMM_CPU_PROTOCOL *mSmmCpu;
+extern EFI_GLOBAL_NVS_AREA *mGlobalNvsAreaPtr;
+extern EFI_ACPI_SUPPORT_PROTOCOL *mAcpiSupport;
+extern EFI_MP_SERVICES_PROTOCOL *mMpService;
+
+//
+// Function prototypes
+//
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf
new file mode 100644
index 0000000..9e37483
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf
@@ -0,0 +1,104 @@
+## @file
+# Component description file for SMM Power Management module
+#
+# This is QNC Smm Power Management driver .
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmPowerManagement
+ FILE_GUID = 271F1343-20D6-4e14-9B62-3C0297F56F07
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = InitializePowerManagement
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ SmmPowerManagement.c
+ SmmPowerManagement.h
+ Ppm.c
+ Ppm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ PcdLib
+ IoLib
+ PciLib
+ BaseLib
+ BaseMemoryLib
+ SmmServicesTableLib
+ UefiBootServicesTableLib
+ S3BootScriptLib
+ MemoryAllocationLib
+
+[Protocols]
+ gEfiSmmCpuProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSmmSwDispatch2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiGlobalNvsAreaProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Guids]
+ gPowerManagementAcpiTableStorageGuid
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoLVL2
+
+[Pcd]
+ gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer
+ gEfiCpuTokenSpaceGuid.PcdCpuMaxCpuIDValueLimitFlag
+ gEfiCpuTokenSpaceGuid.PcdCpuS3DataAddress
+
+[Depex]
+ gEfiSmmCpuProtocolGuid AND
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiGlobalNvsAreaProtocolGuid AND
+ gEfiAcpiTableProtocolGuid AND
+ gEfiMpServiceProtocolGuid
diff --git a/QuarkPlatformPkg/Applications/CapsuleApp.efi b/QuarkPlatformPkg/Applications/CapsuleApp.efi
new file mode 100755
index 0000000..5e0904b
--- /dev/null
+++ b/QuarkPlatformPkg/Applications/CapsuleApp.efi
Binary files differ
diff --git a/QuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.c b/QuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.c
new file mode 100755
index 0000000..7d04504
--- /dev/null
+++ b/QuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.c
@@ -0,0 +1,489 @@
+/** @file
+ Application to test the UEFI capsule runtime service functionality.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/ShellLib.h>
+#include <Protocol/FirmwareVolumeBlockSecurity.h>
+
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 3
+
+//
+// Define how many block descriptors we want to test with.
+//
+UINTN NumberOfDescriptors = 1;
+
+STATIC CONST SHELL_PARAM_ITEM CapsuleParamList[] = {
+ {L"-?", TypeFlag},
+ {L"-h", TypeFlag},
+ {L"-H", TypeFlag},
+ {L"-v", TypeFlag},
+ {L"-V", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Display current version.
+**/
+VOID
+ShowVersion (
+ )
+{
+ ShellPrintEx (-1, -1, L"CapsuleApp Version %d.%02d\n", MAJOR_VERSION, MINOR_VERSION);
+}
+
+/**
+ Display Usage and Help information.
+**/
+VOID
+ShowHelp (
+ )
+{
+ ShellPrintEx (-1, -1, L"CapsuleApp: usage\n CapsuleApp [capsule filename]\n");
+}
+
+/**
+ Update Capsule image.
+
+ @param[in] ImageHandle The image handle.
+ @param[in] SystemTable The system table.
+
+ @retval EFI_SUCCESS Command completed successfully.
+ @retval EFI_INVALID_PARAMETER Command usage error.
+ @retval EFI_NOT_FOUND The input file can't be found.
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *ParamPackage;
+ CHAR16 *ParamProblem;
+ EFI_SHELL_FILE_INFO *ListHead;
+ EFI_SHELL_FILE_INFO *Node;
+ SHELL_FILE_HANDLE SourceHandle;
+ UINTN SignedFileSize;
+ UINTN FileSize;
+ UINT8 *SignedCapsuleBuffer;
+ UINT8 *CapsuleBuffer;
+ CHAR16 *CapsuleFileName;
+ CHAR16 *InputFileName;
+
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors1;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors2;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
+ UINT8 *TempDataPtr;
+ UINTN SizeLeft;
+ UINTN Size;
+ INT32 Count;
+ INT32 Number;
+ EFI_CAPSULE_HEADER *CapsuleHeaderArray[2];
+ UINT64 MaxCapsuleSize;
+ EFI_RESET_TYPE ResetType;
+ EFI_FILE_INFO *FileInfo;
+ FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL *FvbSecurityProtocol;
+
+ ListHead = NULL;
+ ParamProblem = NULL;
+ SignedCapsuleBuffer = NULL;
+ CapsuleBuffer = NULL;
+ CapsuleFileName = NULL;
+ BlockDescriptors1 = NULL;
+ BlockDescriptors2 = NULL;
+ SignedFileSize = 0;
+ FileSize = 0;
+ FileInfo = NULL;
+ SourceHandle = NULL;
+ ParamPackage = NULL;
+
+ //
+ // Locate Fvb Security Protocol for Capsule File Verification.
+ //
+ Status = gBS->LocateProtocol(
+ &gFirmwareVolumeBlockSecurityGuid,
+ NULL,
+ (VOID**) &FvbSecurityProtocol
+ );
+ if (EFI_ERROR(Status)) {
+ FvbSecurityProtocol = NULL;
+ } else {
+ ASSERT (FvbSecurityProtocol != NULL);
+ ASSERT (FvbSecurityProtocol->SecurityAuthenticateImage != NULL);
+ }
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (CapsuleParamList, &ParamPackage, &ParamProblem, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (ParamProblem != NULL) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: %EError. %NThe argument '%B%s%N' is invalid.\n", ParamProblem);
+ FreePool(ParamProblem);
+ } else {
+ ShellPrintEx(-1, -1, L"CapsuleApp: %EError. %NThe input parameters are not recognized.\n");
+ }
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // check for "-?" help information, and for "-v" for version inforamtion.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-?") ||
+ ShellCommandLineGetFlag (ParamPackage, L"-h") ||
+ ShellCommandLineGetFlag (ParamPackage, L"-H")) {
+ ShowHelp();
+ goto Done;
+ } else if (ShellCommandLineGetFlag (ParamPackage, L"-v") ||
+ ShellCommandLineGetFlag (ParamPackage, L"-V")) {
+ ShowVersion();
+ goto Done;
+ } else {
+ //
+ // Only support single parameter as the input file name.
+ //
+ InputFileName = (CHAR16 *) ShellCommandLineGetRawValue(ParamPackage, 1);
+ if (InputFileName == NULL) {
+ //
+ // we can't get any for file name
+ //
+ ShellPrintEx(-1, -1, L"CapsuleApp: %EError. %NToo few arguments specified.\n");
+ Status = EFI_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(ParamPackage, 2) != NULL) {
+ //
+ // we get more than one input parameters for file name
+ //
+ ShellPrintEx(-1, -1, L"CapsuleApp: %EError. %NToo many arguments specified.\n");
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // Read the input file. If more than one is found, the first one will be used.
+ //
+ Status = ShellOpenFileMetaArg(InputFileName, EFI_FILE_MODE_READ, &ListHead);
+ if (!EFI_ERROR(Status)) {
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
+ ; !IsNull(&ListHead->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
+ ) {
+
+ if (ShellIsFile(Node->FullName) != EFI_SUCCESS) {
+ continue;
+ }
+
+ //
+ // open source file
+ //
+ Status = ShellOpenFileByName(Node->FullName, &SourceHandle, EFI_FILE_MODE_READ, 0);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // get file size
+ //
+ FileInfo = ShellGetFileInfo (SourceHandle);
+ SignedFileSize = (UINTN) FileInfo->FileSize;
+ FreePool (FileInfo);
+
+ //
+ // read data from file
+ //
+ SignedCapsuleBuffer = AllocateZeroPool(SignedFileSize);
+ Status = ShellReadFile (SourceHandle, &SignedFileSize, SignedCapsuleBuffer);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get Capsule file name
+ //
+ CapsuleFileName = AllocateZeroPool (StrSize (Node->FullName));
+ ASSERT (CapsuleFileName != NULL);
+ StrCpy (CapsuleFileName, Node->FullName);
+ } else {
+ FreePool (SignedCapsuleBuffer);
+ SignedCapsuleBuffer = NULL;
+ }
+
+ //
+ // close source file.
+ //
+ if (SourceHandle != NULL) {
+ ShellCloseFile(&SourceHandle); // map to ShellOpenFileByName()
+ SourceHandle = NULL;
+ }
+
+ //
+ // Capsule image is got. First capsule file is used.
+ //
+ if (SignedCapsuleBuffer != NULL && SignedFileSize != 0) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+
+ //
+ // Free ListHead
+ // map to ShellOpenFileMetaArg
+ //
+ ShellCloseFileMetaArg(&ListHead);
+ } else {
+ //
+ // no files are found.
+ //
+ ShellPrintEx(-1, -1, L"CapsuleApp: File '%B%s%N' was not found.\n", InputFileName);
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ // map to ShellCommandLineParse
+ //
+ ShellCommandLineFreeVarList (ParamPackage);
+ ParamPackage = NULL;
+ }
+
+ //
+ // Additional check for the input parameter.
+ //
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ if (SignedCapsuleBuffer == NULL || SignedFileSize == 0) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: no capsule image is found.\n");
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Allocate memory for the descriptors.
+ //
+ if (NumberOfDescriptors == 1) {
+ Count = 2;
+ } else {
+ Count = (INT32)(NumberOfDescriptors + 2) / 2;
+ }
+
+ Size = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
+ BlockDescriptors1 = AllocateRuntimeZeroPool (Size);
+ ASSERT (BlockDescriptors1 != NULL);
+ if (EFI_ERROR (Status)) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: failed to allocate memory for descriptors\n");
+ goto Done;
+ } else {
+ CapsuleBuffer = SignedCapsuleBuffer + FixedPcdGet32 (PcdFvSecurityHeaderSize);
+ if (FvbSecurityProtocol != NULL) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: SecurityAuthenticateImage 0x%X\n", (UINTN) CapsuleBuffer);
+ Status = FvbSecurityProtocol->SecurityAuthenticateImage ((VOID *) CapsuleBuffer);
+ if (EFI_ERROR(Status)) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: Rom SecurityAuthenticateImage failed\n");
+ goto Done;
+ }
+ } else {
+ ShellPrintEx(-1, -1, L"CapsuleApp: No Authenticate Image Service found on this platform\n");
+ }
+ FileSize = SignedFileSize - FixedPcdGet32 (PcdFvSecurityHeaderSize);
+ ShellPrintEx(-1, -1, L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN) BlockDescriptors1);
+ ShellPrintEx(-1, -1, L"CapsuleApp: capsule data starts at 0x%X with size 0x%X\n", (UINTN) CapsuleBuffer, FileSize);
+ }
+
+ //
+ // Fill them in
+ //
+ TempBlockPtr = BlockDescriptors1;
+ TempDataPtr = CapsuleBuffer;
+ SizeLeft = FileSize;
+ for (Number = 0; Number < Count - 1; Number++) {
+ //
+ // Divide remaining data in half
+ //
+ if (NumberOfDescriptors != 1) {
+ if (SizeLeft == 1) {
+ Size = 1;
+ } else {
+ Size = SizeLeft / 2;
+ }
+ } else {
+ Size = SizeLeft;
+ }
+ TempBlockPtr->Union.DataBlock = (UINTN)TempDataPtr;
+ TempBlockPtr->Length = Size;
+ ShellPrintEx(-1, -1, L"CapsuleApp: capsule block/size 0x%X/0x%X\n", (UINTN) TempDataPtr, Size);
+ SizeLeft -= Size;
+ TempDataPtr += Size;
+ TempBlockPtr++;
+ }
+ //
+ // Allocate the second list, point the first block's last entry to point
+ // to this one, and fill this one in. Worst case is that the previous
+ // list only had one element that pointed here, so we need at least two
+ // elements -- one to point to all the data, another to terminate the list.
+ //
+ if (NumberOfDescriptors != 1) {
+ Count = (INT32)(NumberOfDescriptors + 2) - Count;
+ if (Count == 1) {
+ Count++;
+ }
+
+ Size = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
+ BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
+ ASSERT (BlockDescriptors2 != NULL);
+ if (EFI_ERROR (Status)) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: failed to allocate memory for descriptors\n");
+ return Status;
+ }
+ //
+ // Point the first list's last element to point to this second list.
+ //
+ TempBlockPtr->Union.ContinuationPointer = (UINTN) BlockDescriptors2;
+
+ TempBlockPtr->Length = 0;
+ TempBlockPtr = BlockDescriptors2;
+ for (Number = 0; Number < Count - 1; Number++) {
+ //
+ // If second-to-last one, then dump rest to this element
+ //
+ if (Number == (Count - 2)) {
+ Size = SizeLeft;
+ } else {
+ //
+ // Divide remaining data in half
+ //
+ if (SizeLeft == 1) {
+ Size = 1;
+ } else {
+ Size = SizeLeft / 2;
+ }
+ }
+
+ TempBlockPtr->Union.DataBlock = (UINTN)TempDataPtr;
+ TempBlockPtr->Length = Size;
+ ShellPrintEx(-1, -1, L"CapsuleApp: capsule block/size 0x%X/0x%X\n", (UINTN) TempDataPtr, Size);
+ SizeLeft -= Size;
+ TempDataPtr += Size;
+ TempBlockPtr++;
+ }
+ }
+ //
+ // Null-terminate.
+ //
+ TempBlockPtr->Union.ContinuationPointer = (UINTN)NULL;
+ TempBlockPtr->Length = 0;
+
+ //
+ // Call the runtime service capsule.
+ //
+ CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) CapsuleBuffer;
+ CapsuleHeaderArray[1] = NULL;
+
+ //
+ // Inquire platform capability of UpdateCapsule.
+ //
+ Status = gRT->QueryCapsuleCapabilities(CapsuleHeaderArray,1,&MaxCapsuleSize,&ResetType);
+ if (Status == EFI_UNSUPPORTED) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: %s file is not recognized.\n", CapsuleFileName);
+ goto Done;
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: failed to query capsule capability\n");
+ goto Done;
+ }
+ if (SignedFileSize > MaxCapsuleSize) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: capsule is too large to update\n");
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ //
+ // Check whether the input capsule image has the flag of persist across system reset.
+ //
+ if ((CapsuleHeaderArray[0]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
+ Status = gRT->UpdateCapsule(CapsuleHeaderArray,1,(UINTN) BlockDescriptors1);
+ if (Status != EFI_SUCCESS) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: failed to update capsule\n");
+ goto Done;
+ }
+ //
+ // For capsule who has reset flag, after calling UpdateCapsule service,triger a
+ // system reset to process capsule persist across a system reset.
+ //
+ gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
+ } else {
+ //
+ // For capsule who has no reset flag, only call UpdateCapsule Service without a
+ // system reset. The service will process the capsule immediately.
+ //
+ Status = gRT->UpdateCapsule(CapsuleHeaderArray,1,(UINTN) BlockDescriptors1);
+ if (Status != EFI_SUCCESS) {
+ ShellPrintEx(-1, -1, L"CapsuleApp: failed to update capsule\n");
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+ //
+ // Clean up
+ //
+ if (ParamPackage != NULL) {
+ ShellCommandLineFreeVarList (ParamPackage);
+ }
+
+ if (SignedCapsuleBuffer != NULL) {
+ FreePool (SignedCapsuleBuffer);
+ }
+
+ if (BlockDescriptors1 != NULL) {
+ FreePool (BlockDescriptors1);
+ }
+
+ if (BlockDescriptors2 != NULL) {
+ FreePool (BlockDescriptors2);
+ }
+
+ if (CapsuleFileName != NULL) {
+ FreePool (CapsuleFileName);
+ }
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.inf b/QuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.inf
new file mode 100755
index 0000000..d6d64d0
--- /dev/null
+++ b/QuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.inf
@@ -0,0 +1,71 @@
+## @file
+# CapsuleApp is used to run capsule service in Shell.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = CapsuleApp
+ FILE_GUID = E61DD373-4B13-45ec-9EF4-7DB88688F612
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CapsuleApp.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiApplicationEntryPoint
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ ShellLib
+ PcdLib
+
+[Protocols]
+ gFirmwareVolumeBlockSecurityGuid ## CONSUMES
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+
diff --git a/QuarkPlatformPkg/Bds/BdsDxe/Bds.h b/QuarkPlatformPkg/Bds/BdsDxe/Bds.h
new file mode 100644
index 0000000..1f3adb5
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BdsDxe/Bds.h
@@ -0,0 +1,88 @@
+/** @file
+ Head file for BDS Architectural Protocol implementation
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+#ifndef _BDS_MODULE_H_
+#define _BDS_MODULE_H_
+
+#include <Uefi.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/ConnectConInEvent.h>
+
+#include <Protocol/Bds.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/LoadedImage.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <Library/UefiBootManagerLib.h>
+#include <Library/PlatformBootManagerLib.h>
+
+//
+// Prototypes
+//
+
+/**
+
+ Service routine for BdsInstance->Entry(). Devices are connected, the
+ consoles are initialized, and the boot options are tried.
+
+ @param This Protocol Instance structure.
+
+**/
+VOID
+EFIAPI
+BdsEntry (
+ IN EFI_BDS_ARCH_PROTOCOL *This
+ );
+
+typedef
+VOID
+(* BDS_PROCESS_VARIABLE) (
+ VOID **Variable,
+ UINTN *VariableSize
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Bds/BdsDxe/BdsDxe.inf b/QuarkPlatformPkg/Bds/BdsDxe/BdsDxe.inf
new file mode 100644
index 0000000..130fc23
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BdsDxe/BdsDxe.inf
@@ -0,0 +1,144 @@
+## @file
+#
+# BDSDxe module is core driver for BDS phase.
+# When DxeCore dispatching all DXE driver, this module will produce architecture protocol
+# gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry
+# interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered.
+#
+# Generally, this module take reposiblity to connect all necessary devices for platform boot,
+# these boot device path are hold in PlatformBdsLib library instance produced by platform.
+# For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is select.
+# For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI,
+# EFI\BOOT\BOOTIA64.EFI file from selected boot device and transfer control to boot loader.
+#
+# BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, Device Manager" which
+# is used for user to configure boot option or maintain hardware device.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BdsDxe
+ FILE_GUID = 6D33944A-EC75-4855-A54D-809C75241F6C
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = BdsInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ Language.h
+ Bds.h
+ HwErrRecSupport.c
+ HwErrRecSupport.h
+ Language.c
+ BdsEntry.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ DevicePathLib
+ BaseLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ ReportStatusCodeLib
+ UefiLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ UefiBootManagerLib
+ PlatformBootManagerLib
+ PcdLib
+
+[Guids]
+ gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"BootNext" (The number of next boot option)
+ ## SOMETIMES_PRODUCES ## Variable:L"BootXX" (Boot option variable)
+ ## SOMETIMES_PRODUCES ## Variable:L"PlatformLang" (Platform supported languange in Rfc4646 format)
+ ## SOMETIMES_PRODUCES ## Variable:L"Lang" (Platform supported languange in Iso639 format)
+ ## SOMETIMES_PRODUCES ## Variable:L"KeyXX" (Hotkey option variable)
+ ## PRODUCES ## Variable:L"HwErrRecSupport" (The level of platform supported hardware Error Record Persistence)
+ ## SOMETIMES_PRODUCES ## Variable:L"BootOptionSupport" (The feature supported in boot option menu, value could be: EFI_BOOT_OPTION_SUPPORT_KEY, EFI_BOOT_OPTION_SUPPORT_APP
+ ## SOMETIMES_PRODUCES (not PcdUefiVariableDefaultLangDeprecate)## Variable:L"LangCodes" (Value of PcdUefiVariableDefaultLangCodes)
+ ## PRODUCES ## Variable:L"PlatformLangCodes" (Value of PcdUefiVariableDefaultPlatformLangCodes)
+ ## PRODUCES ## Variable:L"Timeout" (The time out value in second of showing progress bar)
+ ## SOMETIMES_PRODUCES ## Variable:L"BootOrder" (The boot option array)
+ ## SOMETIMES_PRODUCES ## Variable:L"DriverOrder" (The driver order list)
+ ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)
+ ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)
+ ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)
+ gConnectConInEventGuid ## SOMETIMES_CONSUMES
+
+[Protocols]
+ gEfiBdsArchProtocolGuid ## PROTOCOL PRODUCES
+ gEfiSimpleTextInputExProtocolGuid ## PROTOCOL CONSUMES
+
+[FeaturePcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate
+ gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand
+
+###Corresponding variable defined in UEFI spec, why not put them in MdePkg
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+
+[Depex]
+ TRUE
+
+#
+# [BootMode]
+# BOOT_ON_FLASH_UPDATE ## SOMETIMES_CONSUMES (Update Capsule Image)
+#
+#
+# [Hob]
+# HOB ## SOMETIMES_CONSUMES ## GUID EXTENSION Capsule Data Hob
+#
+#
diff --git a/QuarkPlatformPkg/Bds/BdsDxe/BdsEntry.c b/QuarkPlatformPkg/Bds/BdsDxe/BdsEntry.c
new file mode 100644
index 0000000..0781343
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BdsDxe/BdsEntry.c
@@ -0,0 +1,1003 @@
+/** @file
+ This module produce main entry for BDS phase - BdsEntry.
+ When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed
+ which contains interface of BdsEntry.
+ After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked
+ to enter BDS phase.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+#include "Bds.h"
+#include "Language.h"
+#include "HwErrRecSupport.h"
+
+#define SET_BOOT_OPTION_SUPPORT_KEY_COUNT(a, c) { \
+ (a) = ((a) & ~EFI_BOOT_OPTION_SUPPORT_COUNT) | (((c) << LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT)) & EFI_BOOT_OPTION_SUPPORT_COUNT); \
+ }
+
+//TODO: BdsDxe driver produces BDS ARCH protocol but also BDS UTILITY protocol to replace UefiBootManagerLib.
+///
+/// BDS arch protocol instance initial value.
+///
+EFI_BDS_ARCH_PROTOCOL gBds = {
+ BdsEntry
+};
+
+//
+// gConnectConInEvent - Event which is signaled when ConIn connection is required
+//
+EFI_EVENT gConnectConInEvent = NULL;
+
+
+/**
+ Event to Connect ConIn.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context Pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+BdsDxeOnConnectConInCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // When Osloader call ReadKeyStroke to signal this event
+ // no driver dependency is assumed existing. So use a non-dispatch version
+ //
+ Status = EfiBootManagerConnectConsoleVariable (ConIn, FALSE);
+ if (EFI_ERROR (Status)) {
+ //
+ // Should not enter this case, if enter, the keyboard will not work.
+ // May need platfrom policy to connect keyboard.
+ //
+ DEBUG ((EFI_D_WARN, "[Bds] ASSERT Connect ConIn failed!!!\n"));
+ }
+}
+
+/**
+
+ Install Boot Device Selection Protocol
+
+ @param ImageHandle The image handle.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCEESS BDS has finished initializing.
+ Return the dispatcher and recall BDS.Entry
+ @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
+
+**/
+EFI_STATUS
+EFIAPI
+BdsInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ //
+ // Install protocol interface
+ //
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiBdsArchProtocolGuid, &gBds,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Callback function to change the L"Timeout" variable.
+**/
+VOID
+SetNoWaiting (
+ IN OUT VOID **Variable,
+ IN OUT UINTN *VariableSize
+ )
+{
+ UINT16 *Timeout;
+
+ ASSERT ((*VariableSize == sizeof (UINT16)) ||
+ (*Variable == NULL && *VariableSize == 0)
+ );
+ Timeout = AllocatePool (sizeof (UINT16));
+ ASSERT (Timeout != NULL);
+ *Timeout = 0;
+
+ *Variable = Timeout;
+ *VariableSize = sizeof (UINT16);
+}
+
+/**
+ Generic function to update the EFI global variables.
+
+ @param VariableName The name of the variable to be updated.
+ @param ProcessVariable The function pointer to update the variable.
+ NULL means to restore to the original value.
+**/
+VOID
+BdsUpdateEfiGlobalVariable (
+ CHAR16 *VariableName,
+ BDS_PROCESS_VARIABLE ProcessVariable
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 BackupVariableName[20];
+ CHAR16 FlagVariableName[20];
+ VOID *Variable;
+ VOID *BackupVariable;
+ VOID *NewVariable;
+ UINTN VariableSize;
+ UINTN BackupVariableSize;
+ UINTN NewVariableSize;
+ BOOLEAN Flag;
+ BOOLEAN *FlagVariable;
+ UINTN FlagSize;
+
+ ASSERT (StrLen (VariableName) <= 13);
+ UnicodeSPrint (BackupVariableName, sizeof (BackupVariableName), L"%sBackup", VariableName);
+ UnicodeSPrint (FlagVariableName, sizeof (FlagVariableName), L"%sModify", VariableName);
+
+ Variable = EfiBootManagerGetVariableAndSize (VariableName, &gEfiGlobalVariableGuid, &VariableSize);
+ BackupVariable = EfiBootManagerGetVariableAndSize (BackupVariableName, &gEfiCallerIdGuid, &BackupVariableSize);
+ FlagVariable = EfiBootManagerGetVariableAndSize (FlagVariableName, &gEfiCallerIdGuid, &FlagSize);
+ if ((ProcessVariable != NULL) && (FlagVariable == NULL)) {
+ //
+ // Current boot is a modified boot and last boot is a normal boot
+ // Set flag to indicate it's a modified boot
+ // BackupVariable <- Variable
+ // Variable <- ProcessVariable (Variable)
+ //
+ Flag = TRUE;
+ Status = gRT->SetVariable (
+ FlagVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (Flag),
+ &Flag
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gRT->SetVariable (
+ BackupVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ VariableSize,
+ Variable
+ );
+ ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND));
+
+
+ NewVariable = Variable;
+ NewVariableSize = VariableSize;
+ ProcessVariable (&NewVariable, &NewVariableSize);
+
+ Status = gRT->SetVariable (
+ VariableName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ NewVariableSize,
+ NewVariable
+ );
+ ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND));
+
+ if (NewVariable != NULL) {
+ FreePool (NewVariable);
+ }
+ } else if ((ProcessVariable == NULL) && (FlagVariable != NULL)) {
+ //
+ // Current boot is a normal boot and last boot is a modified boot
+ // Clear flag to indicate it's a normal boot
+ // Variable <- BackupVariable
+ // BackupVariable <- NULL
+ //
+ Status = gRT->SetVariable (
+ FlagVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gRT->SetVariable (
+ VariableName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ BackupVariableSize,
+ BackupVariable
+ );
+ ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND));
+
+ Status = gRT->SetVariable (
+ BackupVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+ ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND));
+ }
+
+ if (Variable != NULL) {
+ FreePool (Variable);
+ }
+
+ if (BackupVariable != NULL) {
+ FreePool (BackupVariable);
+ }
+
+ if (FlagVariable != NULL) {
+ FreePool (FlagVariable);
+ }
+}
+
+
+/**
+ Function waits for a given event to fire, or for an optional timeout to expire.
+
+ @param Event The event to wait for
+ @param Timeout An optional timeout value in 100 ns units.
+
+ @retval EFI_SUCCESS Event fired before Timeout expired.
+ @retval EFI_TIME_OUT Timout expired before Event fired..
+
+**/
+EFI_STATUS
+BdsWaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout OPTIONAL
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_EVENT TimerEvent;
+ EFI_EVENT WaitList[2];
+
+ if (Timeout != 0) {
+ //
+ // Create a timer event
+ //
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+
+ //
+ // Wait for the original event or the timer
+ //
+ WaitList[0] = Event;
+ WaitList[1] = TimerEvent;
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+ ASSERT_EFI_ERROR (Status);
+ gBS->CloseEvent (TimerEvent);
+
+ //
+ // If the timer expired, change the return to timed out
+ //
+ if (Index == 1) {
+ Status = EFI_TIMEOUT;
+ }
+ }
+ } else {
+ //
+ // No timeout... just wait on the event
+ //
+ Status = gBS->WaitForEvent (1, &Event, &Index);
+ ASSERT (!EFI_ERROR (Status));
+ ASSERT (Index == 0);
+ }
+
+ return Status;
+}
+
+/**
+ The function reads user inputs.
+
+**/
+
+VOID
+BdsReadKeys (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ while (gST->ConIn != NULL) {
+
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // No more keys.
+ //
+ break;
+ }
+ }
+}
+
+/**
+ The function waits for the boot manager timeout expires or hotkey is pressed.
+
+ It calls PlatformBootManagerWaitCallback each second.
+**/
+VOID
+BdsWait (
+ IN EFI_EVENT HotkeyTriggered
+ )
+{
+ EFI_STATUS Status;
+ UINT16 TimeoutRemain;
+
+ DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n"));
+
+ TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut);
+ while (TimeoutRemain != 0) {
+ DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain));
+ PlatformBootManagerWaitCallback (TimeoutRemain);
+ if (!PcdGetBool (PcdConInConnectOnDemand)) {
+ BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered
+ // Can be removed after all keyboard drivers invoke callback in timer callback.
+ }
+
+ if (HotkeyTriggered != NULL) {
+ Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1));
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ } else {
+ gBS->Stall (1000000);
+ }
+
+ //
+ // 0xffff means waiting forever
+ // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop
+ //
+ if (TimeoutRemain != 0xffff) {
+ TimeoutRemain--;
+ }
+ }
+ DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n"));
+}
+
+/**
+ Attempt to boot each boot option in the BootOptions array.
+
+ @retval TRUE Successfully boot one of the boot options.
+ @retval FALSE Failed boot any of the boot options.
+**/
+BOOLEAN
+BootAllBootOptions (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,
+ IN UINTN BootOptionCount
+ )
+{
+ UINTN Index;
+
+ //
+ // Attempt boot each boot option
+ //
+ for (Index = 0; Index < BootOptionCount; Index++) {
+ //
+ // According to EFI Specification, if a load option is not marked
+ // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
+ // load the option.
+ //
+ if ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) {
+ continue;
+ }
+
+ //
+ // All the driver options should have been processed since
+ // now boot will be performed.
+ //
+ EfiBootManagerBoot (&BootOptions[Index]);
+
+ //
+ // Successful boot breaks the loop, otherwise tries next boot option
+ //
+ if (BootOptions[Index].Status == EFI_SUCCESS) {
+ break;
+ }
+ }
+
+ return (BOOLEAN) (Index < BootOptionCount);
+}
+
+/**
+ This function attempts to boot per the boot order specified by platform policy.
+
+ If the boot via Boot#### returns with a status of EFI_SUCCESS the boot manager will stop
+ processing the BootOrder variable and present a boot manager menu to the user. If a boot via
+ Boot#### returns a status other than EFI_SUCCESS, the boot has failed and the next Boot####
+ in the BootOrder variable will be tried until all possibilities are exhausted.
+ -- Chapter 3.1.1 Boot Manager Programming, the 4th paragraph
+**/
+VOID
+DefaultBootBehavior (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN BootOptionCount;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+ if (BootAllBootOptions (BootOptions, BootOptionCount)) {
+ //
+ // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
+ //
+ if (PcdGetBool (PcdConInConnectOnDemand)) {
+ BdsDxeOnConnectConInCallBack (NULL, NULL);
+ }
+
+ //
+ // Show the Boot Manager Menu after successful boot
+ //
+ Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
+ ASSERT_EFI_ERROR (Status);
+ EfiBootManagerBoot (&BootManagerMenu);
+ EfiBootManagerFreeLoadOption (&BootManagerMenu);
+ } else {
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+ //
+ // Re-scan all EFI boot options in case all the boot#### are deleted or failed to boot
+ //
+ // TODO: Can move the below connect all to EfiBootManagerEnumerateBootOptions
+ EfiBootManagerConnectAll ();
+ BootOptions = EfiBootManagerEnumerateBootOptions (&BootOptionCount);
+
+ if (!BootAllBootOptions (BootOptions, BootOptionCount)) {
+ DEBUG ((EFI_D_ERROR, "[Bds]No bootable device!\n"));
+ ASSERT_EFI_ERROR (EFI_NOT_FOUND);
+ }
+ }
+
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+/**
+ The function will go through the driver option link list, load and start
+ every driver the driver option device path point to.
+
+ @param BdsDriverLists The header of the current driver option link list
+
+**/
+VOID
+LoadDrivers (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *DriverOption,
+ IN UINTN DriverOptionCount
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_HANDLE ImageHandle;
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
+ BOOLEAN ReconnectAll;
+
+ ReconnectAll = FALSE;
+
+ //
+ // Process the driver option
+ //
+ for (Index = 0; Index < DriverOptionCount; Index++) {
+ //
+ // If a load option is not marked as LOAD_OPTION_ACTIVE,
+ // the boot manager will not automatically load the option.
+ //
+ if ((DriverOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) {
+ continue;
+ }
+
+ //
+ // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
+ // then all of the EFI drivers in the system will be disconnected and
+ // reconnected after the last driver load option is processed.
+ //
+ if ((DriverOption[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0) {
+ ReconnectAll = TRUE;
+ }
+
+ //
+ // Make sure the driver path is connected.
+ //
+ EfiBootManagerConnectDevicePath (DriverOption[Index].FilePath, NULL);
+
+ //
+ // Load and start the image that Driver#### describes
+ //
+ Status = gBS->LoadImage (
+ FALSE,
+ gImageHandle,
+ DriverOption[Index].FilePath,
+ NULL,
+ 0,
+ &ImageHandle
+ );
+
+ if (!EFI_ERROR (Status)) {
+ gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
+
+ //
+ // Verify whether this image is a driver, if not,
+ // exit it and continue to parse next load option
+ //
+ if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {
+ gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
+ continue;
+ }
+
+ ImageInfo->LoadOptionsSize = DriverOption[Index].OptionalDataSize;
+ ImageInfo->LoadOptions = DriverOption[Index].OptionalData;
+ //
+ // Before calling the image, enable the Watchdog Timer for
+ // the 5 Minute period
+ //
+ gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
+
+ DriverOption[Index].Status = gBS->StartImage (ImageHandle, &DriverOption[Index].ExitDataSize, &DriverOption[Index].ExitData);
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", DriverOption[Index].Status));
+
+ //
+ // Clear the Watchdog Timer after the image returns
+ //
+ gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
+ }
+ }
+
+ //
+ // Process the LOAD_OPTION_FORCE_RECONNECT driver option
+ //
+ if (ReconnectAll) {
+ EfiBootManagerDisconnectAll ();
+ EfiBootManagerConnectAll ();
+ }
+
+}
+
+/**
+
+ Validate input console variable data.
+
+ If found the device path is not a valid device path, remove the variable.
+
+ @param VariableName Input console variable name.
+
+**/
+VOID
+BdsFormalizeConsoleVariable (
+ IN CHAR16 *VariableName
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN VariableSize;
+ EFI_STATUS Status;
+
+ DevicePath = EfiBootManagerGetVariableAndSize (
+ VariableName,
+ &gEfiGlobalVariableGuid,
+ &VariableSize
+ );
+ if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) {
+ Status = gRT->SetVariable (
+ VariableName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+/**
+ Formalize OsIndication related variables.
+
+ For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps
+ Delete OsIndications variable if it is not NV/BS/RT UINT64.
+
+ Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable.
+
+**/
+VOID
+BdsFormalizeOSIndicationVariable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 OsIndicationSupport;
+ UINT64 OsIndication;
+ UINTN DataSize;
+ UINT32 Attributes;
+
+ //
+ // OS indicater support variable
+ //
+ OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
+ Status = gRT->SetVariable (
+ L"OsIndicationsSupported",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(UINT64),
+ &OsIndicationSupport
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // If OsIndications is invalid, remove it.
+ // Invalid case
+ // 1. Data size != UINT64
+ // 2. OsIndication value inconsistence
+ // 3. OsIndication attribute inconsistence
+ //
+ OsIndication = 0;
+ Attributes = 0;
+ DataSize = sizeof(UINT64);
+ Status = gRT->GetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ &Attributes,
+ &DataSize,
+ &OsIndication
+ );
+ if (Status == EFI_NOT_FOUND) {
+ return;
+ }
+
+ if (DataSize != sizeof(UINT64) ||
+ (OsIndication & ~OsIndicationSupport) != 0 ||
+ Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE)){
+
+ DEBUG ((EFI_D_ERROR, "Unformalized OsIndications variable exists. Delete it\n"));
+ Status = gRT->SetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ Attributes,
+ 0,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+ }
+}
+
+/**
+
+ Validate variables.
+
+**/
+VOID
+BdsFormalizeEfiGlobalVariable (
+ VOID
+ )
+{
+ //
+ // Validate Console variable.
+ //
+ BdsFormalizeConsoleVariable (L"ConIn");
+ BdsFormalizeConsoleVariable (L"ConOut");
+ BdsFormalizeConsoleVariable (L"ErrOut");
+
+ //
+ // Validate OSIndication related variable.
+ //
+ BdsFormalizeOSIndicationVariable ();
+}
+
+/**
+
+ Service routine for BdsInstance->Entry(). Devices are connected, the
+ consoles are initialized, and the boot options are tried.
+
+ @param This Protocol Instance structure.
+
+**/
+VOID
+EFIAPI
+BdsEntry (
+ IN EFI_BDS_ARCH_PROTOCOL *This
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *DriverOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+ UINTN DriverOptionCount;
+ CHAR16 *FirmwareVendor;
+ EFI_EVENT HotkeyTriggered;
+ UINT32 PlatformBdsRequest;
+ UINT64 OsIndication;
+ UINTN DataSize;
+ EFI_STATUS Status;
+ UINT32 BootOptionSupport;
+
+
+ HotkeyTriggered = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // Insert the performance probe
+ //
+ PERF_END (NULL, "DXE", NULL, 0);
+ PERF_START (NULL, "BDS", NULL, 0);
+ DEBUG ((EFI_D_INFO, "[Bds] Entry...\n"));
+
+ //
+ // Fill in FirmwareVendor and FirmwareRevision from PCDs
+ //
+ FirmwareVendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor);
+ gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor);
+ ASSERT (gST->FirmwareVendor != NULL);
+ gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision);
+
+ //
+ // Fixup Tasble CRC after we updated Firmware Vendor and Revision
+ //
+ gST->Hdr.CRC32 = 0;
+ gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);
+
+ //
+ // Validate Variable.
+ //
+ BdsFormalizeEfiGlobalVariable();
+
+ InitializeHwErrRecSupport ();
+
+ //
+ // Initialize the platform language variables
+ //
+ InitializeLanguage (TRUE);
+
+ //
+ // Initialize hotkey service
+ // Do not report the hotkey capability if PcdConInConnectOnDemand is enabled.
+ //
+ if (!PcdGetBool (PcdConInConnectOnDemand)) {
+ EfiBootManagerStartHotkeyService (&HotkeyTriggered);
+ }
+
+ //
+ // Report Status Code to indicate connecting drivers will happen
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS)
+ );
+
+ //
+ // Do the platform init, can be customized by OEM/IBV
+ // Possible things that can be done in PlatformBdsInit:
+ // > Update console variable: 1. include hot-plug devices; 2. Clear ConIn and add SOL for AMT
+ // > Register new Driver#### or Boot####
+ // > Register new Key####: e.g.: F12
+ // > Signal ReadyToLock event
+ // > Authentication action: 1. connect Auth devices; 2. Identify auto logon user.
+ //
+ PERF_START (NULL, "PlatformBootManagerBeforeConsole", "BDS", 0);
+ PlatformBootManagerBeforeConsole ();
+ PERF_END (NULL, "PlatformBootManagerBeforeConsole", "BDS", 0);
+
+ //
+ // Load Driver Options
+ //
+ DriverOption = EfiBootManagerGetLoadOptions (&DriverOptionCount, LoadOptionTypeDriver);
+ LoadDrivers (DriverOption, DriverOptionCount);
+ EfiBootManagerFreeLoadOptions (DriverOption, DriverOptionCount);
+
+ //
+ // Connect consoles
+ //
+ PERF_START (NULL, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
+ if (PcdGetBool (PcdConInConnectOnDemand)) {
+ EfiBootManagerConnectConsoleVariable (ConOut, TRUE);
+ EfiBootManagerConnectConsoleVariable (ErrOut, TRUE);
+
+ //
+ // Initialize ConnectConIn event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ BdsDxeOnConnectConInCallBack,
+ NULL,
+ &gConnectConInEventGuid,
+ &gConnectConInEvent
+ );
+ if (EFI_ERROR (gConnectConInEvent)) {
+ gConnectConInEvent = NULL;
+ }
+ } else {
+ EfiBootManagerConnectAllDefaultConsoles();
+ }
+ PERF_END (NULL, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
+
+ //
+ // Do the platform specific action after the console is ready
+ // Possible things that can be done in PlatformBootManagerConsoleReady:
+ // > Console post action:
+ // > Dynamically switch output mode from 100x31 to 80x25 for AMT SOL
+ // > Signal console ready platform customized event
+ // > Run diagnostics: 1. driver health check; 2. memory test
+ // > Connect certain devices: 1. connect all; 2. connect nothing; 3. connect platform specified devices
+ // > Dispatch aditional option roms
+ // > Special boot: e.g.: AMT boot, enter UI
+ //
+ // NOTE: New boot options could appear after connecting certain devices.
+ // WHEN to enumerate the boot options? Ideally, only do the enumeration in FULL_CONFIGURATION boot mode.
+ // -> if so, the boot option enumeration can be done in BdsDxe driver
+ // BUT 1. user may plug in new HD/remove HD; 2. PXE enable/disable; 3. SATA mode (IDE/AHCI/RAID) need to enumerate the boot option again.
+ // 1 can be detected by chassis intrusion, 2 & 3 can be handled by code.
+ // BDS assumes platform code should set correct boot mode.
+ //
+ PERF_START (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);
+ PlatformBdsRequest = PlatformBootManagerAfterConsole ();
+ PERF_END (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);
+
+ if (PcdGetBool (PcdConInConnectOnDemand)) {
+ PlatformBdsRequest &= ~PLATFORM_BOOT_MANAGER_ENABLE_HOTKEY;
+ }
+
+ //
+ // Clear/Restore Key####/Timeout per platform request
+ // For Timeout, variable change is enough to control the following behavior
+ // For Key####, variable change is not enough so we still need to check the *_ENABLE_HOTKEY later
+ //
+ if ((PlatformBdsRequest & PLATFORM_BOOT_MANAGER_ENABLE_TIMEOUT) == PLATFORM_BOOT_MANAGER_ENABLE_TIMEOUT) {
+ BdsUpdateEfiGlobalVariable (L"Timeout", NULL);
+ } else {
+ BdsUpdateEfiGlobalVariable (L"Timeout", SetNoWaiting);
+ }
+
+ //
+ // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP
+ // with maximum number of key presses of 3
+ //
+ BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP;
+ if ((PlatformBdsRequest & PLATFORM_BOOT_MANAGER_ENABLE_HOTKEY) == PLATFORM_BOOT_MANAGER_ENABLE_HOTKEY) {
+ BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;
+ SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
+ }
+ Status = gRT->SetVariable (
+ L"BootOptionSupport",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (UINT32),
+ &BootOptionSupport
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG_CODE (
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ UINTN Index;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+ DEBUG ((EFI_D_INFO, "[Bds]=============Dumping Boot Options=============\n"));
+ for (Index = 0; Index < BootOptionCount; Index++) {
+ DEBUG ((
+ EFI_D_INFO, "[Bds]Boot%04x: %s \t\t 0x%04x\n",
+ BootOptions[Index].OptionNumber,
+ BootOptions[Index].Description,
+ BootOptions[Index].Attributes
+ ));
+ }
+ DEBUG ((EFI_D_INFO, "[Bds]=============Dumping Boot Options Finished====\n"));
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+ );
+
+ //
+ // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set
+ //
+ DataSize = sizeof(UINT64);
+ Status = gRT->GetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &DataSize,
+ &OsIndication
+ );
+
+ //
+ // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
+ //
+ if (!EFI_ERROR(Status) && ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0)) {
+ //
+ // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS
+ //
+ OsIndication &= ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
+ Status = gRT->SetVariable (
+ L"OsIndications",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof(UINT64),
+ &OsIndication
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
+ //
+ if (PcdGetBool (PcdConInConnectOnDemand)) {
+ BdsDxeOnConnectConInCallBack (NULL, NULL);
+ }
+
+ //
+ // Directly enter the setup page.
+ //
+ Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+ ASSERT_EFI_ERROR (Status);
+ EfiBootManagerBoot (&BootOption);
+ EfiBootManagerFreeLoadOption (&BootOption);
+ } else {
+ PERF_START (NULL, "BdsWait", "BDS", 0);
+ BdsWait (HotkeyTriggered);
+ PERF_END (NULL, "BdsWait", "BDS", 0);
+
+ if (!PcdGetBool (PcdConInConnectOnDemand)) {
+ //
+ // No need to check hotkey boot if hotkey service is disabled.
+ //
+ if ((PlatformBdsRequest & PLATFORM_BOOT_MANAGER_ENABLE_HOTKEY) == PLATFORM_BOOT_MANAGER_ENABLE_HOTKEY) {
+ //
+ // BUGBUG: Only reading can trigger the notification function
+ // Can be removed after all keyboard drivers are updated to invoke callback in timer callback.
+ //
+ BdsReadKeys ();
+
+ EfiBootManagerHotkeyBoot ();
+ }
+ }
+ }
+
+ while (TRUE) {
+ //
+ // BDS select the boot device to load OS
+ // Try next upon boot failure
+ // Show Boot Manager Menu upon boot success
+ //
+ DefaultBootBehavior ();
+ }
+}
diff --git a/QuarkPlatformPkg/Bds/BdsDxe/HwErrRecSupport.c b/QuarkPlatformPkg/Bds/BdsDxe/HwErrRecSupport.c
new file mode 100644
index 0000000..40aebe7
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BdsDxe/HwErrRecSupport.c
@@ -0,0 +1,61 @@
+/** @file
+ Set the level of support for Hardware Error Record Persistence that is
+ implemented by the platform.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "HwErrRecSupport.h"
+
+/**
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the
+ level of support for Hardware Error Record Persistence that is implemented
+ by the platform.
+
+**/
+VOID
+InitializeHwErrRecSupport (
+ VOID
+ )
+{
+ UINT16 HardwareErrorRecordLevel;
+
+ HardwareErrorRecordLevel = PcdGet16 (PcdHardwareErrorRecordLevel);
+
+ if (HardwareErrorRecordLevel != 0) {
+ //
+ // Set original value again to make sure this value is stored into variable
+ // area but not PCD database.
+ // if level value equal 0, no need set to 0 to variable area because UEFI specification
+ // define same behavior between no value or 0 value for L"HwErrRecSupport"
+ //
+ PcdSet16 (PcdHardwareErrorRecordLevel, HardwareErrorRecordLevel);
+ }
+}
diff --git a/QuarkPlatformPkg/Bds/BdsDxe/HwErrRecSupport.h b/QuarkPlatformPkg/Bds/BdsDxe/HwErrRecSupport.h
new file mode 100644
index 0000000..c525790
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BdsDxe/HwErrRecSupport.h
@@ -0,0 +1,51 @@
+/** @file
+ Set the level of support for Hardware Error Record Persistence that is
+ implemented by the platform.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _HW_ERR_REC_SUPPORT_H_
+#define _HW_ERR_REC_SUPPORT_H_
+
+#include "Bds.h"
+
+/**
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the
+ level of support for Hardware Error Record Persistence that is implemented
+ by the platform.
+
+**/
+VOID
+InitializeHwErrRecSupport (
+ VOID
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Bds/BdsDxe/Language.c b/QuarkPlatformPkg/Bds/BdsDxe/Language.c
new file mode 100644
index 0000000..8958c4f
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BdsDxe/Language.c
@@ -0,0 +1,152 @@
+/** @file
+ Language settings
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Bds.h"
+#define ISO_639_2_ENTRY_SIZE 3
+
+/**
+ Determine the current language that will be used
+ based on language related EFI Variables.
+
+ @param LangCodesSettingRequired - If required to set LangCode variable
+
+**/
+VOID
+InitializeLanguage (
+ BOOLEAN LangCodesSettingRequired
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ CHAR8 *Lang;
+ CHAR8 LangCode[ISO_639_2_ENTRY_SIZE + 1];
+ CHAR8 *LangCodes;
+ CHAR8 *PlatformLang;
+ CHAR8 *PlatformLangCodes;
+ UINTN Index;
+ BOOLEAN Invalid;
+
+ LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes);
+ if (LangCodesSettingRequired) {
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {
+ //
+ // UEFI 2.1 depricated this variable so we support turning it off
+ //
+ Status = gRT->SetVariable (
+ L"LangCodes",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (LangCodes),
+ LangCodes
+ );
+ }
+
+
+ PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes);
+ Status = gRT->SetVariable (
+ L"PlatformLangCodes",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (PlatformLangCodes),
+ PlatformLangCodes
+ );
+ }
+
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {
+ //
+ // UEFI 2.1 depricated this variable so we support turning it off
+ //
+
+ //
+ // Find current LangCode from Lang NV Variable
+ //
+ Size = ISO_639_2_ENTRY_SIZE + 1;
+ Status = gRT->GetVariable (
+ L"Lang",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &Size,
+ &LangCode
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) {
+ if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+
+ //
+ // If we cannot get language code from Lang variable,
+ // or LangCode cannot be found from language table,
+ // set the mDefaultLangCode to Lang variable.
+ //
+ if (EFI_ERROR (Status)) {
+ Lang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang);
+ Status = gRT->SetVariable (
+ L"Lang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ ISO_639_2_ENTRY_SIZE + 1,
+ Lang
+ );
+ }
+ }
+
+ Invalid = FALSE;
+ PlatformLang = EfiBootManagerGetVariableAndSize (L"PlatformLang", &gEfiGlobalVariableGuid, &Size);
+ if (PlatformLang != NULL) {
+ //
+ // Check Current PlatformLang value against PlatformLangCode. Need a library that is TBD
+ // Set Invalid based on state of PlatformLang.
+ //
+
+ FreePool (PlatformLang);
+ } else {
+ // No valid variable is set
+ Invalid = TRUE;
+ }
+
+ if (Invalid) {
+ PlatformLang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang);
+ Status = gRT->SetVariable (
+ L"PlatformLang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (PlatformLang),
+ PlatformLang
+ );
+ }
+}
diff --git a/QuarkPlatformPkg/Bds/BdsDxe/Language.h b/QuarkPlatformPkg/Bds/BdsDxe/Language.h
new file mode 100644
index 0000000..6b2bceb
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BdsDxe/Language.h
@@ -0,0 +1,49 @@
+/** @file
+ Language setting
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _LANGUAGE_H_
+#define _LANGUAGE_H_
+
+/**
+ Determine the current language that will be used
+ based on language related EFI Variables.
+
+ @param LangCodesSettingRequired If required to set LangCode variable
+
+**/
+VOID
+InitializeLanguage (
+ BOOLEAN LangCodesSettingRequired
+ );
+
+#endif // _LANGUAGE_H_
diff --git a/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenu.c b/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenu.c
new file mode 100644
index 0000000..ff2559d
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenu.c
@@ -0,0 +1,760 @@
+/** @file
+ The application to show the Boot Manager Menu.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+#include "BootManagerMenu.h"
+
+/**
+ Prints a unicode string to the default console, at
+ the supplied cursor position, using L"%s" format.
+
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at
+ @param String String pointer.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+PrintStringAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *String
+ )
+{
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
+ return Print (L"%s", String);
+}
+
+/**
+ Prints a chracter to the default console, at
+ the supplied cursor position, using L"%c" format.
+
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at.
+ @param Character Character to print.
+
+ @return Length of string printed to the console.
+
+**/
+UINTN
+PrintCharAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 Character
+ )
+{
+ gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
+ return Print (L"%c", Character);
+}
+
+/**
+ Count the storage space of a Unicode string which uses current lanaguag to get
+ from input string ID.
+
+ @param String The input string to be counted.
+
+ @return Storage space for the input string.
+
+**/
+UINTN
+GetLineWidth (
+ IN EFI_STRING_ID StringId
+ )
+{
+ UINTN Index;
+ UINTN IncrementValue;
+ EFI_STRING String;
+ UINTN LineWidth;
+
+ LineWidth = 0;
+ String = HiiGetString (gStringPackHandle, StringId, NULL);
+
+ if (String != NULL) {
+ Index = 0;
+ IncrementValue = 1;
+
+ do {
+ //
+ // Advance to the null-terminator or to the first width directive
+ //
+ for (;
+ (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
+ Index++, LineWidth = LineWidth + IncrementValue
+ )
+ ;
+
+ //
+ // We hit the null-terminator, we now have a count
+ //
+ if (String[Index] == 0) {
+ break;
+ }
+ //
+ // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
+ // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
+ //
+ if (String[Index] == NARROW_CHAR) {
+ //
+ // Skip to the next character
+ //
+ Index++;
+ IncrementValue = 1;
+ } else {
+ //
+ // Skip to the next character
+ //
+ Index++;
+ IncrementValue = 2;
+ }
+ } while (String[Index] != 0);
+ FreePool (String);
+ }
+
+ return LineWidth;
+}
+
+/**
+ This function uses calculate the boot menu location, size and scroll bar information.
+
+ @param BootMenuData The boot menu data to be proccessed.
+
+ @return EFI_SUCCESS calculate boot menu information successful.
+ @retval EFI_INVALID_PARAMETER Input parameter is invalid
+
+**/
+EFI_STATUS
+InitializeBootMenuScreen (
+ IN OUT BOOT_MENU_POPUP_DATA *BootMenuData
+ )
+{
+ UINTN MaxStrWidth;
+ UINTN StrWidth;
+ UINTN Index;
+ UINTN Column;
+ UINTN Row;
+ UINTN MaxPrintRows;
+ UINTN UnSelectableItmes;
+
+ if (BootMenuData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Get maximum string width
+ //
+ MaxStrWidth = 0;
+ for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {
+ StrWidth = GetLineWidth (BootMenuData->TitleToken[Index]);
+ MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
+ }
+
+ for (Index = 0; Index < BootMenuData->ItemCount; Index++) {
+ StrWidth = GetLineWidth (BootMenuData->PtrTokens[Index]);
+ MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
+ }
+
+ for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {
+ StrWidth = GetLineWidth (BootMenuData->HelpToken[Index]);
+ MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
+ }
+ //
+ // query current row and column to calculate boot menu location
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &Column,
+ &Row
+ );
+
+ MaxPrintRows = Row - 6;
+ UnSelectableItmes = TITLE_TOKEN_COUNT + 2 + HELP_TOKEN_COUNT + 2;
+ BootMenuData->MenuScreen.Width = MaxStrWidth + 8;
+ if (BootMenuData->ItemCount + UnSelectableItmes > MaxPrintRows) {
+ BootMenuData->MenuScreen.Height = MaxPrintRows;
+ BootMenuData->ScrollBarControl.HasScrollBar = TRUE;
+ BootMenuData->ScrollBarControl.ItemCountPerScreen = MaxPrintRows - UnSelectableItmes;
+ BootMenuData->ScrollBarControl.FirstItem = 0;
+ BootMenuData->ScrollBarControl.LastItem = MaxPrintRows - UnSelectableItmes - 1;
+ } else {
+ BootMenuData->MenuScreen.Height = BootMenuData->ItemCount + UnSelectableItmes;
+ BootMenuData->ScrollBarControl.HasScrollBar = FALSE;
+ BootMenuData->ScrollBarControl.ItemCountPerScreen = BootMenuData->ItemCount;
+ BootMenuData->ScrollBarControl.FirstItem = 0;
+ BootMenuData->ScrollBarControl.LastItem = BootMenuData->ItemCount - 1;
+ }
+ BootMenuData->MenuScreen.StartCol = (Column - BootMenuData->MenuScreen.Width) / 2;
+ BootMenuData->MenuScreen.StartRow = (Row - BootMenuData->MenuScreen.Height) / 2;
+
+ return EFI_SUCCESS;
+}
+/**
+ This funciton uses check boot option is wheher setup application or no
+
+ @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
+
+ @retval TRUE This boot option is setup application.
+ @retval FALSE This boot options isn't setup application
+
+**/
+BOOLEAN
+IsBootManagerMenu (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
+
+ Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
+ if (!EFI_ERROR (Status)) {
+ EfiBootManagerFreeLoadOption (&BootManagerMenu);
+ }
+
+ return (BOOLEAN) (!EFI_ERROR (Status) && (BootOption->OptionNumber == BootManagerMenu.OptionNumber));
+}
+
+
+/**
+ This funciton uses to initialize boot menu data
+
+ @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
+ @param BootOptionCount Number of boot option.
+ @param BootMenuData The Input BootMenuData to be initialized.
+
+ @retval EFI_SUCCESS Initialize boot menu data successful.
+ @retval EFI_INVALID_PARAMETER Input parameter is invalid.
+
+**/
+EFI_STATUS
+InitializeBootMenuData (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,
+ IN UINTN BootOptionCount,
+ OUT BOOT_MENU_POPUP_DATA *BootMenuData
+ )
+{
+ UINTN Index;
+ UINTN StrIndex;
+
+ if (BootOption == NULL || BootMenuData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BootMenuData->TitleToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING);
+ BootMenuData->PtrTokens = AllocateZeroPool (BootOptionCount * sizeof (EFI_STRING_ID));
+ ASSERT (BootMenuData->PtrTokens != NULL);
+
+ //
+ // Skip boot option which created by BootNext Variable
+ //
+ Index = 0;
+ if (BootOptionCount != 0 && BootOption[0].BootNext) {
+ Index++;
+ }
+ for (StrIndex = 0; Index < BootOptionCount; Index++) {
+ //
+ // Don't display the hidden/inactive boot option except setup application.
+ //
+ if ((((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) &&
+ !IsBootManagerMenu (&BootOption[Index])) {
+ continue;
+ }
+ ASSERT (BootOption[Index].Description != NULL);
+ BootMenuData->PtrTokens[StrIndex++] = HiiSetString (
+ gStringPackHandle,
+ 0,
+ BootOption[Index].Description,
+ NULL
+ );
+ }
+
+ BootMenuData->ItemCount = StrIndex;
+ BootMenuData->HelpToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING);
+ BootMenuData->HelpToken[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING);
+ BootMenuData->HelpToken[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING);
+ InitializeBootMenuScreen (BootMenuData);
+ BootMenuData->SelectItem = 0;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function uses input select item to highlight selected item
+ and set current selected item in BootMenuData
+
+ @param BootMenuData The boot menu data to be proccessed
+ @param WantSelectItem The user wants to select item.
+
+ @return EFI_SUCCESS Highlight selected item and update current selected
+ item successful
+ @retval EFI_INVALID_PARAMETER Input parameter is invalid
+**/
+EFI_STATUS
+BootMenuSelectItem (
+ IN UINTN WantSelectItem,
+ IN OUT BOOT_MENU_POPUP_DATA *BootMenuData
+ )
+{
+ INT32 SavedAttribute;
+ EFI_STRING String;
+ UINTN StartCol;
+ UINTN StartRow;
+ UINTN PrintCol;
+ UINTN PrintRow;
+ UINTN TopShadeNum;
+ UINTN LowShadeNum;
+ UINTN FirstItem;
+ UINTN LastItem;
+ UINTN ItemCountPerScreen;
+ UINTN Index;
+ BOOLEAN RePaintItems;
+
+ if (BootMenuData == NULL || WantSelectItem >= BootMenuData->ItemCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+ SavedAttribute = gST->ConOut->Mode->Attribute;
+ RePaintItems = FALSE;
+ StartCol = BootMenuData->MenuScreen.StartCol;
+ StartRow = BootMenuData->MenuScreen.StartRow;
+ //
+ // print selectable items again and adjust scroll bar if need
+ //
+ if (BootMenuData->ScrollBarControl.HasScrollBar &&
+ (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem ||
+ WantSelectItem > BootMenuData->ScrollBarControl.LastItem ||
+ WantSelectItem == BootMenuData->SelectItem)) {
+ ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;
+ //
+ // Set first item and last item
+ //
+ if (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem) {
+ BootMenuData->ScrollBarControl.FirstItem = WantSelectItem;
+ BootMenuData->ScrollBarControl.LastItem = WantSelectItem + ItemCountPerScreen - 1;
+ } else if (WantSelectItem > BootMenuData->ScrollBarControl.LastItem) {
+ BootMenuData->ScrollBarControl.FirstItem = WantSelectItem - ItemCountPerScreen + 1;
+ BootMenuData->ScrollBarControl.LastItem = WantSelectItem;
+ }
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
+ FirstItem = BootMenuData->ScrollBarControl.FirstItem;
+ LastItem = BootMenuData->ScrollBarControl.LastItem;
+ TopShadeNum = 0;
+ if (FirstItem != 0) {
+ TopShadeNum = (FirstItem * ItemCountPerScreen) / BootMenuData->ItemCount;
+ if ((FirstItem * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {
+ TopShadeNum++;
+ }
+ PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
+ PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
+ for (Index = 0; Index < TopShadeNum; Index++, PrintRow++) {
+ PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);
+ }
+ }
+ LowShadeNum = 0;
+ if (LastItem != BootMenuData->ItemCount - 1) {
+ LowShadeNum = ((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) / BootMenuData->ItemCount;
+ if (((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {
+ LowShadeNum++;
+ }
+ PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
+ PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + ItemCountPerScreen - LowShadeNum;
+ for (Index = 0; Index < LowShadeNum; Index++, PrintRow++) {
+ PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);
+ }
+ }
+ PrintCol = StartCol + BootMenuData->MenuScreen.Width - 2;
+ PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + TopShadeNum;
+ for (Index = TopShadeNum; Index < ItemCountPerScreen - LowShadeNum; Index++, PrintRow++) {
+ PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_FULL_BLOCK);
+ }
+
+
+ //
+ // Clear selectable items first
+ //
+ PrintCol = StartCol + 1;
+ PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
+ String = AllocateZeroPool ((BootMenuData->MenuScreen.Width - 2) * sizeof (CHAR16));
+ ASSERT (String != NULL);
+ for (Index = 0; Index < BootMenuData->MenuScreen.Width - 3; Index++) {
+ String[Index] = 0x20;
+ }
+ for (Index = 0; Index < ItemCountPerScreen; Index++) {
+ PrintStringAt (PrintCol, PrintRow + Index, String);
+ }
+ FreePool (String);
+ //
+ // print selectable items
+ //
+ for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {
+ String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index + FirstItem], NULL);
+ PrintStringAt (PrintCol, PrintRow, String);
+ FreePool (String);
+ }
+ RePaintItems = TRUE;
+ }
+
+ //
+ // Print want to select item
+ //
+ FirstItem = BootMenuData->ScrollBarControl.FirstItem;
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);
+ String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);
+ PrintCol = StartCol + 1;
+ PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem;
+ PrintStringAt (PrintCol, PrintRow, String);
+ FreePool (String);
+
+ //
+ // if Want Select and selected item isn't the same and doesn't re-draw selectable
+ // items, clear select item
+ //
+ if (WantSelectItem != BootMenuData->SelectItem && !RePaintItems) {
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
+ String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL);
+ PrintCol = StartCol + 1;
+ PrintRow = StartRow + 3 + BootMenuData->SelectItem - FirstItem;
+ PrintStringAt (PrintCol, PrintRow, String);
+ FreePool (String);
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+ BootMenuData->SelectItem = WantSelectItem;
+ return EFI_SUCCESS;
+}
+
+/**
+ This funciton uses to draw boot popup menu
+
+ @param BootMenuData The Input BootMenuData to be processed.
+
+ @retval EFI_SUCCESS Draw boot popup menu successful.
+
+**/
+EFI_STATUS
+DrawBootPopupMenu (
+ IN BOOT_MENU_POPUP_DATA *BootMenuData
+ )
+{
+ EFI_STRING String;
+ UINTN Index;
+ UINTN Width;
+ UINTN Height;
+ UINTN StartCol;
+ UINTN StartRow;
+ UINTN PrintRow;
+ UINTN PrintCol;
+ UINTN LineWidth;
+ INT32 SavedAttribute;
+ UINTN ItemCountPerScreen;
+
+ SavedAttribute = gST->ConOut->Mode->Attribute;
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
+ Width = BootMenuData->MenuScreen.Width;
+ Height = BootMenuData->MenuScreen.Height;
+ StartCol = BootMenuData->MenuScreen.StartCol;
+ StartRow = BootMenuData->MenuScreen.StartRow;
+ ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;
+ PrintRow = StartRow;
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+ //
+ // Draw Boot popup menu screen
+ //
+ PrintCharAt (StartCol, PrintRow, BOXDRAW_DOWN_RIGHT);
+ for (Index = 1; Index < Width - 1; Index++) {
+ PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
+ }
+ PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_DOWN_LEFT);
+
+ //
+ // Draw the screen for title
+ //
+ String = AllocateZeroPool ((Width - 1) * sizeof (CHAR16));
+ ASSERT (String != NULL);
+ for (Index = 0; Index < Width - 2; Index++) {
+ String[Index] = 0x20;
+ }
+
+ for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {
+ PrintRow++;
+ PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
+ PrintStringAt (StartCol + 1, PrintRow, String);
+ PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
+ }
+
+ PrintRow++;
+ PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);
+ for (Index = 1; Index < Width - 1; Index++) {
+ PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
+ }
+ PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);
+
+ //
+ // Draw screen for selectable items
+ //
+ for (Index = 0; Index < ItemCountPerScreen; Index++) {
+ PrintRow++;
+ PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
+ PrintStringAt (StartCol + 1, PrintRow, String);
+ PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
+ }
+
+ PrintRow++;
+ PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);
+ for (Index = 1; Index < Width - 1; Index++) {
+ PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
+ }
+ PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);
+
+ //
+ // Draw screen for Help
+ //
+ for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {
+ PrintRow++;
+ PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
+ PrintStringAt (StartCol + 1, PrintRow, String);
+ PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
+ }
+ FreePool (String);
+
+ PrintRow++;
+ PrintCharAt (StartCol, PrintRow, BOXDRAW_UP_RIGHT);
+ for (Index = 1; Index < Width - 1; Index++) {
+ PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL);
+ }
+ PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_UP_LEFT);
+
+
+ //
+ // print title strings
+ //
+ PrintRow = StartRow + 1;
+ for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++, PrintRow++) {
+ String = HiiGetString (gStringPackHandle, BootMenuData->TitleToken[Index], NULL);
+ LineWidth = GetLineWidth (BootMenuData->TitleToken[Index]);
+ PrintCol = StartCol + (Width - LineWidth) / 2;
+ PrintStringAt (PrintCol, PrintRow, String);
+ FreePool (String);
+ }
+
+ //
+ // print selectable items
+ //
+ PrintCol = StartCol + 1;
+ PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;
+ for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {
+ String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index], NULL);
+ PrintStringAt (PrintCol, PrintRow, String);
+ FreePool (String);
+ }
+
+ //
+ // Print Help strings
+ //
+ PrintRow++;
+ for (Index = 0; Index < HELP_TOKEN_COUNT; Index++, PrintRow++) {
+ String = HiiGetString (gStringPackHandle, BootMenuData->HelpToken[Index], NULL);
+ LineWidth = GetLineWidth (BootMenuData->HelpToken[Index]);
+ PrintCol = StartCol + (Width - LineWidth) / 2;
+ PrintStringAt (PrintCol, PrintRow, String);
+ FreePool (String);
+ }
+
+ //
+ // Print scroll bar if has scroll bar
+ //
+ if (BootMenuData->ScrollBarControl.HasScrollBar) {
+ PrintCol = StartCol + Width - 2;
+ PrintRow = StartRow + 2;
+ PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_UP_TRIANGLE);
+ PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL);
+ PrintRow += (ItemCountPerScreen + 1);
+ PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_DOWN_TRIANGLE);
+ PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL);
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+ //
+ // Print Selected item
+ //
+ BootMenuSelectItem (BootMenuData->SelectItem, BootMenuData);
+ return EFI_SUCCESS;
+}
+
+/**
+ This funciton uses to boot from selected item
+
+ @param BootOption Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
+ @param BootOptionCount Number of boot option.
+ @param SelectItem Current selected item.
+**/
+VOID
+BootFromSelectOption (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,
+ IN UINTN BootOptionCount,
+ IN UINTN SelectItem
+ )
+{
+ UINTN ItemNum;
+ UINTN Index;
+
+ ASSERT (BootOptions != NULL);
+
+ ItemNum = 0;
+ for (Index = 0; Index < BootOptionCount; Index++) {
+ //
+ // Don't display the hidden/inactive boot option except setup application.
+ //
+ if ((((BootOptions[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) &&
+ !IsBootManagerMenu (&BootOptions[Index])) {
+ continue;
+ }
+ if (ItemNum++ == SelectItem) {
+ EfiBootManagerBoot (&BootOptions[Index]);
+ break;
+ }
+ }
+}
+
+/**
+ Display the boot popup menu and allow user select boot item
+
+ @retval EFI_SUCCESS Boot from selected boot option, and return success from boot option
+ @retval EFI_NOT_FOUND User select to enter setup or can not find boot option
+
+**/
+EFI_STATUS
+EFIAPI
+BootManagerMenuEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
+ UINTN BootOptionCount;
+ EFI_STATUS Status;
+ BOOT_MENU_POPUP_DATA BootMenuData;
+ UINTN Index;
+ EFI_INPUT_KEY Key;
+ BOOLEAN ExitApplication;
+ UINTN SelectItem;
+ EFI_BOOT_LOGO_PROTOCOL *BootLogo;
+
+ //
+ // Set Logo status invalid when boot manager menu is launched
+ //
+ BootLogo = NULL;
+ Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
+ if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
+ Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ gStringPackHandle = HiiAddPackages (
+ &gEfiCallerIdGuid,
+ gImageHandle,
+ BootManagerMenuAppStrings,
+ NULL
+ );
+ ASSERT (gStringPackHandle != NULL);
+
+ //
+ // Connect all prior to entering the platform setup menu.
+ //
+ EfiBootManagerConnectAll ();
+ EfiBootManagerRefreshAllBootOption ();
+
+ BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+ //
+ // Initialize Boot menu data
+ //
+ Status = InitializeBootMenuData (BootOption, BootOptionCount, &BootMenuData);
+ //
+ // According to boot menu data to draw boot popup menu
+ //
+ DrawBootPopupMenu (&BootMenuData);
+
+ //
+ // check user input to determine want to re-draw or boot from user selected item
+ //
+ ExitApplication = FALSE;
+ while (!ExitApplication) {
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status)) {
+ switch (Key.UnicodeChar) {
+
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+
+ case SCAN_UP:
+ SelectItem = BootMenuData.SelectItem == 0 ? BootMenuData.ItemCount - 1 : BootMenuData.SelectItem - 1;
+ BootMenuSelectItem (SelectItem, &BootMenuData);
+ break;
+
+ case SCAN_DOWN:
+ SelectItem = BootMenuData.SelectItem == BootMenuData.ItemCount - 1 ? 0 : BootMenuData.SelectItem + 1;
+ BootMenuSelectItem (SelectItem, &BootMenuData);
+ break;
+
+ case SCAN_ESC:
+ gST->ConOut->ClearScreen (gST->ConOut);
+ ExitApplication = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ gST->ConOut->ClearScreen (gST->ConOut);
+ BootFromSelectOption (BootOption, BootOptionCount, BootMenuData.SelectItem);
+ DrawBootPopupMenu (&BootMenuData);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
+ FreePool (BootMenuData.PtrTokens);
+
+ HiiRemovePackages (gStringPackHandle);
+
+ return Status;
+
+} \ No newline at end of file
diff --git a/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenu.h b/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenu.h
new file mode 100644
index 0000000..14653c7
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenu.h
@@ -0,0 +1,81 @@
+/** @file
+ FrontPage routines to handle the callbacks and browser calls
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+#ifndef _UI_BOOT_MENU_H_
+#define _UI_BOOT_MENU_H_
+
+#include <Uefi.h>
+#include <Guid/MdeModuleHii.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/BootLogo.h>
+
+EFI_HII_HANDLE gStringPackHandle;
+
+#define TITLE_TOKEN_COUNT 1
+#define HELP_TOKEN_COUNT 3
+
+typedef struct _BOOT_MENU_SCREEN {
+ UINTN StartCol;
+ UINTN StartRow;
+ UINTN Width;
+ UINTN Height;
+} BOOT_MENU_SCREEN;
+
+typedef struct _BOOT_MENU_SCROLL_BAR_CONTROL {
+ BOOLEAN HasScrollBar;
+ UINTN ItemCountPerScreen;
+ UINTN FirstItem;
+ UINTN LastItem;
+} BOOT_MENU_SCROLL_BAR_CONTROL;
+
+typedef struct _BOOT_MENU_POPUP_DATA {
+ EFI_STRING_ID TitleToken[TITLE_TOKEN_COUNT]; // Title string ID
+ UINTN ItemCount; // Selectable item count
+ EFI_STRING_ID *PtrTokens; // All of selectable items string ID
+ EFI_STRING_ID HelpToken[HELP_TOKEN_COUNT]; // All of help string ID
+ UINTN SelectItem; // Current select item
+ BOOT_MENU_SCREEN MenuScreen; // Boot menu screen information
+ BOOT_MENU_SCROLL_BAR_CONTROL ScrollBarControl; // Boot menu scroll bar inoformation
+} BOOT_MENU_POPUP_DATA;
+
+#endif
+
diff --git a/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuApp.inf b/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuApp.inf
new file mode 100644
index 0000000..bbb28a3
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuApp.inf
@@ -0,0 +1,73 @@
+## @file
+#
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BootManagerMenuApp
+ FILE_GUID = EEC25BDC-67F2-4D95-B1D5-F81B2039D11D
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = BootManagerMenuEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ BootManagerMenu.c
+ BootManagerMenu.h
+ BootManagerMenuStrings.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ HiiLib
+ DebugLib
+ UefiLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiApplicationEntryPoint
+ UefiBootManagerLib
+
+[Guids]
+
+[Protocols]
+ gEfiLoadedImageDevicePathProtocolGuid
+ gEfiBootLogoProtocolGuid
+
+[FeaturePcd]
diff --git a/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuStrings.uni b/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuStrings.uni
new file mode 100644
index 0000000..c767c41
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuStrings.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsBoot.c b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsBoot.c
new file mode 100644
index 0000000..3bdaa21
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsBoot.c
@@ -0,0 +1,2199 @@
+/** @file
+ BDS Lib functions which relate with create or process the boot option.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#include "InternalBdsLib.h"
+
+CONST UINT16 USB_LANG_ID = 0x0409; // English
+CHAR16 mUefiPrefix[] = L"UEFI ";
+
+EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION mEfiBootManagerRefreshLegacyBootOption = NULL;
+EFI_BOOT_MANAGER_LEGACY_BOOT mEfiBootManagerLegacyBoot = NULL;
+
+///
+/// This GUID is used for an EFI Variable that stores the front device pathes
+/// for a partial device path that starts with the HD node.
+///
+EFI_GUID mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x08, 0xe2, 0x0e, 0x90, 0x6c, 0xb6, 0xde } };
+EFI_GUID mAutoCreateBootOptionGuid = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } };
+
+/**
+ Get the image file buffer data and buffer size by its device path.
+
+ @param FilePath On input, a pointer to an allocated buffer containing the device
+ path of the file.
+ On output the pointer could be NULL when the function fails to
+ load the boot option, or could point to an allocated buffer containing
+ the device path of the file.
+ It could be updated by either short-form device path expanding,
+ or default boot file path appending.
+ Caller is responsible to free it when it's non-NULL.
+ @param FileSize A pointer to the size of the file buffer.
+
+ @retval NULL File is NULL, or FileSize is NULL. Or, the file can't be found.
+ @retval other The file buffer. The caller is responsible to free the memory.
+**/
+VOID *
+LoadEfiBootOption (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT UINTN *FileSize
+ );
+
+VOID
+EFIAPI
+EfiBootManagerRegisterLegacyBootSupport (
+ EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION RefreshLegacyBootOption,
+ EFI_BOOT_MANAGER_LEGACY_BOOT LegacyBoot
+ )
+{
+ mEfiBootManagerRefreshLegacyBootOption = RefreshLegacyBootOption;
+ mEfiBootManagerLegacyBoot = LegacyBoot;
+}
+
+VOID
+FreeAndSet (
+ VOID **Orig,
+ VOID *New
+ )
+{
+ FreePool (*Orig);
+ *Orig = New;
+}
+
+/**
+ Internal function to check if the input boot option is a valid EFI NV Boot####.
+
+ @param OptionToCheck Boot option to be checked.
+
+ @retval TRUE This boot option matches a valid EFI NV Boot####.
+ @retval FALSE If not.
+
+**/
+BOOLEAN
+BootOptionInVariable (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *OptionToCheck
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+ BOOLEAN Valid;
+ CHAR16 OptionName[sizeof ("Boot####")];
+
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionToCheck->OptionNumber);
+ Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ //
+ // If the Boot Option Number and Device Path matches, OptionToCheck matches a
+ // valid EFI NV Boot####.
+ //
+ Valid = FALSE;
+ if ((OptionToCheck->OptionNumber == BootOption.OptionNumber) &&
+ (CompareMem (OptionToCheck->FilePath, BootOption.FilePath, GetDevicePathSize (OptionToCheck->FilePath)) == 0))
+ {
+ Valid = TRUE;
+ }
+
+ EfiBootManagerFreeLoadOption (&BootOption);
+ return Valid;
+}
+
+/**
+ According to a file guild, check a Fv file device path is valid. If it is invalid,
+ try to return the valid device path.
+ FV address maybe changes for memory layout adjust from time to time, use this function
+ could promise the Fv file device path is right.
+
+ @param DevicePath The Fv file device path to be fixed up.
+
+ @retval DevicePath The DevicePath ponits to the valid FV file.
+ @retval !NULL The fixed device path.
+ @retval NULL Failed to fix up the DevicePath.
+**/
+VOID
+FixupMemmapFvFilePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_HANDLE FvHandle;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ UINTN Size;
+ EFI_FV_FILETYPE Type;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINT32 AuthenticationStatus;
+ UINTN FvHandleCount;
+ EFI_HANDLE *FvHandleBuffer;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+
+ Node = *DevicePath;
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &Fv);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Fv->ReadFile (
+ Fv,
+ EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),
+ NULL,
+ &Size,
+ &Type,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ FreeAndSet ((VOID **) DevicePath, NULL);
+ }
+ return;
+ }
+
+
+ Node = NextDevicePathNode (DevicePath);
+
+ //
+ // Firstly find the FV file in current FV
+ //
+ gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), Node);
+ FixupMemmapFvFilePath (&NewDevicePath);
+
+ if (NewDevicePath != NULL) {
+ FreeAndSet ((VOID **) DevicePath, NewDevicePath);
+ return;
+ }
+
+ //
+ // Secondly find the FV file in all other FVs
+ //
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &FvHandleCount,
+ &FvHandleBuffer
+ );
+ for (Index = 0; Index < FvHandleCount; Index++) {
+ if (FvHandleBuffer[Index] == LoadedImage->DeviceHandle) {
+ //
+ // Skip current FV
+ //
+ continue;
+ }
+ NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (FvHandleBuffer[Index]), Node);
+ FixupMemmapFvFilePath (&NewDevicePath);
+
+ if (NewDevicePath != NULL) {
+ FreeAndSet ((VOID **) DevicePath, NewDevicePath);
+ return;
+ }
+ }
+}
+
+/**
+ Check if it's of Fv file device path type.
+
+ The function doesn't garentee the device path points to existing Fv file.
+
+ @retval TRUE The device path is of Fv file device path type.
+ @retval FALSE The device path isn't of Fv file device path type.
+**/
+BOOLEAN
+IsMemmapFvFilePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *FileNode;
+
+ if ((DevicePathType (DevicePath) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (DevicePath) == HW_MEMMAP_DP)) {
+ FileNode = NextDevicePathNode (DevicePath);
+ if ((DevicePathType (FileNode) == MEDIA_DEVICE_PATH) && (DevicePathSubType (FileNode) == MEDIA_PIWG_FW_FILE_DP)) {
+ return IsDevicePathEnd (NextDevicePathNode (FileNode));
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Check whether a USB device match the specified USB Class device path. This
+ function follows "Load Option Processing" behavior in UEFI specification.
+
+ @param UsbIo USB I/O protocol associated with the USB device.
+ @param UsbClass The USB Class device path to match.
+
+ @retval TRUE The USB device match the USB Class device path.
+ @retval FALSE The USB device does not match the USB Class device path.
+
+**/
+BOOLEAN
+MatchUsbClass (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN USB_CLASS_DEVICE_PATH *UsbClass
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc;
+ EFI_USB_INTERFACE_DESCRIPTOR IfDesc;
+ UINT8 DeviceClass;
+ UINT8 DeviceSubClass;
+ UINT8 DeviceProtocol;
+
+ if ((DevicePathType (UsbClass) != MESSAGING_DEVICE_PATH) ||
+ (DevicePathSubType (UsbClass) != MSG_USB_CLASS_DP)){
+ return FALSE;
+ }
+
+ //
+ // Check Vendor Id and Product Id.
+ //
+ Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ if ((UsbClass->VendorId != 0xffff) &&
+ (UsbClass->VendorId != DevDesc.IdVendor)) {
+ return FALSE;
+ }
+
+ if ((UsbClass->ProductId != 0xffff) &&
+ (UsbClass->ProductId != DevDesc.IdProduct)) {
+ return FALSE;
+ }
+
+ DeviceClass = DevDesc.DeviceClass;
+ DeviceSubClass = DevDesc.DeviceSubClass;
+ DeviceProtocol = DevDesc.DeviceProtocol;
+ if (DeviceClass == 0) {
+ //
+ // If Class in Device Descriptor is set to 0, use the Class, SubClass and
+ // Protocol in Interface Descriptor instead.
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ DeviceClass = IfDesc.InterfaceClass;
+ DeviceSubClass = IfDesc.InterfaceSubClass;
+ DeviceProtocol = IfDesc.InterfaceProtocol;
+ }
+
+ //
+ // Check Class, SubClass and Protocol.
+ //
+ if ((UsbClass->DeviceClass != 0xff) &&
+ (UsbClass->DeviceClass != DeviceClass)) {
+ return FALSE;
+ }
+
+ if ((UsbClass->DeviceSubClass != 0xff) &&
+ (UsbClass->DeviceSubClass != DeviceSubClass)) {
+ return FALSE;
+ }
+
+ if ((UsbClass->DeviceProtocol != 0xff) &&
+ (UsbClass->DeviceProtocol != DeviceProtocol)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Eliminate the extra spaces in the Str to one space.
+**/
+VOID
+EliminateExtraSpaces (
+ IN CHAR16 *Str
+ )
+{
+ UINTN Index;
+ UINTN ActualIndex;
+
+ for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) {
+ if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] != L' '))) {
+ Str[ActualIndex++] = Str[Index];
+ }
+ }
+ Str[ActualIndex] = L'\0';
+}
+
+/**
+ Try to get the controller's ATA/ATAPI description.
+
+ @param Handle Controller handle.
+
+ @return The description string.
+**/
+CHAR16 *
+GetAtaAtapiDescription (
+ IN EFI_HANDLE Handle
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_DISK_INFO_PROTOCOL *DiskInfo;
+ UINT32 BufferSize;
+ EFI_ATAPI_IDENTIFY_DATA IdentifyData;
+ CHAR16 *Description;
+ UINTN Length;
+ CONST UINTN ModelNameLength = 40;
+ CONST UINTN SerialNumberLength = 20;
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiDiskInfoProtocolGuid,
+ (VOID **) &DiskInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Description = NULL;
+ BufferSize = sizeof (EFI_ATAPI_IDENTIFY_DATA);
+ Status = DiskInfo->Identify (
+ DiskInfo,
+ &IdentifyData,
+ &BufferSize
+ );
+ if (!EFI_ERROR (Status)) {
+ Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16));
+ ASSERT (Description != NULL);
+ for (Index = 0; Index + 1 < ModelNameLength; Index += 2) {
+ Description[Index] = (CHAR16) IdentifyData.ModelName[Index + 1];
+ Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index];
+ }
+
+ Length = Index;
+ Description[Length++] = L' ';
+
+ for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) {
+ Description[Length + Index] = (CHAR16) IdentifyData.SerialNo[Index + 1];
+ Description[Length + Index + 1] = (CHAR16) IdentifyData.SerialNo[Index];
+ }
+ Length += Index;
+ Description[Length++] = L'\0';
+ ASSERT (Length == ModelNameLength + SerialNumberLength + 2);
+
+ EliminateExtraSpaces (Description);
+ }
+
+ return Description;
+}
+
+/**
+ Try to get the controller's USB description.
+
+ @param Handle Controller handle.
+
+ @return The description string.
+**/
+CHAR16 *
+GetUsbDescription (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ CHAR16 NullChar;
+ CHAR16 *Manufacturer;
+ CHAR16 *Product;
+ CHAR16 *SerialNumber;
+ CHAR16 *Description;
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc;
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ NullChar = L'\0';
+
+ Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Status = UsbIo->UsbGetStringDescriptor (
+ UsbIo,
+ USB_LANG_ID,
+ DevDesc.StrManufacturer,
+ &Manufacturer
+ );
+ if (EFI_ERROR (Status)) {
+ Manufacturer = &NullChar;
+ }
+
+ Status = UsbIo->UsbGetStringDescriptor (
+ UsbIo,
+ USB_LANG_ID,
+ DevDesc.StrProduct,
+ &Product
+ );
+ if (EFI_ERROR (Status)) {
+ Product = &NullChar;
+ }
+
+ Status = UsbIo->UsbGetStringDescriptor (
+ UsbIo,
+ USB_LANG_ID,
+ DevDesc.StrSerialNumber,
+ &SerialNumber
+ );
+ if (EFI_ERROR (Status)) {
+ SerialNumber = &NullChar;
+ }
+
+ if ((Manufacturer == &NullChar) &&
+ (Product == &NullChar) &&
+ (SerialNumber == &NullChar)
+ ) {
+ return NULL;
+ }
+
+ Description = AllocateZeroPool (StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber));
+ ASSERT (Description != NULL);
+ StrCat (Description, Manufacturer);
+ StrCat (Description, L" ");
+
+ StrCat (Description, Product);
+ StrCat (Description, L" ");
+
+ StrCat (Description, SerialNumber);
+
+ if (Manufacturer != &NullChar) {
+ FreePool (Manufacturer);
+ }
+ if (Product != &NullChar) {
+ FreePool (Product);
+ }
+ if (SerialNumber != &NullChar) {
+ FreePool (SerialNumber);
+ }
+
+ EliminateExtraSpaces (Description);
+
+ return Description;
+}
+
+/**
+ Return the boot description for the controller based on the type.
+
+ @param Handle Controller handle.
+
+ @return The description string.
+**/
+CHAR16 *
+GetMiscDescription (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Description;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ switch (BootTypeFromDevicePath (DevicePathFromHandle (Handle))) {
+ case AcpiFloppyBoot:
+ Description = L"Floppy";
+ break;
+
+ case MessageAtapiBoot:
+ case MessageSataBoot:
+ Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Assume a removable SATA device should be the DVD/CD device
+ //
+ Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : L"Hard Drive";
+ break;
+
+ case MessageUsbBoot:
+ Description = L"USB Device";
+ break;
+
+ case MessageScsiBoot:
+ Description = L"SCSI Device";
+ break;
+
+ default:
+ Description = L"Misc Device";
+ break;
+ }
+
+ return AllocateCopyPool (StrSize (Description), Description);
+}
+
+GET_BOOT_DESCRIPTION mGetBootDescription[] = {
+ GetUsbDescription,
+ GetAtaAtapiDescription,
+ GetMiscDescription
+};
+
+/**
+ Check whether a USB device match the specified USB WWID device path. This
+ function follows "Load Option Processing" behavior in UEFI specification.
+
+ @param UsbIo USB I/O protocol associated with the USB device.
+ @param UsbWwid The USB WWID device path to match.
+
+ @retval TRUE The USB device match the USB WWID device path.
+ @retval FALSE The USB device does not match the USB WWID device path.
+
+**/
+BOOLEAN
+MatchUsbWwid (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN USB_WWID_DEVICE_PATH *UsbWwid
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc;
+ EFI_USB_INTERFACE_DESCRIPTOR IfDesc;
+ UINT16 *LangIdTable;
+ UINT16 TableSize;
+ UINT16 Index;
+ CHAR16 *CompareStr;
+ UINTN CompareLen;
+ CHAR16 *SerialNumberStr;
+ UINTN Length;
+
+ if ((DevicePathType (UsbWwid) != MESSAGING_DEVICE_PATH) ||
+ (DevicePathSubType (UsbWwid) != MSG_USB_WWID_DP)) {
+ return FALSE;
+ }
+
+ //
+ // Check Vendor Id and Product Id.
+ //
+ Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ if ((DevDesc.IdVendor != UsbWwid->VendorId) ||
+ (DevDesc.IdProduct != UsbWwid->ProductId)) {
+ return FALSE;
+ }
+
+ //
+ // Check Interface Number.
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ if (IfDesc.InterfaceNumber != UsbWwid->InterfaceNumber) {
+ return FALSE;
+ }
+
+ //
+ // Check Serial Number.
+ //
+ if (DevDesc.StrSerialNumber == 0) {
+ return FALSE;
+ }
+
+ //
+ // Get all supported languages.
+ //
+ TableSize = 0;
+ LangIdTable = NULL;
+ Status = UsbIo->UsbGetSupportedLanguages (UsbIo, &LangIdTable, &TableSize);
+ if (EFI_ERROR (Status) || (TableSize == 0) || (LangIdTable == NULL)) {
+ return FALSE;
+ }
+
+ //
+ // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.
+ //
+ CompareStr = (CHAR16 *) (UINTN) (UsbWwid + 1);
+ CompareLen = (DevicePathNodeLength (UsbWwid) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);
+ if (CompareStr[CompareLen - 1] == L'\0') {
+ CompareLen--;
+ }
+
+ //
+ // Compare serial number in each supported language.
+ //
+ for (Index = 0; Index < TableSize / sizeof (UINT16); Index++) {
+ SerialNumberStr = NULL;
+ Status = UsbIo->UsbGetStringDescriptor (
+ UsbIo,
+ LangIdTable[Index],
+ DevDesc.StrSerialNumber,
+ &SerialNumberStr
+ );
+ if (EFI_ERROR (Status) || (SerialNumberStr == NULL)) {
+ continue;
+ }
+
+ Length = StrLen (SerialNumberStr);
+ if ((Length >= CompareLen) &&
+ (CompareMem (SerialNumberStr + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0)) {
+ FreePool (SerialNumberStr);
+ return TRUE;
+ }
+
+ FreePool (SerialNumberStr);
+ }
+
+ return FALSE;
+}
+
+VOID
+PrintDp (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *ToText;
+ CHAR16 *DpStr;
+
+ Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &ToText);
+ ASSERT_EFI_ERROR (Status);
+
+ DpStr = ToText->ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ DEBUG ((EFI_D_INFO, "%s", DpStr));
+ FreePool (DpStr);
+}
+
+/**
+ Find a USB device which match the specified short-form device path start with
+ USB Class or USB WWID device path. If ParentDevicePath is NULL, this function
+ will search in all USB devices of the platform. If ParentDevicePath is not NULL,
+ this function will only search in its child devices.
+
+ @param DevicePath The device path that contains USB Class or USB WWID device path.
+ @param ParentDevicePathSize The length of the device path before the USB Class or
+ USB WWID device path.
+ @param UsbIoHandleCount A pointer to the count of the returned USB IO handles.
+
+ @retval NULL The matched USB IO handles cannot be found.
+ @retval other The matched USB IO handles.
+
+**/
+EFI_HANDLE *
+FindUsbDevice (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN UINTN ParentDevicePathSize,
+ OUT UINTN *UsbIoHandleCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *UsbIoHandles;
+ EFI_DEVICE_PATH_PROTOCOL *UsbIoDevicePath;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINTN Index;
+ UINTN UsbIoDevicePathSize;
+ BOOLEAN Matched;
+
+ ASSERT (UsbIoHandleCount != NULL);
+
+ //
+ // Get all UsbIo Handles.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiUsbIoProtocolGuid,
+ NULL,
+ UsbIoHandleCount,
+ &UsbIoHandles
+ );
+ if (EFI_ERROR (Status)) {
+ *UsbIoHandleCount = 0;
+ UsbIoHandles = NULL;
+ }
+
+ for (Index = 0; Index < *UsbIoHandleCount; ) {
+ //
+ // Get the Usb IO interface.
+ //
+ Status = gBS->HandleProtocol(
+ UsbIoHandles[Index],
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo
+ );
+ UsbIoDevicePath = DevicePathFromHandle (UsbIoHandles[Index]);
+ Matched = FALSE;
+ if (!EFI_ERROR (Status) && (UsbIoDevicePath != NULL)) {
+ UsbIoDevicePathSize = GetDevicePathSize (UsbIoDevicePath) - END_DEVICE_PATH_LENGTH;
+
+ //
+ // Compare starting part of UsbIoHandle's device path with ParentDevicePath.
+ //
+ if (CompareMem (UsbIoDevicePath, DevicePath, ParentDevicePathSize) == 0) {
+ if (MatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *) ((UINTN) DevicePath + ParentDevicePathSize)) ||
+ MatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *) ((UINTN) DevicePath + ParentDevicePathSize))) {
+ Matched = TRUE;
+ }
+ }
+ }
+
+ if (!Matched) {
+ (*UsbIoHandleCount) --;
+ CopyMem (&UsbIoHandles[Index], &UsbIoHandles[Index + 1], (*UsbIoHandleCount - Index) * sizeof (EFI_HANDLE));
+ } else {
+ Index++;
+ }
+ }
+
+ return UsbIoHandles;
+}
+
+/**
+ Expand USB Class or USB WWID device path node to be full device path of a USB
+ device in platform.
+
+ This function support following 4 cases:
+ 1) Boot Option device path starts with a USB Class or USB WWID device path,
+ and there is no Media FilePath device path in the end.
+ In this case, it will follow Removable Media Boot Behavior.
+ 2) Boot Option device path starts with a USB Class or USB WWID device path,
+ and ended with Media FilePath device path.
+ 3) Boot Option device path starts with a full device path to a USB Host Controller,
+ contains a USB Class or USB WWID device path node, while not ended with Media
+ FilePath device path. In this case, it will follow Removable Media Boot Behavior.
+ 4) Boot Option device path starts with a full device path to a USB Host Controller,
+ contains a USB Class or USB WWID device path node, and ended with Media
+ FilePath device path.
+
+ @param DevicePath On input, a pointer to an allocated buffer that contains the
+ file device path.
+ On output, a pointer to an reallocated buffer that contains
+ the expanded device path. It would point to NULL if the file
+ cannot be read.
+
+ @param FileSize A pointer to the file size.
+
+ @retval !NULL The file buffer.
+ @retval NULL The input device path doesn't point to a valid file.
+**/
+VOID *
+ExpandUsbShortFormDevicePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
+ OUT UINTN *FileSize
+ )
+{
+ UINTN ParentDevicePathSize;
+ EFI_DEVICE_PATH_PROTOCOL *ShortformNode;
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
+ EFI_HANDLE *UsbIoHandles;
+ UINTN UsbIoHandleCount;
+ UINTN Index;
+ VOID *FileBuffer;
+
+ //
+ // Search for USB Class or USB WWID device path node.
+ //
+ for ( ShortformNode = *DevicePath
+ ; !IsDevicePathEnd (ShortformNode)
+ ; ShortformNode = NextDevicePathNode (ShortformNode)
+ ) {
+ if ((DevicePathType (ShortformNode) == MESSAGING_DEVICE_PATH) &&
+ ((DevicePathSubType (ShortformNode) == MSG_USB_CLASS_DP) ||
+ (DevicePathSubType (ShortformNode) == MSG_USB_WWID_DP))) {
+ break;
+ }
+ }
+ ASSERT (!IsDevicePathEnd (ShortformNode));
+
+ FullDevicePath = NULL;
+ ParentDevicePathSize = (UINTN) ShortformNode - (UINTN) *DevicePath;
+ RemainingDevicePath = NextDevicePathNode (ShortformNode);
+ FileBuffer = NULL;
+ UsbIoHandles = FindUsbDevice (*DevicePath, ParentDevicePathSize, &UsbIoHandleCount);
+
+ for (Index = 0; Index < UsbIoHandleCount; Index++) {
+ FullDevicePath = AppendDevicePath (DevicePathFromHandle (UsbIoHandles[Index]), RemainingDevicePath);
+ DEBUG ((EFI_D_INFO, "[Bds] FullDp1[%d]:", Index)); DEBUG_CODE (PrintDp (FullDevicePath); ); DEBUG ((EFI_D_INFO, "\n"));
+ FileBuffer = LoadEfiBootOption (&FullDevicePath, FileSize);
+ if (FileBuffer != NULL) {
+ DEBUG ((EFI_D_INFO, "-->")); DEBUG_CODE (PrintDp (FullDevicePath); ); DEBUG ((EFI_D_INFO, FileBuffer != NULL ? " - Found\n" : "\n"));
+ break;
+ }
+ }
+
+ if (UsbIoHandles != NULL) {
+ FreePool (UsbIoHandles);
+ }
+
+ if (FileBuffer == NULL) {
+ //
+ // Boot Option device path starts with USB Class or USB WWID device path.
+ // For Boot Option device path which doesn't begin with the USB Class or
+ // USB WWID device path, it's not needed to connect again here.
+ //
+ if ((DevicePathType (*DevicePath) == MESSAGING_DEVICE_PATH) &&
+ ((DevicePathSubType (*DevicePath) == MSG_USB_CLASS_DP) ||
+ (DevicePathSubType (*DevicePath) == MSG_USB_WWID_DP))) {
+ EfiBootManagerConnectUsbShortFormDevicePath (*DevicePath);
+
+ UsbIoHandles = FindUsbDevice (*DevicePath, ParentDevicePathSize, &UsbIoHandleCount);
+ for (Index = 0; Index < UsbIoHandleCount; Index++) {
+ FullDevicePath = AppendDevicePath (DevicePathFromHandle (UsbIoHandles[Index]), RemainingDevicePath);
+ DEBUG ((EFI_D_INFO, "[Bds] FullDp2[%d]:", Index)); DEBUG_CODE (PrintDp (FullDevicePath); ); DEBUG ((EFI_D_INFO, "\n"));
+ FileBuffer = LoadEfiBootOption (&FullDevicePath, FileSize);
+ if (FileBuffer != NULL) {
+ DEBUG ((EFI_D_INFO, "-->")); DEBUG_CODE (PrintDp (FullDevicePath); ); DEBUG ((EFI_D_INFO, FileBuffer != NULL ? " - Found\n" : "\n"));
+ break;
+ }
+ }
+
+ if (UsbIoHandles != NULL) {
+ FreePool (UsbIoHandles);
+ }
+ }
+ }
+
+ FreeAndSet ((VOID **) DevicePath, FullDevicePath);
+ return FileBuffer;
+}
+
+/**
+ Expand a device path that starts with a hard drive media device path node to be a
+ full device path that includes the full hardware path to the device. We need
+ to do this so it can be booted. As an optimization the front match (the part point
+ to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable
+ so a connect all is not required on every boot. All successful history device path
+ which point to partition node (the front part) will be saved.
+
+ @param DevicePath On input, a pointer to an allocated buffer that contains the
+ file device path.
+ On output, a pointer to an reallocated buffer that contains
+ the expanded device path. It would point to NULL if the file
+ cannot be read.
+
+**/
+VOID
+ExpandPartitionShortFormDevicePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ EFI_STATUS Status;
+ UINTN BlockIoHandleCount;
+ EFI_HANDLE *BlockIoBuffer;
+ EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;
+ UINTN Index;
+ UINTN InstanceNum;
+ EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
+ UINTN CachedDevicePathSize;
+ BOOLEAN DeviceExist;
+ BOOLEAN NeedAdjust;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ UINTN Size;
+
+ FullDevicePath = NULL;
+ //
+ // Check if there is prestore 'HDDP' variable.
+ // If exist, search the front path which point to partition node in the variable instants.
+ // If fail to find or 'HDDP' not exist, reconnect all and search in all system
+ //
+ CachedDevicePath = EfiBootManagerGetVariableAndSize (
+ L"HDDP",
+ &mHdBootVariablePrivateGuid,
+ &CachedDevicePathSize
+ );
+
+ if (CachedDevicePath != NULL) {
+ TempNewDevicePath = CachedDevicePath;
+ DeviceExist = FALSE;
+ NeedAdjust = FALSE;
+ do {
+ //
+ // Check every instance of the variable
+ // First, check whether the instance contain the partition node, which is needed for distinguishing multi
+ // partial partition boot option. Second, check whether the instance could be connected.
+ //
+ Instance = GetNextDevicePathInstance (&TempNewDevicePath, &Size);
+ if (MatchPartitionDevicePathNode (Instance, (HARDDRIVE_DEVICE_PATH *) *DevicePath)) {
+ //
+ // Connect the device path instance, the device path point to hard drive media device path node
+ // e.g. ACPI() /PCI()/ATA()/Partition()
+ //
+ Status = EfiBootManagerConnectDevicePath (Instance, NULL);
+ if (!EFI_ERROR (Status)) {
+ DeviceExist = TRUE;
+ break;
+ }
+ }
+ //
+ // Come here means the first instance is not matched
+ //
+ NeedAdjust = TRUE;
+ FreePool(Instance);
+ } while (TempNewDevicePath != NULL);
+
+ if (DeviceExist) {
+ //
+ // Find the matched device path.
+ // Append the file path information from the boot option and return the fully expanded device path.
+ //
+ FullDevicePath = AppendDevicePath (Instance, NextDevicePathNode (*DevicePath));
+
+ //
+ // Adjust the 'HDDP' instances sequence if the matched one is not first one.
+ //
+ if (NeedAdjust) {
+ //
+ // First delete the matched instance.
+ //
+ TempNewDevicePath = CachedDevicePath;
+ CachedDevicePath = EfiBootManagerDelPartMatchInstance (CachedDevicePath, Instance);
+ FreePool (TempNewDevicePath);
+
+ //
+ // Second, append the remaining path after the matched instance
+ //
+ TempNewDevicePath = CachedDevicePath;
+ CachedDevicePath = AppendDevicePathInstance (Instance, CachedDevicePath );
+ FreePool (TempNewDevicePath);
+ //
+ // Save the matching Device Path so we don't need to do a connect all next time
+ //
+ Status = gRT->SetVariable (
+ L"HDDP",
+ &mHdBootVariablePrivateGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ GetDevicePathSize (CachedDevicePath),
+ CachedDevicePath
+ );
+ }
+
+ FreePool (Instance);
+ FreePool (CachedDevicePath);
+ FreePool (*DevicePath);
+ *DevicePath = FullDevicePath;
+ return;
+ }
+ }
+
+ //
+ // If we get here we fail to find or 'HDDP' not exist, and now we need
+ // to search all devices in the system for a matched partition
+ //
+ EfiBootManagerConnectAll ();
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
+ if (EFI_ERROR (Status)) {
+ BlockIoHandleCount = 0;
+ BlockIoBuffer = NULL;
+ }
+ //
+ // Loop through all the device handles that support the BLOCK_IO Protocol
+ //
+ for (Index = 0; Index < BlockIoHandleCount; Index++) {
+
+ Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);
+ if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {
+ continue;
+ }
+
+ if (MatchPartitionDevicePathNode (BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *) *DevicePath)) {
+ //
+ // Find the matched partition device path
+ //
+ FullDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (*DevicePath));
+
+ //
+ // Save the matched partition device path in 'HDDP' variable
+ //
+ if (CachedDevicePath != NULL) {
+ //
+ // Save the matched partition device path as first instance of 'HDDP' variable
+ //
+ if (EfiBootManagerMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) {
+ TempNewDevicePath = CachedDevicePath;
+ CachedDevicePath = EfiBootManagerDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath);
+ FreePool(TempNewDevicePath);
+
+ TempNewDevicePath = CachedDevicePath;
+ CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);
+ if (TempNewDevicePath != NULL) {
+ FreePool(TempNewDevicePath);
+ }
+ } else {
+ TempNewDevicePath = CachedDevicePath;
+ CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);
+ FreePool(TempNewDevicePath);
+ }
+ //
+ // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller
+ // If the user try to boot many OS in different HDs or partitions, in theory, the 'HDDP' variable maybe become larger and larger.
+ //
+ InstanceNum = 0;
+ ASSERT (CachedDevicePath != NULL);
+ TempNewDevicePath = CachedDevicePath;
+ while (!IsDevicePathEnd (TempNewDevicePath)) {
+ TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);
+ //
+ // Parse one instance
+ //
+ while (!IsDevicePathEndType (TempNewDevicePath)) {
+ TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);
+ }
+ InstanceNum++;
+ //
+ // If the CachedDevicePath variable contain too much instance, only remain 12 instances.
+ //
+ if (InstanceNum >= 12) {
+ SetDevicePathEndNode (TempNewDevicePath);
+ break;
+ }
+ }
+ } else {
+ CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);
+ }
+
+ //
+ // Save the matching Device Path so we don't need to do a connect all next time
+ //
+ Status = gRT->SetVariable (
+ L"HDDP",
+ &mHdBootVariablePrivateGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ GetDevicePathSize (CachedDevicePath),
+ CachedDevicePath
+ );
+
+ break;
+ }
+ }
+
+ if (CachedDevicePath != NULL) {
+ FreePool (CachedDevicePath);
+ }
+ if (BlockIoBuffer != NULL) {
+ FreePool (BlockIoBuffer);
+ }
+ FreeAndSet ((VOID **) DevicePath, FullDevicePath);
+}
+
+/**
+ Algorithm follows the UEFI Spec chapter 3.4 Boot Mechanisms.
+
+ @param DevicePath Device Path to a bootable device
+
+ @return The bootable media handle. If the media on the DevicePath is not bootable, NULL will return.
+
+**/
+EFI_HANDLE
+GetBootableDeviceHandle (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ VOID *Buffer;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ UINTN Size;
+ UINTN TempSize;
+ EFI_HANDLE ReturnHandle;
+ EFI_HANDLE *SimpleFileSystemHandles;
+ UINTN NumberSimpleFileSystemHandles;
+ UINTN Index;
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
+
+ ReturnHandle = NULL;
+ UpdatedDevicePath = DevicePath;
+
+ //
+ // Check whether the device is connected
+ //
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &UpdatedDevicePath, &Handle);
+ if (EFI_ERROR (Status)) {
+ //
+ // Skip the case that the boot option point to a simple file protocol which does not consume block Io protocol,
+ //
+ Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &UpdatedDevicePath, &Handle);
+ if (EFI_ERROR (Status)) {
+ //
+ // Fail to find the proper BlockIo and simple file protocol, maybe because device not present, we need to connect it firstly
+ //
+ UpdatedDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);
+ }
+ } else {
+ //
+ // For removable device boot option, its contained device path only point to the removable device handle,
+ // should make sure all its children handles (its child partion or media handles) are created and connected.
+ //
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);
+ //
+ // Get BlockIo protocol and check removable attribute
+ //
+ Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+ //
+ // Issue a dummy read to the device to check for media change.
+ // When the removable media is changed, any Block IO read/write will
+ // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is
+ // returned. After the Block IO protocol is reinstalled, subsequent
+ // Block IO read/write will success.
+ //
+ Buffer = AllocatePool (BlockIo->Media->BlockSize);
+ if (Buffer != NULL) {
+ BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ 0,
+ BlockIo->Media->BlockSize,
+ Buffer
+ );
+ FreePool(Buffer);
+ }
+ }
+
+ //
+ // Detect the the default boot file from removable Media
+ //
+ Size = GetDevicePathSize(DevicePath) - END_DEVICE_PATH_LENGTH;
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &NumberSimpleFileSystemHandles,
+ &SimpleFileSystemHandles
+ );
+ for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
+ //
+ // Get the device path size of SimpleFileSystem handle
+ //
+ TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
+ TempSize = GetDevicePathSize (TempDevicePath)- END_DEVICE_PATH_LENGTH;
+ //
+ // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path
+ //
+ if ((Size <= TempSize) && (CompareMem (TempDevicePath, DevicePath, Size) == 0)) {
+ //
+ // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media
+ // machinename is ia32, ia64, x64, ...
+ //
+ Hdr.Union = &HdrData;
+ Status = GetImageHeader (
+ SimpleFileSystemHandles[Index],
+ EFI_REMOVABLE_MEDIA_FILE_NAME,
+ &DosHeader,
+ Hdr
+ );
+ if (!EFI_ERROR (Status) && EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&
+ (Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)
+ ) {
+ ReturnHandle = SimpleFileSystemHandles[Index];
+ break;
+ }
+ }
+ }
+
+ if (SimpleFileSystemHandles != NULL) {
+ FreePool(SimpleFileSystemHandles);
+ }
+
+ return ReturnHandle;
+}
+
+/**
+ Get the image file buffer data and buffer size by its device path.
+
+ @param FilePath On input, a pointer to an allocated buffer that contains the
+ file device path.
+ On output the device path pointer could be modified to point to
+ a new allocated buffer that contains the full device path.
+ It could be caused by either short-form device path expanding,
+ or default boot file path appending.
+ @param FileSize A pointer to the size of the file buffer.
+
+ @retval NULL The file can't be found.
+ @retval other The file buffer. The caller is responsible to free memory.
+**/
+VOID *
+LoadEfiBootOption (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT UINTN *FileSize
+ )
+{
+ EFI_HANDLE Handle;
+ VOID *FileBuffer;
+ UINT32 AuthenticationStatus;
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+
+ ASSERT ((FilePath != NULL) && (*FilePath != NULL) && (FileSize != NULL));
+
+ EfiBootManagerConnectDevicePath (*FilePath, NULL);
+
+ *FileSize = 0;
+ FileBuffer = NULL;
+ //
+ // Expand the short-form device path to full device path
+ //
+ if (FeaturePcdGet (PcdShortformBootSupport)) {
+
+ if ((DevicePathType (*FilePath) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (*FilePath) == MEDIA_HARDDRIVE_DP)) {
+ //
+ // Expand the Harddrive device path
+ //
+ ExpandPartitionShortFormDevicePath (FilePath);
+ if (*FilePath == NULL) {
+ return NULL;
+ }
+
+ } else {
+ for (Node = *FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&
+ ((DevicePathSubType (Node) == MSG_USB_CLASS_DP) ||
+ (DevicePathSubType (Node) == MSG_USB_WWID_DP))) {
+ break;
+ }
+ }
+
+ if (!IsDevicePathEnd (Node)) {
+ //
+ // Expand the USB WWID/Class device path
+ //
+ FileBuffer = ExpandUsbShortFormDevicePath (FilePath, FileSize);
+ if (FileBuffer == NULL) {
+ return NULL;
+ }
+ }
+ }
+ }
+
+ //
+ // Fix up the boot option path if it points to a FV in memory map style of device path
+ //
+ if (IsMemmapFvFilePath (*FilePath)) {
+ FixupMemmapFvFilePath (FilePath);
+ if (*FilePath == NULL) {
+ return NULL;
+ }
+ }
+
+ if (FileBuffer == NULL) {
+ FileBuffer = GetFileBufferByFilePath (TRUE, *FilePath, FileSize, &AuthenticationStatus);
+ }
+
+ //
+ // If we didn't find an image directly, we need to try as if it is a removable device boot option
+ // and load the image according to the default boot behavior.
+ //
+ if (FileBuffer == NULL) {
+ //
+ // check if there is a bootable media could be found in this device path,
+ // and get the bootable media handle
+ //
+ Handle = GetBootableDeviceHandle (*FilePath);
+ if (Handle != NULL) {
+ //
+ // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from the media
+ // machinename is ia32, ia64, x64, ...
+ //
+ FreeAndSet ((VOID **) FilePath, FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME));
+ ASSERT (*FilePath != NULL);
+ FileBuffer = GetFileBufferByFilePath (TRUE, *FilePath, FileSize, &AuthenticationStatus);
+ }
+ }
+
+ if (FileBuffer == NULL) {
+ FreeAndSet ((VOID **) FilePath, NULL);
+ }
+
+ return FileBuffer;
+}
+
+/**
+ Attempt to boot the EFI boot option. This routine sets L"BootCurent" and
+ also signals the EFI ready to boot event. If the device path for the option
+ starts with a BBS device path a legacy boot is attempted via the registered
+ gLegacyBoot function. Short form device paths are also supported via this
+ rountine. A device path starting with MEDIA_HARDDRIVE_DP, MSG_USB_WWID_DP,
+ MSG_USB_CLASS_DP gets expaned out to find the first device that matches.
+ If the BootOption Device Path fails the removable media boot algorithm
+ is attempted (\EFI\BOOTIA32.EFI, \EFI\BOOTX64.EFI,... only one file type
+ is tried per processor type)
+
+ @param BootOption Boot Option to try and boot.
+ On return, BootOption->Status contains the boot status.
+ EFI_SUCCESS BootOption was booted
+ EFI_UNSUPPORTED A BBS device path was found with no valid callback
+ registered via EfiBootManagerInitialize().
+ EFI_NOT_FOUND The BootOption was not found on the system
+ !EFI_SUCCESS BootOption failed with this error status
+
+**/
+VOID
+EFIAPI
+EfiBootManagerBoot (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE ImageHandle;
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
+ UINT16 OptionNumber;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ VOID *FileBuffer;
+ UINTN FileSize;
+ EFI_BOOT_LOGO_PROTOCOL *BootLogo;
+ EFI_EVENT LegacyBootEvent;
+
+ if (BootOption == NULL) {
+ return;
+ }
+
+ if (BootOption->FilePath == NULL) {
+ BootOption->Status = EFI_INVALID_PARAMETER;
+ return;
+ }
+
+ //
+ // 1. Create Boot#### for a temporary boot (i.e. a boot by selected a EFI Shell using "Boot From File")
+ //
+ if (!BootOptionInVariable (BootOption) && (BootOption->OptionNumber == LoadOptionNumberUnassigned)) {
+ Status = GetFreeOptionNumber (L"BootOrder", &OptionNumber);
+ if (!EFI_ERROR (Status)) {
+ BootOption->OptionNumber = OptionNumber;
+ Status = EfiBootManagerLoadOptionToVariable (BootOption);
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[Bds] Failed to create Boot#### for a temporary boot - %r!\n", Status));
+ BootOption->Status = Status;
+ return ;
+ }
+ }
+
+ //
+ // 2. Update system variables: remove BootNext, set BootCurrent
+ //
+
+ //
+ // 2.1. Remove BootNext
+ // To prevent loops, the boot manager deletes BootNext before transferring control to the
+ // preselected boot option.
+ //
+ if (BootOption->BootNext) {
+ Status = gRT->SetVariable (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ 0,
+ 0,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // 2.2. Set BootCurrent
+ //
+ Status = gRT->SetVariable (
+ L"BootCurrent",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (UINT16),
+ &BootOption->OptionNumber
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Report Status Code to indicate ReadyToBoot event will be signalled
+ //
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT));
+
+ //
+ // 3. Signal the EVT_SIGNAL_READY_TO_BOOT event when we are about to load and execute
+ // the boot option.
+ //
+ EfiSignalEventReadyToBoot();
+
+ PERF_START_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) BootOption->OptionNumber);
+
+ //
+ // 4. Load EFI boot option to ImageHandle
+ //
+ ImageHandle = NULL;
+ if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {
+ Status = EFI_NOT_FOUND;
+ FilePath = DuplicateDevicePath (BootOption->FilePath);
+ FileBuffer = LoadEfiBootOption (&FilePath, &FileSize);
+ if (FileBuffer != NULL) {
+
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));
+
+ Status = gBS->LoadImage (
+ TRUE,
+ gImageHandle,
+ FilePath,
+ FileBuffer,
+ FileSize,
+ &ImageHandle
+ );
+ FreePool (FileBuffer);
+ FreePool (FilePath);
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Report Status Code to indicate that the failure to load boot option
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)
+ );
+ BootOption->Status = Status;
+ return;
+ }
+ }
+
+ PERF_CODE (
+ AllocateMemoryForPerformanceData ();
+ );
+
+ //
+ // 5. Adjust the different type memory page number just before booting
+ // and save the updated info into the variable for next boot to use
+ //
+ if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT) {
+ if (PcdGetBool (PcdResetOnMemoryTypeInformationChange)) {
+ SetMemoryTypeInformationVariable ();
+ }
+ }
+
+ DEBUG_CODE_BEGIN();
+ if (BootOption->Description == NULL) {
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));
+ } else {
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));
+ }
+ DEBUG_CODE_END();
+
+ //
+ // Check to see if we should legacy BOOT. If yes then do the legacy boot
+ // Write boot to OS performance data for Legacy boot
+ //
+ if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) && (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) {
+ if (mEfiBootManagerLegacyBoot != NULL) {
+ //
+ // Write boot to OS performance data for legacy boot.
+ //
+ PERF_CODE (
+ //
+ // Create an event to be signalled when Legacy Boot occurs to write performance data.
+ //
+ Status = EfiCreateEventLegacyBootEx(
+ TPL_NOTIFY,
+ WriteBootToOsPerformanceData,
+ NULL,
+ &LegacyBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ );
+
+ mEfiBootManagerLegacyBoot (BootOption);
+ } else {
+ BootOption->Status = EFI_UNSUPPORTED;
+ }
+
+ PERF_CODE (
+ FreeMemoryForPerformanceData ();
+ );
+ PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) BootOption->OptionNumber);
+ return;
+ }
+
+ //
+ // Provide the image with its load options
+ //
+ Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
+ ASSERT_EFI_ERROR (Status);
+
+ ImageInfo->LoadOptionsSize = BootOption->OptionalDataSize;
+ ImageInfo->LoadOptions = BootOption->OptionalData;
+
+ //
+ // Clean to NULL because the image is loaded directly from the firmwares boot manager.
+ //
+ ImageInfo->ParentHandle = NULL;
+
+ //
+ // Before calling the image, enable the Watchdog Timer for 5 minutes period
+ //
+ gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
+
+ //
+ // Write boot to OS performance data for UEFI boot
+ //
+ PERF_CODE (
+ WriteBootToOsPerformanceData (NULL, NULL);
+ );
+
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderStart));
+
+ Status = gBS->StartImage (ImageHandle, &BootOption->ExitDataSize, &BootOption->ExitData);
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));
+ BootOption->Status = Status;
+ if (EFI_ERROR (Status)) {
+ //
+ // Report Status Code to indicate that boot failure
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED)
+ );
+ }
+ PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) BootOption->OptionNumber);
+
+ //
+ // Clear the Watchdog Timer after the image returns
+ //
+ gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
+
+ //
+ // Set Logo status invalid after trying one boot option
+ //
+ BootLogo = NULL;
+ Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
+ if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
+ Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Clear Boot Current
+ //
+ gRT->SetVariable (
+ L"BootCurrent",
+ &gEfiGlobalVariableGuid,
+ 0,
+ 0,
+ NULL
+ );
+ PERF_CODE (
+ FreeMemoryForPerformanceData ();
+ );
+}
+
+
+/**
+ Check whether there is a instance in BlockIoDevicePath, which contain multi device path
+ instances, has the same partition node with HardDriveDevicePath device path
+
+ @param BlockIoDevicePath Multi device path instances which need to check
+ @param HardDriveDevicePath A device path which starts with a hard drive media
+ device path.
+
+ @retval TRUE There is a matched device path instance.
+ @retval FALSE There is no matched device path instance.
+
+**/
+BOOLEAN
+MatchPartitionDevicePathNode (
+ IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
+ )
+{
+ HARDDRIVE_DEVICE_PATH *TmpHdPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ BOOLEAN Match;
+ EFI_DEVICE_PATH_PROTOCOL *BlockIoHdDevicePathNode;
+
+ if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {
+ return FALSE;
+ }
+
+ //
+ // Make PreviousDevicePath == the device path node before the end node
+ //
+ DevicePath = BlockIoDevicePath;
+ BlockIoHdDevicePathNode = NULL;
+
+ //
+ // find the partition device path node
+ //
+ while (!IsDevicePathEnd (DevicePath)) {
+ if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)
+ ) {
+ BlockIoHdDevicePathNode = DevicePath;
+ break;
+ }
+
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+
+ if (BlockIoHdDevicePathNode == NULL) {
+ return FALSE;
+ }
+ //
+ // See if the harddrive device path in blockio matches the orig Hard Drive Node
+ //
+ TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePathNode;
+ Match = FALSE;
+
+ //
+ // Check for the match
+ //
+ if ((TmpHdPath->MBRType == HardDriveDevicePath->MBRType) &&
+ (TmpHdPath->SignatureType == HardDriveDevicePath->SignatureType)) {
+ switch (TmpHdPath->SignatureType) {
+ case SIGNATURE_TYPE_GUID:
+ Match = CompareGuid ((EFI_GUID *)TmpHdPath->Signature, (EFI_GUID *)HardDriveDevicePath->Signature);
+ break;
+ case SIGNATURE_TYPE_MBR:
+ Match = (BOOLEAN) (*((UINT32 *) (&(TmpHdPath->Signature[0]))) == ReadUnaligned32((UINT32 *)(&(HardDriveDevicePath->Signature[0]))));
+ break;
+ default:
+ Match = FALSE;
+ break;
+ }
+ }
+
+ return Match;
+}
+
+/**
+ Emuerate all possible bootable medias in the following order:
+ 1. Removable BlockIo - The boot option only points to the removable media
+ device, like USB key, DVD, Floppy etc.
+ 2. Fixed BlockIo - The boot option only points to a Fixed blockIo device,
+ like HardDisk.
+ 3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting
+ SimpleFileSystem Protocol, but not supporting BlockIo
+ protocol.
+ 4. LoadFile - The boot option points to the media supporting
+ LoadFile protocol.
+ Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior
+
+ TODO: Do we need to add EfiBootManagerConnectAll() in this function? Impact to SLE platform is big.
+**/
+EFI_BOOT_MANAGER_LOAD_OPTION *
+EFIAPI
+EfiBootManagerEnumerateBootOptions (
+ UINTN *BootOptionCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINT16 NonBlockNumber;
+ UINTN HandleCount;
+ EFI_HANDLE *Handles;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ UINTN Removable;
+ UINTN Index;
+ UINTN FunctionIndex;
+ CHAR16 *Temp;
+ CHAR16 *DescriptionPtr;
+ CHAR16 Description[30];
+
+ ASSERT (BootOptionCount != NULL);
+
+ *BootOptionCount = 0;
+ BootOptions = NULL;
+
+ //
+ // Parse removable block io followed by fixed block io
+ //
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+
+ for (Removable = 0; Removable < 2; Removable++) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Skip the logical partitions
+ //
+ if (BlkIo->Media->LogicalPartition) {
+ continue;
+ }
+
+ //
+ // Skip the fixed block io then the removable block io
+ //
+ if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) {
+ continue;
+ }
+
+ DescriptionPtr = NULL;
+ for (FunctionIndex = 0; FunctionIndex < sizeof (mGetBootDescription) / sizeof (mGetBootDescription[0]); FunctionIndex++) {
+ DescriptionPtr = mGetBootDescription[FunctionIndex] (Handles[Index]);
+ if (DescriptionPtr != NULL) {
+ break;
+ }
+ }
+
+ if (DescriptionPtr == NULL) {
+ continue;
+ }
+
+ //
+ // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix
+ //
+ Temp = AllocatePool (StrSize (DescriptionPtr) + sizeof (mUefiPrefix));
+ ASSERT (Temp != NULL);
+ StrCpy (Temp, mUefiPrefix);
+ StrCat (Temp, DescriptionPtr);
+ FreePool (DescriptionPtr);
+ DescriptionPtr = Temp;
+
+ BootOptions = ReallocatePool (
+ sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),
+ sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),
+ BootOptions
+ );
+ ASSERT (BootOptions != NULL);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ &BootOptions[(*BootOptionCount)++],
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ LOAD_OPTION_ACTIVE,
+ DescriptionPtr,
+ DevicePathFromHandle (Handles[Index]),
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ FreePool (DescriptionPtr);
+ }
+ }
+
+ if (HandleCount != 0) {
+ FreePool (Handles);
+ }
+
+ //
+ // Parse simple file system not based on block io
+ //
+ NonBlockNumber = 0;
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Skip if the file system handle supports a BlkIo protocol, which we've handled in above
+ //
+ continue;
+ }
+ UnicodeSPrint (Description, sizeof (Description), NonBlockNumber > 0 ? L"%s %d" : L"%s", L"UEFI Non-Block Boot Device", NonBlockNumber);
+
+ BootOptions = ReallocatePool (
+ sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),
+ sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),
+ BootOptions
+ );
+ ASSERT (BootOptions != NULL);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ &BootOptions[(*BootOptionCount)++],
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ LOAD_OPTION_ACTIVE,
+ Description,
+ DevicePathFromHandle (Handles[Index]),
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (HandleCount != 0) {
+ FreePool (Handles);
+ }
+
+ //
+ // Parse load file, assuming UEFI Network boot option
+ //
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiLoadFileProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+
+ UnicodeSPrint (Description, sizeof (Description), Index > 0 ? L"%s %d" : L"%s", L"UEFI Network", Index);
+
+ BootOptions = ReallocatePool (
+ sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),
+ sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),
+ BootOptions
+ );
+ ASSERT (BootOptions != NULL);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ &BootOptions[(*BootOptionCount)++],
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ LOAD_OPTION_ACTIVE,
+ Description,
+ DevicePathFromHandle (Handles[Index]),
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (HandleCount != 0) {
+ FreePool (Handles);
+ }
+
+ return BootOptions;
+}
+
+/**
+ The function enumerates all boot options, creates them and registers them in the BootOrder variable.
+**/
+VOID
+EFIAPI
+EfiBootManagerRefreshAllBootOption (
+ VOID
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *NvBootOptions;
+ UINTN NvBootOptionCount;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ UINTN Index;
+
+ //
+ // Optionally refresh the legacy boot option
+ //
+ if (mEfiBootManagerRefreshLegacyBootOption != NULL) {
+ mEfiBootManagerRefreshLegacyBootOption ();
+ }
+
+ BootOptions = EfiBootManagerEnumerateBootOptions (&BootOptionCount);
+ NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount, LoadOptionTypeBoot);
+
+ //
+ // Mark the boot option as added by bds by setting OptionalData to a special GUID
+ //
+ for (Index = 0; Index < BootOptionCount; Index++) {
+ BootOptions[Index].OptionalData = AllocateCopyPool (sizeof (EFI_GUID), &mAutoCreateBootOptionGuid);
+ BootOptions[Index].OptionalDataSize = sizeof (EFI_GUID);
+ }
+
+ //
+ // Remove invalid EFI boot options from NV
+ //
+ for (Index = 0; Index < NvBootOptionCount; Index++) {
+ if (((DevicePathType (NvBootOptions[Index].FilePath) != BBS_DEVICE_PATH) ||
+ (DevicePathSubType (NvBootOptions[Index].FilePath) != BBS_BBS_DP)
+ ) &&
+ (NvBootOptions[Index].OptionalDataSize == sizeof (EFI_GUID)) &&
+ CompareGuid ((EFI_GUID *) NvBootOptions[Index].OptionalData, &mAutoCreateBootOptionGuid)
+ ) {
+ //
+ // Only check those added by platform bds
+ // so that the boot options added by end-user or OS installer won't be deleted
+ //
+ if (EfiBootManagerFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == (UINTN) -1) {
+ EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+ }
+ }
+ }
+
+ //
+ // Add new EFI boot options to NV
+ //
+ for (Index = 0; Index < BootOptionCount; Index++) {
+ if (EfiBootManagerFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == (UINTN) -1) {
+ EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);
+ }
+ }
+
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+ EfiBootManagerFreeLoadOptions (NvBootOptions, NvBootOptionCount);
+}
+
+
+/**
+ For a bootable Device path, return its boot type.
+
+ @param DevicePath The bootable device Path to check
+
+ @retval AcpiFloppyBoot If given device path contains ACPI_DEVICE_PATH type device path node
+ which HID is floppy device.
+ @retval MessageAtapiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_ATAPI_DP.
+ @retval MessageSataBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_SATA_DP.
+ @retval MessageScsiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_SCSI_DP.
+ @retval MessageUsbBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_USB_DP.
+ @retval MessageNetworkBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_MAC_ADDR_DP, MSG_VLAN_DP,
+ MSG_IPv4_DP or MSG_IPv6_DP.
+ @retval UnsupportedBoot If tiven device path doesn't match the above condition, it's not supported.
+
+**/
+BOOT_TYPE
+BootTypeFromDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
+
+ ASSERT (DevicePath != NULL);
+
+ for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {
+ switch (DevicePathType (Node)) {
+
+ case ACPI_DEVICE_PATH:
+ if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == 0x0604) {
+ return AcpiFloppyBoot;
+ }
+ break;
+
+ case MESSAGING_DEVICE_PATH:
+ //
+ // Skip LUN device node
+ //
+ do {
+ LastDeviceNode = NextDevicePathNode (Node);
+ } while (DevicePathSubType(LastDeviceNode) == MSG_DEVICE_LOGICAL_UNIT_DP);
+
+ //
+ // if the device path not only point to driver device, it is not a messaging device path,
+ //
+ if (!IsDevicePathEndType (LastDeviceNode)) {
+ break;
+ }
+
+ switch (DevicePathSubType (Node)) {
+ case MSG_ATAPI_DP:
+ return MessageAtapiBoot;
+ break;
+
+ case MSG_SATA_DP:
+ return MessageSataBoot;
+ break;
+
+ case MSG_USB_DP:
+ return MessageUsbBoot;
+ break;
+
+ case MSG_SCSI_DP:
+ return MessageScsiBoot;
+ break;
+
+ case MSG_MAC_ADDR_DP:
+ case MSG_VLAN_DP:
+ case MSG_IPv4_DP:
+ case MSG_IPv6_DP:
+ return MessageNetworkBoot;
+ break;
+ }
+ }
+ }
+
+ return UnsupportedBoot;
+}
+
+/**
+ This function is called to create the boot option for the Boot Manager Menu.
+
+ The Boot Manager Menu is shown after successfully booting a boot option.
+ Assume the BootManagerMenuFile is in the same FV as the module links to this library.
+
+ @param OptionNumber Return the boot option number of the Boot Manager Menu
+
+ @retval EFI_SUCCESS Successfully register the Boot Manager Menu.
+ @retval Status Return status of gRT->SetVariable ().
+**/
+EFI_STATUS
+RegisterBootManagerMenu (
+ OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Description;
+ UINTN DescriptionLength;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+
+ Status = GetSectionFromFv (
+ PcdGetPtr (PcdBootManagerMenuFile),
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ (VOID **) &Description,
+ &DescriptionLength
+ );
+ if (EFI_ERROR (Status)) {
+ Description = NULL;
+ }
+
+ EfiInitializeFwVolDevicepathNode (&FileNode, PcdGetPtr (PcdBootManagerMenuFile));
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+ DevicePath = AppendDevicePathNode (
+ DevicePathFromHandle (LoadedImage->DeviceHandle),
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ ASSERT (DevicePath != NULL);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ BootOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ LOAD_OPTION_CATEGORY_APP,
+ (Description != NULL) ? Description : L"Boot Manager Menu",
+ DevicePath,
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (DevicePath);
+ if (Description != NULL) {
+ FreePool (Description);
+ }
+
+ DEBUG_CODE (
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+ ASSERT (EfiBootManagerFindLoadOption (BootOption, BootOptions, BootOptionCount) == -1);
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+ );
+
+ return EfiBootManagerAddLoadOptionVariable (BootOption, 0);
+}
+
+/**
+ Return the boot option corresponding to the Boot Manager Menu.
+ It may automatically create one if the boot option hasn't been created yet.
+
+ @param BootOption Return the Boot Manager Menu.
+
+ @retval EFI_SUCCESS The Boot Manager Menu is successfully returned.
+ @retval Status Return status of gRT->SetVariable ().
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerGetBootManagerMenu (
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ )
+{
+ EFI_STATUS Status;
+ UINTN BootOptionCount;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_HANDLE FvHandle;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+ for (Index = 0; Index < BootOptionCount; Index++) {
+ Node = BootOptions[Index].FilePath;
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);
+ if (!EFI_ERROR (Status)) {
+ if (CompareGuid (
+ EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),
+ PcdGetPtr (PcdBootManagerMenuFile)
+ )
+ ) {
+ Status = EfiBootManagerInitializeLoadOption (
+ BootOption,
+ BootOptions[Index].OptionNumber,
+ BootOptions[Index].OptionType,
+ BootOptions[Index].Attributes,
+ BootOptions[Index].Description,
+ BootOptions[Index].FilePath,
+ BootOptions[Index].OptionalData,
+ BootOptions[Index].OptionalDataSize
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+ }
+ }
+ }
+
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+
+ //
+ // Automatically create the Boot#### for Boot Manager Menu when not found.
+ //
+ if (Index == BootOptionCount) {
+ return RegisterBootManagerMenu (BootOption);
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsConnect.c b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsConnect.c
new file mode 100644
index 0000000..6e089d1
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsConnect.c
@@ -0,0 +1,365 @@
+/** @file
+ BDS Lib functions which relate with connect the device
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#include "InternalBdsLib.h"
+
+
+/**
+ This function will connect all the system driver to controller
+ first, and then special connect the default console, this make
+ sure all the system controller available and the platform default
+ console connected.
+
+**/
+VOID
+EFIAPI
+EfiBootManagerConnectAll (
+ VOID
+ )
+{
+ //
+ // Connect the platform console first
+ //
+ EfiBootManagerConnectAllDefaultConsoles ();
+
+ //
+ // Generic way to connect all the drivers
+ //
+ ConnectAllDriversToAllControllers ();
+
+ //
+ // Here we have the assumption that we have already had
+ // platform default console
+ //
+ EfiBootManagerConnectAllDefaultConsoles ();
+}
+
+/**
+ This function will create all handles associate with every device
+ path node. If the handle associate with one device path node can not
+ be created successfully, Dispatch service which load the missing drivers
+ is called according to input parameter, since in some cases no driver
+ dependency is assumed exist, so may need not to call this service.
+
+ @param DevicePathToConnect The device path which will be connected, it CANNOT be
+ a multi-instance device path
+ @param NeedDispatch Whether requires dispatch service during connection
+ @param MatchingHandle Return the controller handle closest to the DevicePathToConnect
+
+ @retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.
+ @retval EFI_NOT_FOUND Failed to create all handles associate with every device path node.
+ @retval EFI_SUCCESS Successful to create all handles associate with every device path node.
+
+**/
+EFI_STATUS
+ConnectDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
+ IN BOOLEAN NeedDispatch,
+ OUT EFI_HANDLE *MatchingHandle OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
+ EFI_HANDLE Handle;
+ EFI_HANDLE PreviousHandle;
+
+ if (DevicePathToConnect == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Start the real work of connect with RemainingDevicePath
+ //
+ PreviousHandle = NULL;
+ do {
+ //
+ // Find the handle that best matches the Device Path. If it is only a
+ // partial match the remaining part of the device path is returned in
+ // RemainingDevicePath.
+ //
+ RemainingDevicePath = DevicePathToConnect;
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
+ if (!EFI_ERROR (Status)) {
+ if (Handle == PreviousHandle) {
+ //
+ // If no forward progress is made try invoking the Dispatcher.
+ // A new FV may have been added to the system an new drivers
+ // may now be found.
+ // Status == EFI_SUCCESS means a driver was dispatched
+ // Status == EFI_NOT_FOUND means no new drivers were dispatched
+ //
+ if (NeedDispatch) {
+ Status = gDS->Dispatch ();
+ } else {
+ //
+ // Always return EFI_NOT_FOUND here
+ // to prevent dead loop when control handle is found but connection failded case
+ //
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+
+ if (!EFI_ERROR (Status)) {
+ PreviousHandle = Handle;
+ //
+ // Connect all drivers that apply to Handle and RemainingDevicePath,
+ // the Recursive flag is FALSE so only one level will be expanded.
+ //
+ // Do not check the connect status here, if the connect controller fail,
+ // then still give the chance to do dispatch, because partial
+ // RemainingDevicepath may be in the new FV
+ //
+ // 1. If the connect fail, RemainingDevicepath and handle will not
+ // change, so next time will do the dispatch, then dispatch's status
+ // will take effect
+ // 2. If the connect success, the RemainingDevicepath and handle will
+ // change, then avoid the dispatch, we have chance to continue the
+ // next connection
+ //
+ gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
+ if (MatchingHandle != NULL) {
+ *MatchingHandle = Handle;
+ }
+ }
+ }
+ //
+ // Loop until RemainingDevicePath is an empty device path
+ //
+ } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
+
+ ASSERT (EFI_ERROR (Status) || IsDevicePathEnd (RemainingDevicePath));
+
+ return Status;
+}
+
+/**
+ This function will create all handles associate with every device
+ path node. If the handle associate with one device path node can not
+ be created successfully, then still give chance to do the dispatch,
+ which load the missing drivers if possible.
+
+ @param DevicePathToConnect The device path which will be connected, it can be
+ a multi-instance device path
+ @param MatchingHandle Return the controller handle closest to the DevicePathToConnect
+
+ @retval EFI_SUCCESS All handles associate with every device path node
+ have been created
+ @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
+ @retval EFI_NOT_FOUND Create the handle associate with one device path
+ node failed
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerConnectDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
+ OUT EFI_HANDLE *MatchingHandle OPTIONAL
+ )
+{
+ return ConnectDevicePath (DevicePathToConnect, TRUE, MatchingHandle);
+}
+
+/**
+ This function will disconnect all current system handles.
+
+ gBS->DisconnectController() is invoked for each handle exists in system handle buffer.
+ If handle is a bus type handle, all childrens also are disconnected recursively by
+ gBS->DisconnectController().
+**/
+VOID
+EFIAPI
+EfiBootManagerDisconnectAll (
+ VOID
+ )
+{
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+
+ //
+ // Disconnect all
+ //
+ gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+}
+
+
+/**
+ Connect all the drivers to all the controllers.
+
+ This function makes sure all the current system drivers manage the correspoinding
+ controllers if have. And at the same time, makes sure all the system controllers
+ have driver to manage it if have.
+**/
+VOID
+ConnectAllDriversToAllControllers (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+
+ do {
+ //
+ // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
+ //
+ gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ //
+ // Check to see if it's possible to dispatch an more DXE drivers.
+ // The above code may have made new DXE drivers show up.
+ // If any new driver is dispatched (Status == EFI_SUCCESS) and we will try
+ // the connect again.
+ //
+ Status = gDS->Dispatch ();
+
+ } while (!EFI_ERROR (Status));
+}
+
+
+/**
+ Connect the specific Usb device which match the short form device path,
+ and whose bus is determined by Host Controller (Uhci or Ehci).
+
+ @param DevicePath A short-form device path that starts with the first
+ element being a USB WWID or a USB Class device
+ path
+
+ @return EFI_INVALID_PARAMETER DevicePath is NULL pointer.
+ DevicePath is not a USB device path.
+
+ @return EFI_SUCCESS Success to connect USB device
+ @return EFI_NOT_FOUND Fail to find handle for USB controller to connect.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerConnectUsbShortFormDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Class[3];
+ BOOLEAN AtLeastOneConnected;
+
+ //
+ // Check the passed in parameters
+ //
+ if (DevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
+ ((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Find the usb host controller firstly, then connect with the remaining device path
+ //
+ AtLeastOneConnected = FALSE;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Check whether the Pci device is the wanted usb host controller
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
+ if (!EFI_ERROR (Status) &&
+ ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
+ ) {
+ Status = gBS->ConnectController (
+ Handles[Index],
+ NULL,
+ DevicePath,
+ FALSE
+ );
+ if (!EFI_ERROR(Status)) {
+ AtLeastOneConnected = TRUE;
+ }
+ }
+ }
+ }
+
+ if (Handles != NULL) {
+ FreePool (Handles);
+ }
+ }
+
+ return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
+}
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsConsole.c b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsConsole.c
new file mode 100644
index 0000000..33a50c0
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsConsole.c
@@ -0,0 +1,827 @@
+/** @file
+ BDS Lib functions which contain all the code to connect console device
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#include "InternalBdsLib.h"
+
+CHAR16 *mConVarName[] = {
+ L"ConIn",
+ L"ConOut",
+ L"ErrOut",
+ L"ConInDev",
+ L"ConOutDev",
+ L"ErrOutDev"
+};
+
+/**
+ Search out the video controller.
+
+ @return PCI device path of the video controller.
+**/
+EFI_HANDLE
+GetVideoController (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN RootBridgeHandleCount;
+ EFI_HANDLE *RootBridgeHandleBuffer;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN RootBridgeIndex;
+ UINTN Index;
+ EFI_HANDLE VideoController;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // Make all the PCI_IO protocols show up
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &RootBridgeHandleCount,
+ &RootBridgeHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (RootBridgeHandleCount == 0)) {
+ return NULL;
+ }
+
+ VideoController = NULL;
+ for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
+ gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);
+
+ //
+ // Start to check all the pci io to find the first video controller
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Check for all video controller
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (!EFI_ERROR (Status) && IS_PCI_VGA (&Pci)) {
+ // TODO: use IS_PCI_DISPLAY??
+ VideoController = HandleBuffer[Index];
+ break;
+ }
+ }
+ }
+ FreePool (HandleBuffer);
+
+ if (VideoController != NULL) {
+ break;
+ }
+ }
+ FreePool (RootBridgeHandleBuffer);
+
+ return VideoController;
+}
+
+/**
+ Query all the children of VideoController and return the device paths of all the
+ children that support GraphicsOutput protocol.
+
+ @param VideoController PCI handle of video controller.
+
+ @return Device paths of all the children that support GraphicsOutput protocol.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+EfiBootManagerGetGopDevicePath (
+ IN EFI_HANDLE VideoController
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *GopPool;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
+ UINTN EntryCount;
+
+ ASSERT (VideoController != NULL);
+
+ GopPool = NULL;
+
+ Status = gBS->OpenProtocolInformation (
+ VideoController,
+ &gEfiPciIoProtocolGuid,
+ &OpenInfoBuffer,
+ &EntryCount
+ );
+ if (EFI_ERROR (Status)) {
+ EntryCount = 0;
+ }
+
+ for (Index = 0; Index < EntryCount; Index++) {
+ //
+ // Query all the children created by the GOP driver
+ //
+ if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ Status = gBS->OpenProtocol (
+ OpenInfoBuffer[Index].ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ChildDevicePath,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ OpenInfoBuffer[Index].ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Append the device path to GOP pool when there is GOP protocol installed.
+ //
+ TempDevicePath = GopPool;
+ GopPool = AppendDevicePathInstance (GopPool, ChildDevicePath);
+ if (TempDevicePath != NULL) {
+ FreePool (TempDevicePath);
+ }
+ }
+ }
+ }
+ }
+ FreePool (OpenInfoBuffer);
+
+ return GopPool;
+}
+
+/**
+ Find the platform active active video controller and connect it.
+
+ @retval EFI_NOT_FOUND There is no active video controller.
+ @retval EFI_SUCCESS The video controller is connected.
+**/
+EFI_STATUS
+ConnectVideoController (
+ VOID
+ )
+{
+ EFI_HANDLE VideoController;
+ EFI_DEVICE_PATH_PROTOCOL *Gop;
+
+ //
+ // Get the platform vga device
+ //
+ VideoController = GetVideoController ();
+
+ if (VideoController == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Try to connect the PCI device path, so that GOP dirver could start on this
+ // device and create child handles with GraphicsOutput Protocol installed
+ // on them, then we get device paths of these child handles and select
+ // them as possible console device.
+ //
+ gBS->ConnectController (VideoController, NULL, NULL, FALSE);
+
+ Gop = EfiBootManagerGetGopDevicePath (VideoController);
+ if (Gop == NULL) {
+ //
+ // Last chance - just try VGA controller
+ // Don't assume all VGA controller support GOP operation
+ //
+ DEBUG ((EFI_D_ERROR, "[Bds] GOP not found, try VGA device path!\n"));
+ Gop = DuplicateDevicePath (DevicePathFromHandle (VideoController));
+ if (Gop == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, Gop, NULL);
+ FreePool (Gop);
+
+ //
+ // Necessary for ConPlatform and ConSplitter driver to start up again after ConOut is updated.
+ //
+ return gBS->ConnectController (VideoController, NULL, NULL, TRUE);
+}
+
+/**
+ Check if the video controller is connected.
+
+ @retval TRUE The video controller is connected.
+ @retval FALSE The video controller isn't connected.
+**/
+BOOLEAN
+HasLocalDisplay (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleTextOutProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ while (HandleCount-- != 0) {
+ Status = gBS->OpenProtocol (
+ HandleBuffer[HandleCount],
+ &gEfiGraphicsOutputProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ HandleBuffer[HandleCount],
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Fill console handle in System Table if there are no valid console handle in.
+
+ Firstly, check the validation of console handle in System Table. If it is invalid,
+ update it by the first console device handle from EFI console variable.
+
+ @param VarName The name of the EFI console variable.
+ @param ConsoleGuid Specified Console protocol GUID.
+ @param ConsoleHandle On IN, console handle in System Table to be checked.
+ On OUT, new console hanlde in system table.
+ @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.
+ On OUT, new console protocol on new console hanlde in system table.
+
+ @retval TRUE System Table has been updated.
+ @retval FALSE System Table hasn't been updated.
+
+**/
+BOOLEAN
+UpdateSystemTableConsole (
+ IN CHAR16 *VarName,
+ IN EFI_GUID *ConsoleGuid,
+ IN OUT EFI_HANDLE *ConsoleHandle,
+ IN OUT VOID **ProtocolInterface
+ )
+{
+ EFI_STATUS Status;
+ UINTN DevicePathSize;
+ EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *VarConsole;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ VOID *Interface;
+ EFI_HANDLE NewHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
+
+ ASSERT (VarName != NULL);
+ ASSERT (ConsoleHandle != NULL);
+ ASSERT (ConsoleGuid != NULL);
+ ASSERT (ProtocolInterface != NULL);
+
+ if (*ConsoleHandle != NULL) {
+ Status = gBS->HandleProtocol (
+ *ConsoleHandle,
+ ConsoleGuid,
+ &Interface
+ );
+ if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {
+ //
+ // If ConsoleHandle is valid and console protocol on this handle also
+ // also matched, just return.
+ //
+ return FALSE;
+ }
+ }
+
+ //
+ // Get all possible consoles device path from EFI variable
+ //
+ VarConsole = EfiBootManagerGetVariableAndSize (
+ VarName,
+ &gEfiGlobalVariableGuid,
+ &DevicePathSize
+ );
+ if (VarConsole == NULL) {
+ //
+ // If there is no any console device, just return.
+ //
+ return FALSE;
+ }
+
+ FullDevicePath = VarConsole;
+
+ do {
+ //
+ // Check every instance of the console variable
+ //
+ Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);
+ if (Instance == NULL) {
+ DEBUG ((EFI_D_ERROR, "[Bds] No valid console instance is found for %s!\n", VarName));
+ // We should not ASSERT when all the console devices are removed.
+ // ASSERT_EFI_ERROR (EFI_NOT_FOUND);
+ FreePool (FullDevicePath);
+ return FALSE;
+ }
+
+ //
+ // Find console device handle by device path instance
+ //
+ Status = gBS->LocateDevicePath (
+ ConsoleGuid,
+ &Instance,
+ &NewHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get the console protocol on this console device handle
+ //
+ Status = gBS->HandleProtocol (
+ NewHandle,
+ ConsoleGuid,
+ &Interface
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update new console handle in System Table.
+ //
+ *ConsoleHandle = NewHandle;
+ *ProtocolInterface = Interface;
+ if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {
+ //
+ // If it is console out device, set console mode 80x25 if current mode is invalid.
+ //
+ TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface;
+ if (TextOut->Mode->Mode == -1) {
+ TextOut->SetMode (TextOut, 0);
+ }
+ }
+ return TRUE;
+ }
+ }
+
+ } while (Instance != NULL);
+
+ //
+ // No any available console devcie found.
+ //
+ return FALSE;
+}
+
+/**
+ This function update console variable based on ConVarName, it can
+ add or remove one specific console device path from the variable
+
+ @param ConVarName Console related variable name, ConIn, ConOut,
+ ErrOut.
+ @param CustomizedConDevicePath The console device path which will be added to
+ the console variable ConVarName, this parameter
+ can not be multi-instance.
+ @param ExclusiveDevicePath The console device path which will be removed
+ from the console variable ConVarName, this
+ parameter can not be multi-instance.
+
+ @retval EFI_UNSUPPORTED The added device path is same to the removed one.
+ @retval EFI_SUCCESS Success add or remove the device path from the
+ console variable.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerUpdateConsoleVariable (
+ IN CONSOLE_TYPE ConsoleType,
+ IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *VarConsole;
+ UINTN DevicePathSize;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
+
+ if (ConsoleType >= sizeof (mConVarName) / sizeof (mConVarName[0])) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ VarConsole = NULL;
+ DevicePathSize = 0;
+
+ //
+ // Notes: check the device path point, here should check
+ // with compare memory
+ //
+ if (CustomizedConDevicePath == ExclusiveDevicePath) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Delete the ExclusiveDevicePath from current default console
+ //
+ VarConsole = EfiBootManagerGetVariableAndSize (
+ mConVarName[ConsoleType],
+ &gEfiGlobalVariableGuid,
+ &DevicePathSize
+ );
+
+ //
+ // Initialize NewDevicePath
+ //
+ NewDevicePath = VarConsole;
+
+ //
+ // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
+ // In the end, NewDevicePath is the final device path.
+ //
+ if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
+ NewDevicePath = EfiBootManagerDelPartMatchInstance (VarConsole, ExclusiveDevicePath);
+ }
+ //
+ // Try to append customized device path to NewDevicePath.
+ //
+ if (CustomizedConDevicePath != NULL) {
+ if (!EfiBootManagerMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {
+ //
+ // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
+ //
+ NewDevicePath = EfiBootManagerDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);
+ //
+ // In the first check, the default console variable will be _ModuleEntryPoint,
+ // just append current customized device path
+ //
+ TempNewDevicePath = NewDevicePath;
+ NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);
+ if (TempNewDevicePath != NULL) {
+ FreePool(TempNewDevicePath);
+ }
+ }
+ }
+
+ //
+ // Finally, Update the variable of the default console by NewDevicePath
+ //
+ gRT->SetVariable (
+ mConVarName[ConsoleType],
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS
+ | EFI_VARIABLE_RUNTIME_ACCESS
+ | ((ConsoleType < ConInDev) ? EFI_VARIABLE_NON_VOLATILE : 0),
+ GetDevicePathSize (NewDevicePath),
+ NewDevicePath
+ );
+
+ if (VarConsole == NewDevicePath) {
+ if (VarConsole != NULL) {
+ FreePool(VarConsole);
+ }
+ } else {
+ if (VarConsole != NULL) {
+ FreePool(VarConsole);
+ }
+ if (NewDevicePath != NULL) {
+ FreePool(NewDevicePath);
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ Connect the console device base on the variable ConsoleType.
+
+ @param ConsoleType ConIn, ConOut or ErrOut.
+ @param NeedDispatch Whether need to dispatch.
+
+ @retval EFI_NOT_FOUND There is not any console devices connected
+ success
+ @retval EFI_SUCCESS Success connect any one instance of the console
+ device path base on the variable ConVarName.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerConnectConsoleVariable (
+ IN CONSOLE_TYPE ConsoleType,
+ IN BOOLEAN NeedDispatch
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;
+ UINTN VariableSize;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ EFI_DEVICE_PATH_PROTOCOL *Next;
+ EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
+ UINTN Size;
+ BOOLEAN DeviceExist;
+ EFI_HANDLE Handle;
+
+ if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ DeviceExist = FALSE;
+
+ //
+ // Check if the console variable exist
+ //
+ StartDevicePath = EfiBootManagerGetVariableAndSize (
+ mConVarName[ConsoleType],
+ &gEfiGlobalVariableGuid,
+ &VariableSize
+ );
+ if (StartDevicePath == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ CopyOfDevicePath = StartDevicePath;
+ do {
+ //
+ // Check every instance of the console variable
+ //
+ Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);
+ if (Instance == NULL) {
+ FreePool (StartDevicePath);
+ return EFI_UNSUPPORTED;
+ }
+
+ Next = Instance;
+ while (!IsDevicePathEndType (Next)) {
+ Next = NextDevicePathNode (Next);
+ }
+
+ SetDevicePathEndNode (Next);
+ //
+ // Connect the USB console
+ // USB console device path is a short-form device path that
+ // starts with the first element being a USB WWID
+ // or a USB Class device path
+ //
+ if (FeaturePcdGet (PcdShortformBootSupport) &&
+ (DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
+ ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP))
+ ) {
+ Status = EfiBootManagerConnectUsbShortFormDevicePath (Instance);
+ if (!EFI_ERROR (Status)) {
+ DeviceExist = TRUE;
+ }
+ } else {
+ //
+ // Connect the instance device path
+ //
+ Status = ConnectDevicePath (Instance, NeedDispatch, NULL);
+ if (EFI_ERROR (Status)) {
+ //
+ // Do not delete the instance from the console variable if the device path is of GOP type
+ // and the parent controller exists in the system
+ // This is to support the monitor hotplug in a headless boot
+ //
+ for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
+ if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
+ break;
+ }
+ }
+ if (!IsDevicePathEnd (Next)) {
+ Next = Instance;
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Next, &Handle);
+ if (!EFI_ERROR (Status) && (DevicePathType (Next) != ACPI_DEVICE_PATH || DevicePathSubType (Next) != ACPI_ADR_DP)) {
+ //
+ // We found the parent controller but it's not the direct parent of the ADR device path instance
+ // which indicates the video controller doesn't exist.
+ // If this happens, we need to delete the invalid device path from ConOut
+ //
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ } else {
+ DeviceExist = TRUE;
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Delete the instance from the console variable
+ //
+ EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance);
+ }
+ }
+ FreePool(Instance);
+ } while (CopyOfDevicePath != NULL);
+
+ FreePool (StartDevicePath);
+
+ if ((ConsoleType == ConOut) && FeaturePcdGet (PcdBdsFindDisplay) && !HasLocalDisplay ()) {
+ //
+ // Force to connect local video controller
+ // Backward compatible to old platforms which don't insert the GOP device path to ConOut
+ //
+ DEBUG ((EFI_D_ERROR, "[Bds] Local display isn't found, find & connect it automatically\n"));
+ Status = ConnectVideoController ();
+ if (!EFI_ERROR (Status)) {
+ DeviceExist = TRUE;
+ }
+ }
+
+ if (!DeviceExist) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function will search every input/output device in current system,
+ and make every input/output device as potential console device.
+**/
+VOID
+EFIAPI
+EfiBootManagerConnectAllConsoles (
+ VOID
+ )
+{
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+
+ Index = 0;
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ ConDevicePath = NULL;
+
+ //
+ // Update all the console variables
+ //
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleTextInProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ConDevicePath
+ );
+ EfiBootManagerUpdateConsoleVariable (ConIn, ConDevicePath, NULL);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool(HandleBuffer);
+ HandleBuffer = NULL;
+ }
+
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleTextOutProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ConDevicePath
+ );
+ EfiBootManagerUpdateConsoleVariable (ConOut, ConDevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, ConDevicePath, NULL);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool(HandleBuffer);
+ }
+
+ //
+ // Connect all console variables
+ //
+ EfiBootManagerConnectAllDefaultConsoles ();
+}
+
+
+/**
+ This function will connect all the console devices base on the console
+ device variable ConIn, ConOut and ErrOut.
+**/
+VOID
+EFIAPI
+EfiBootManagerConnectAllDefaultConsoles (
+ VOID
+ )
+{
+ BOOLEAN SystemTableUpdated;
+
+ EfiBootManagerConnectConsoleVariable (ConOut, TRUE);
+ PERF_START (NULL, "ConOutReady", "BDS", 1);
+ PERF_END (NULL, "ConOutReady", "BDS", 0);
+
+
+ EfiBootManagerConnectConsoleVariable (ConIn, TRUE);
+ PERF_START (NULL, "ConInReady", "BDS", 1);
+ PERF_END (NULL, "ConInReady", "BDS", 0);
+
+ //
+ // The _ModuleEntryPoint err out var is legal.
+ //
+ EfiBootManagerConnectConsoleVariable (ErrOut, TRUE);
+ PERF_START (NULL, "ErrOutReady", "BDS", 1);
+ PERF_END (NULL, "ErrOutReady", "BDS", 0);
+
+ SystemTableUpdated = FALSE;
+ //
+ // Fill console handles in System Table if no console device assignd.
+ //
+ if (UpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {
+ SystemTableUpdated = TRUE;
+ }
+ if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {
+ SystemTableUpdated = TRUE;
+ }
+ if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {
+ SystemTableUpdated = TRUE;
+ }
+
+ if (SystemTableUpdated) {
+ //
+ // Update the CRC32 in the EFI System Table header
+ //
+ gST->Hdr.CRC32 = 0;
+ gBS->CalculateCrc32 (
+ (UINT8 *) &gST->Hdr,
+ gST->Hdr.HeaderSize,
+ &gST->Hdr.CRC32
+ );
+ }
+}
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsHotkey.c b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsHotkey.c
new file mode 100644
index 0000000..e323347
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsHotkey.c
@@ -0,0 +1,997 @@
+/** @file
+ Hotkey BDS library function
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#include "InternalBdsLib.h"
+
+//
+// Lock for linked list
+//
+EFI_LOCK mHotkeyLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
+LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);
+EFI_EVENT mHotkeyTriggered = NULL;
+BOOLEAN mHotkeyServiceStarted = FALSE;
+//
+// Set OptionNumber as unassigned value to indicate the option isn't initialized
+//
+EFI_BOOT_MANAGER_LOAD_OPTION mHotkeyBootOption = {LoadOptionNumberUnassigned};
+
+EFI_BOOT_MANAGER_KEY_OPTION *mContinueKeyOption = NULL;
+VOID *mTxtInExRegistration = NULL;
+
+VOID
+EFIAPI
+BdsEmptyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ ) {
+}
+
+UINTN
+SizeOfKeyOption (
+ EFI_BOOT_MANAGER_KEY_OPTION *KeyOption
+ )
+{
+ return OFFSET_OF (EFI_BOOT_MANAGER_KEY_OPTION, Keys)
+ + KEY_OPTION_INPUT_KEY_COUNT (KeyOption) * sizeof (EFI_INPUT_KEY);
+}
+
+BOOLEAN
+BitSet (
+ IN UINT32 Value,
+ IN UINT32 Bit
+ )
+{
+ return (BOOLEAN) ((Value & Bit) != 0);
+}
+
+/**
+ Initialize the KeyData and Key[] in the EFI_BOOT_MANAGER_KEY_OPTION.
+**/
+EFI_STATUS
+InitializeKeyFields (
+ IN UINT32 Modifier,
+ IN VA_LIST Args,
+ OUT EFI_BOOT_MANAGER_KEY_OPTION *KeyOption
+ )
+{
+ EFI_INPUT_KEY *Key;
+ UINTN KeyCount;
+
+ if (KeyOption == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ KeyOption->KeyData = 0;
+
+ for (KeyCount = 0; KeyCount < sizeof (KeyOption->Keys) / sizeof (KeyOption->Keys[0]); KeyCount++) {
+ Key = VA_ARG (Args, EFI_INPUT_KEY *);
+ if (Key == NULL) {
+ break;
+ }
+ CopyMem (
+ &KeyOption->Keys[KeyCount],
+ Key,
+ sizeof (EFI_INPUT_KEY)
+ );
+ }
+ if (KeyCount == sizeof (KeyOption->Keys) / sizeof (KeyOption->Keys[0])) {
+ //
+ // Too many keys
+ //
+ return EFI_INVALID_PARAMETER;
+ } else {
+ KeyOption->KeyData |= KeyCount << LowBitSet32 (EFI_KEY_OPTION_INPUT_KEY_COUNT_MASK);
+ }
+
+ if ((Modifier & ~(EFI_BOOT_MANAGER_SHIFT_PRESSED
+ | EFI_BOOT_MANAGER_CONTROL_PRESSED
+ | EFI_BOOT_MANAGER_ALT_PRESSED
+ | EFI_BOOT_MANAGER_LOGO_PRESSED
+ | EFI_BOOT_MANAGER_MENU_KEY_PRESSED
+ | EFI_BOOT_MANAGER_SYS_REQ_PRESSED
+ )) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BitSet (Modifier, EFI_BOOT_MANAGER_SHIFT_PRESSED)) {
+ KeyOption->KeyData |= EFI_KEY_OPTION_SHIFT_PRESSED_MASK;
+ }
+ if (BitSet (Modifier, EFI_BOOT_MANAGER_CONTROL_PRESSED)) {
+ KeyOption->KeyData |= EFI_KEY_OPTION_CONTROL_PRESSED_MASK;
+ }
+ if (BitSet (Modifier, EFI_BOOT_MANAGER_ALT_PRESSED)) {
+ KeyOption->KeyData |= EFI_KEY_OPTION_ALT_PRESSED_MASK;
+ }
+ if (BitSet (Modifier, EFI_BOOT_MANAGER_LOGO_PRESSED)) {
+ KeyOption->KeyData |= EFI_KEY_OPTION_LOGO_PRESSED_MASK;
+ }
+ if (BitSet (Modifier, EFI_BOOT_MANAGER_MENU_KEY_PRESSED)) {
+ KeyOption->KeyData |= EFI_KEY_OPTION_MENU_PRESSED_MASK;
+ }
+ if (BitSet (Modifier, EFI_BOOT_MANAGER_SYS_REQ_PRESSED)) {
+ KeyOption->KeyData |= EFI_KEY_OPTION_SYS_REQ_PRESSED_MASK;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Try to boot the boot option triggered by hot key.
+**/
+VOID
+EFIAPI
+EfiBootManagerHotkeyBoot (
+ VOID
+ )
+{
+ if (mHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {
+ EfiBootManagerBoot (&mHotkeyBootOption);
+ EfiBootManagerFreeLoadOption (&mHotkeyBootOption);
+ mHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;
+ }
+}
+
+/**
+ This is the common notification function for HotKeys, it will be registered
+ with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.
+
+ @param KeyData A pointer to a buffer that is filled in with the keystroke
+ information for the key that was pressed.
+
+ @retval EFI_SUCCESS KeyData is successfully processed.
+ @return EFI_NOT_FOUND Fail to find boot option variable.
+**/
+EFI_STATUS
+EFIAPI
+HotkeyCallback (
+ IN EFI_KEY_DATA *KeyData
+)
+{
+ LIST_ENTRY *Link;
+ HOTKEY *Hotkey;
+ CHAR16 OptionName[sizeof ("Boot####")];
+ EFI_STATUS Status;
+ EFI_KEY_DATA *HotkeyData;
+
+ if (mHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {
+ //
+ // Do not process sequential hotkey stroke until the current boot option returns
+ //
+ return EFI_SUCCESS;
+ }
+
+ DEBUG ((EFI_D_INFO, "[Bds]HotkeyCallback: %04x:%04x\n", KeyData->Key.ScanCode, KeyData->Key.UnicodeChar));
+
+ EfiAcquireLock (&mHotkeyLock);
+ for ( Link = GetFirstNode (&mHotkeyList)
+ ; !IsNull (&mHotkeyList, Link)
+ ; Link = GetNextNode (&mHotkeyList, Link)
+ ) {
+ Hotkey = HOTKEY_FROM_LINK (Link);
+
+ //
+ // Is this Key Stroke we are waiting for?
+ //
+ ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
+ HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
+ if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
+ (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
+ (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ?
+ (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE
+ )
+ ) {
+
+ //
+ // Receive an expecting key stroke, transit to next waiting state
+ //
+ Hotkey->WaitingKey++;
+
+ if (Hotkey->WaitingKey == Hotkey->CodeCount) {
+ //
+ // Reset to initial waiting state
+ //
+ Hotkey->WaitingKey = 0;
+ //
+ // Received the whole key stroke sequence
+ //
+ Status = gBS->SignalEvent (mHotkeyTriggered);
+ ASSERT_EFI_ERROR (Status);
+
+ if (!Hotkey->IsContinue) {
+ //
+ // Launch its BootOption
+ //
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", Hotkey->BootOption);
+ Status = EfiBootManagerVariableToLoadOption (OptionName, &mHotkeyBootOption);
+ DEBUG ((EFI_D_INFO, "[Bds]Hotkey for %s pressed - %r\n", OptionName, Status));
+ if (EFI_ERROR (Status)) {
+ mHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;
+ }
+ } else {
+ DEBUG ((EFI_D_INFO, "[Bds]Continue key pressed!\n"));
+ }
+ }
+ } else {
+ //
+ // Receive an unexpected key stroke, reset to initial waiting state
+ //
+ Hotkey->WaitingKey = 0;
+ }
+
+ }
+ EfiReleaseLock (&mHotkeyLock);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UnregisterHotkeyNotify (
+ IN HOTKEY *Hotkey
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN KeyIndex;
+ EFI_HANDLE *Handles;
+ UINTN HandleCount;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;
+ VOID *NotifyHandle;
+
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleTextInputExProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
+ ASSERT_EFI_ERROR (Status);
+ for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {
+ Status = TxtInEx->RegisterKeyNotify (
+ TxtInEx,
+ &Hotkey->KeyData[KeyIndex],
+ HotkeyCallback,
+ &NotifyHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = TxtInEx->UnregisterKeyNotify (TxtInEx, NotifyHandle);
+ DEBUG ((EFI_D_INFO, "[Bds]UnregisterKeyNotify: %04x/%04x %r\n", Hotkey->KeyData[KeyIndex].Key.ScanCode, Hotkey->KeyData[KeyIndex].Key.UnicodeChar, Status));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RegisterHotkeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx,
+ IN HOTKEY *Hotkey
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ VOID *NotifyHandle;
+
+ for (Index = 0; Index < Hotkey->CodeCount; Index++) {
+ Status = TxtInEx->RegisterKeyNotify (
+ TxtInEx,
+ &Hotkey->KeyData[Index],
+ HotkeyCallback,
+ &NotifyHandle
+ );
+ DEBUG ((
+ EFI_D_INFO,
+ "[Bds]RegisterKeyNotify: %04x/%04x %08x/%02x %r\n",
+ Hotkey->KeyData[Index].Key.ScanCode,
+ Hotkey->KeyData[Index].Key.UnicodeChar,
+ Hotkey->KeyData[Index].KeyState.KeyShiftState,
+ Hotkey->KeyData[Index].KeyState.KeyToggleState,
+ Status
+ ));
+ if (EFI_ERROR (Status)) {
+ //
+ // some of the hotkey registry failed
+ // do not unregister all in case we have both CTRL-ALT-P and CTRL-ALT-P-R
+ //
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+GenerateKeyShiftState (
+ IN UINTN Depth,
+ IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption,
+ IN UINT32 KeyShiftState,
+ IN UINT32 *KeyShiftStates,
+ IN UINTN *KeyShiftStateCount
+ )
+{
+ switch (Depth) {
+ case 0:
+ if (KEY_OPTION_SHIFT_PRESSED (KeyOption)) {
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_SHIFT_PRESSED, KeyShiftStates, KeyShiftStateCount);
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_SHIFT_PRESSED, KeyShiftStates, KeyShiftStateCount);
+ } else {
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
+ }
+ break;
+
+ case 1:
+ if (KEY_OPTION_CONTROL_PRESSED (KeyOption)) {
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_CONTROL_PRESSED, KeyShiftStates, KeyShiftStateCount);
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_CONTROL_PRESSED, KeyShiftStates, KeyShiftStateCount);
+ } else {
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
+ }
+ break;
+
+ case 2:
+ if (KEY_OPTION_ALT_PRESSED (KeyOption)) {
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_ALT_PRESSED, KeyShiftStates, KeyShiftStateCount);
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_ALT_PRESSED, KeyShiftStates, KeyShiftStateCount);
+ } else {
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
+ }
+ break;
+ case 3:
+ if (KEY_OPTION_LOGO_PRESSED (KeyOption)) {
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_LOGO_PRESSED, KeyShiftStates, KeyShiftStateCount);
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_LOGO_PRESSED, KeyShiftStates, KeyShiftStateCount);
+ } else {
+ GenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
+ }
+ break;
+ case 4:
+ if (KEY_OPTION_MENU_PRESSED (KeyOption)) {
+ KeyShiftState |= EFI_MENU_KEY_PRESSED;
+ }
+ if (KEY_OPTION_SYS_REQ_PRESSED (KeyOption)) {
+ KeyShiftState |= EFI_SYS_REQ_PRESSED;
+ }
+ KeyShiftStates[*KeyShiftStateCount] = KeyShiftState;
+ (*KeyShiftStateCount)++;
+ break;
+ }
+}
+
+/**
+ Add it to hot key database, register it to existing TxtInEx.
+ new TxtInEx will be automatically registered with all the hot key in dababase
+**/
+EFI_STATUS
+ProcessKeyOption (
+ IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;
+ EFI_HANDLE *Handles;
+ UINTN HandleCount;
+ UINTN HandleIndex;
+ UINTN Index;
+ HOTKEY *Hotkey;
+ UINTN KeyIndex;
+ //
+ // 16 is enough to enumerate all the possible combination of LEFT_XXX and RIGHT_XXX
+ //
+ UINT32 KeyShiftStates[16];
+ UINTN KeyShiftStateCount;
+
+ KeyShiftStateCount = 0;
+ GenerateKeyShiftState (0, KeyOption, EFI_SHIFT_STATE_VALID, KeyShiftStates, &KeyShiftStateCount);
+ ASSERT (KeyShiftStateCount <= sizeof (KeyShiftStates) / sizeof (KeyShiftStates[0]));
+
+ EfiAcquireLock (&mHotkeyLock);
+
+ for (Index = 0; Index < KeyShiftStateCount; Index++) {
+ Hotkey = AllocateZeroPool (sizeof (HOTKEY));
+ ASSERT (Hotkey != NULL);
+
+ Hotkey->Signature = HOTKEY_SIGNATURE;
+ Hotkey->BootOption = KeyOption->BootOption;
+ Hotkey->IsContinue = (BOOLEAN) (KeyOption == mContinueKeyOption);
+ Hotkey->CodeCount = (UINT8) KEY_OPTION_INPUT_KEY_COUNT (KeyOption);
+
+ for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {
+ CopyMem (&Hotkey->KeyData[KeyIndex].Key, &KeyOption->Keys[KeyIndex], sizeof (EFI_INPUT_KEY));
+ Hotkey->KeyData[KeyIndex].KeyState.KeyShiftState = KeyShiftStates[Index];
+ }
+ InsertTailList (&mHotkeyList, &Hotkey->Link);
+
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleTextInputExProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
+ ASSERT_EFI_ERROR (Status);
+ RegisterHotkeyNotify (TxtInEx, Hotkey);
+ }
+ }
+
+ EfiReleaseLock (&mHotkeyLock);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Callback function for SimpleTextInEx protocol install events
+
+ @param Event the event that is signaled.
+ @param Context not used here.
+
+**/
+VOID
+EFIAPI
+TxtInExCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_HANDLE Handle;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;
+ LIST_ENTRY *Link;
+
+ while (TRUE) {
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mTxtInExRegistration,
+ &BufferSize,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If no more notification events exist
+ //
+ return ;
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID **) &TxtInEx
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register the hot key notification for the existing items in the list
+ //
+ EfiAcquireLock (&mHotkeyLock);
+ for (Link = GetFirstNode (&mHotkeyList); !IsNull (&mHotkeyList, Link); Link = GetNextNode (&mHotkeyList, Link)) {
+ RegisterHotkeyNotify (TxtInEx, HOTKEY_FROM_LINK (Link));
+ }
+ EfiReleaseLock (&mHotkeyLock);
+ }
+}
+
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeKeyOptions (
+ IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions,
+ IN UINTN KeyOptionCount
+ )
+{
+ if (KeyOptions != NULL) {
+ FreePool (KeyOptions);
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+}
+
+EFI_STATUS
+EFIAPI
+EfiBootManagerRegisterContinueKeyOption (
+ IN UINT32 Modifier,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MANAGER_KEY_OPTION KeyOption;
+ VA_LIST Args;
+
+ if (mContinueKeyOption != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+ VA_START (Args, Modifier);
+ Status = InitializeKeyFields (Modifier, Args, &KeyOption);
+ VA_END (Args);
+
+ if (!EFI_ERROR (Status)) {
+ mContinueKeyOption = AllocateCopyPool (sizeof (EFI_BOOT_MANAGER_KEY_OPTION), &KeyOption);
+ ASSERT (mContinueKeyOption != NULL);
+ if (mHotkeyServiceStarted) {
+ ProcessKeyOption (mContinueKeyOption);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Stop the hotkey processing.
+**/
+VOID
+EFIAPI
+StopHotkeyService (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ LIST_ENTRY *Link;
+ HOTKEY *Hotkey;
+
+ DEBUG ((EFI_D_INFO, "[Bds]Stop Hotkey Service!\n"));
+ gBS->CloseEvent (Event);
+
+ EfiAcquireLock (&mHotkeyLock);
+ for (Link = GetFirstNode (&mHotkeyList); !IsNull (&mHotkeyList, Link); ) {
+ Hotkey = HOTKEY_FROM_LINK (Link);
+ UnregisterHotkeyNotify (Hotkey);
+ Link = RemoveEntryList (Link);
+ FreePool (Hotkey);
+ }
+ EfiReleaseLock (&mHotkeyLock);
+}
+
+/**
+
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.
+
+ @retval EFI_SUCCESS Hotkey services successfully initialized.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerStartHotkeyService (
+ IN EFI_EVENT *HotkeyTriggered
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;
+ UINTN KeyOptionCount;
+ UINTN Index;
+ EFI_EVENT Event;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_CALLBACK,
+ BdsEmptyFunction,
+ NULL,
+ &mHotkeyTriggered
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (HotkeyTriggered != NULL) {
+ *HotkeyTriggered = mHotkeyTriggered;
+ }
+
+ KeyOptions = EfiBootManagerGetKeyOptions (&KeyOptionCount);
+ for (Index = 0; Index < KeyOptionCount; Index ++) {
+ ProcessKeyOption (&KeyOptions[Index]);
+ }
+ EfiBootManagerFreeKeyOptions (KeyOptions, KeyOptionCount);
+
+ if (mContinueKeyOption != NULL) {
+ ProcessKeyOption (mContinueKeyOption);
+ }
+
+ EfiCreateProtocolNotifyEvent (
+ &gEfiSimpleTextInputExProtocolGuid,
+ TPL_CALLBACK,
+ TxtInExCallback,
+ NULL,
+ &mTxtInExRegistration
+ );
+
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ StopHotkeyService,
+ NULL,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ mHotkeyServiceStarted = TRUE;
+ return Status;
+}
+
+BOOLEAN
+EFIAPI
+IsKeyOptionValid (
+ IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption
+)
+{
+ UINT16 OptionName[sizeof (L"Boot####")];
+ UINT8 *BootOption;
+ UINTN BootOptionSize;
+ UINT32 Crc;
+
+ //
+ // Check whether corresponding Boot Option exist
+ //
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", KeyOption->BootOption);
+ BootOption = EfiBootManagerGetVariableAndSize (
+ OptionName,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+
+ if (BootOption == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Check CRC for Boot Option
+ //
+ gBS->CalculateCrc32 (BootOption, BootOptionSize, &Crc);
+ FreePool (BootOption);
+
+ return (BOOLEAN) (KeyOption->BootOptionCrc == Crc);
+}
+
+BOOLEAN
+IsKeyOptionVariable (
+ CHAR16 *Name,
+ EFI_GUID *Guid,
+ UINT16 *OptionNumber
+ )
+{
+ UINTN Index;
+
+ if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) ||
+ (StrSize (Name) != sizeof (L"Key####")) ||
+ (StrnCmp (Name, L"Key", 3) != 0)
+ ) {
+ return FALSE;
+ }
+
+ *OptionNumber = 0;
+ for (Index = 3; Index < 7; Index++) {
+ if ((Name[Index] >= L'0') && (Name[Index] <= L'9')) {
+ *OptionNumber = *OptionNumber * 10 + Name[Index] - L'0';
+ } else if ((Name[Index] >= L'A') && (Name[Index] <= L'F')) {
+ *OptionNumber = *OptionNumber * 10 + Name[Index] - L'A';
+ } else {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+EFI_BOOT_MANAGER_KEY_OPTION *
+EFIAPI
+EfiBootManagerGetKeyOptions (
+ OUT UINTN *Count
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ CHAR16 *Name;
+ EFI_GUID Guid;
+ UINTN NameSize;
+ UINTN NewNameSize;
+ EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;
+ EFI_BOOT_MANAGER_KEY_OPTION *KeyOption;
+ UINT16 OptionNumber;
+
+ if (Count == NULL) {
+ return NULL;
+ }
+
+ *Count = 0;
+ KeyOptions = NULL;
+
+ NameSize = sizeof (CHAR16);
+ Name = AllocateZeroPool (NameSize);
+ ASSERT (Name != NULL);
+ while (TRUE) {
+ NewNameSize = NameSize;
+ Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Name = ReallocatePool (NameSize, NewNameSize, Name);
+ ASSERT (Name != NULL);
+ Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
+ NameSize = NewNameSize;
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ if (IsKeyOptionVariable (Name ,&Guid, &OptionNumber)) {
+ GetEfiGlobalVariable2 (Name, (VOID**) &KeyOption, NULL);
+ ASSERT (KeyOption != NULL);
+ if (IsKeyOptionValid (KeyOption)) {
+ KeyOptions = ReallocatePool (
+ *Count * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),
+ (*Count + 1) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),
+ KeyOptions
+ );
+ ASSERT (KeyOptions != NULL);
+ //
+ // Insert the key option in order
+ //
+ for (Index = 0; Index < *Count; Index++) {
+ if (OptionNumber < KeyOptions[Index].OptionNumber) {
+ break;
+ }
+ }
+ CopyMem (&KeyOptions[Index + 1], &KeyOptions[Index], (*Count - Index) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+ CopyMem (&KeyOptions[Index], KeyOption, SizeOfKeyOption (KeyOption));
+ KeyOptions[Index].OptionNumber = OptionNumber;
+ (*Count)++;
+ }
+ FreePool (KeyOption);
+ }
+ }
+
+ FreePool (Name);
+
+ return KeyOptions;
+}
+
+/**
+ Add the key option.
+ It adds the key option variable and the key option takes affect immediately.
+
+ @param AddedOption Return the added key option.
+ @param BootOptionNumber The boot option number for the key option.
+ @param Modifier Key shift state.
+ @param ... Parameter list of pointer of EFI_INPUT_KEY.
+
+ @retval EFI_SUCCESS The key option is added.
+ @retval EFI_ALREADY_STARTED The hot key is already used by certain key option.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerAddKeyOptionVariable (
+ OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption, OPTIONAL
+ IN UINT16 BootOptionNumber,
+ IN UINT32 Modifier,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Args;
+ VOID *BootOption;
+ UINTN BootOptionSize;
+ CHAR16 BootOptionName[sizeof (L"Boot####")];
+ EFI_BOOT_MANAGER_KEY_OPTION KeyOption;
+ EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;
+ UINTN KeyOptionCount;
+ UINTN Index;
+ UINTN KeyOptionNumber;
+ CHAR16 KeyOptionName[sizeof (L"Key####")];
+
+ UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", BootOptionNumber);
+ BootOption = EfiBootManagerGetVariableAndSize (
+ BootOptionName,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+
+ if (BootOption == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+ KeyOption.BootOption = BootOptionNumber;
+ Status = gBS->CalculateCrc32 (BootOption, BootOptionSize, &KeyOption.BootOptionCrc);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (BootOption);
+
+ VA_START (Args, Modifier);
+ Status = InitializeKeyFields (Modifier, Args, &KeyOption);
+ VA_END (Args);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ KeyOptionNumber = LoadOptionNumberUnassigned;
+ //
+ // Check if the hot key sequence was defined already
+ //
+ KeyOptions = EfiBootManagerGetKeyOptions (&KeyOptionCount);
+ for (Index = 0; Index < KeyOptionCount; Index++) {
+ if ((KeyOptions[Index].KeyData == KeyOption.KeyData) &&
+ (CompareMem (
+ KeyOptions[Index].Keys, KeyOption.Keys,
+ KEY_OPTION_INPUT_KEY_COUNT (&KeyOption) * sizeof (EFI_INPUT_KEY)
+ ) == 0)) {
+ break;
+ }
+
+ if ((KeyOptionNumber == LoadOptionNumberUnassigned) &&
+ (KeyOptions[Index].OptionNumber > Index)
+ ){
+ KeyOptionNumber = Index;
+ }
+ }
+ EfiBootManagerFreeKeyOptions (KeyOptions, KeyOptionCount);
+
+ if (Index < KeyOptionCount) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ if (KeyOptionNumber == LoadOptionNumberUnassigned) {
+ KeyOptionNumber = KeyOptionCount;
+ }
+
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumber);
+
+ Status = gRT->SetVariable (
+ KeyOptionName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ SizeOfKeyOption (&KeyOption),
+ &KeyOption
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Return the Key Option in case needed by caller
+ //
+ if (AddedOption != NULL) {
+ CopyMem (AddedOption, &KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+ }
+
+ //
+ // Register the newly added hot key
+ // Calling this function before EfiBootManagerStartHotkeyService doesn't
+ // need to call ProcessKeyOption
+ //
+ if (mHotkeyServiceStarted) {
+ ProcessKeyOption (&KeyOption);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Delete the Key Option variable and unregister the hot key
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerDeleteKeyOptionVariable (
+ IN EFI_BOOT_MANAGER_KEY_OPTION *DeletedOption, OPTIONAL
+ IN UINT32 Modifier,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ VA_LIST Args;
+ EFI_BOOT_MANAGER_KEY_OPTION KeyOption;
+ EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;
+ UINTN KeyOptionCount;
+ LIST_ENTRY *Link;
+ HOTKEY *Hotkey;
+ UINT32 ShiftState;
+ BOOLEAN Match;
+ CHAR16 KeyOptionName[sizeof (L"Key####")];
+
+ ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+ VA_START (Args, Modifier);
+ Status = InitializeKeyFields (Modifier, Args, &KeyOption);
+ VA_END (Args);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ EfiAcquireLock (&mHotkeyLock);
+ //
+ // Delete the key option from active hot key list
+ // Could have multiple entries when modifier isn't 0 because we map the ShiftPressed to RIGHT_SHIFT and RIGHT_SHIFT
+ //
+ for (Link = GetFirstNode (&mHotkeyList); !IsNull (&mHotkeyList, Link); ) {
+ Hotkey = HOTKEY_FROM_LINK (Link);
+ Match = (BOOLEAN) (Hotkey->CodeCount == KEY_OPTION_INPUT_KEY_COUNT (&KeyOption));
+
+ for (Index = 0; Match && (Index < Hotkey->CodeCount); Index++) {
+ ShiftState = Hotkey->KeyData[Index].KeyState.KeyShiftState;
+ if (
+ (BitSet (ShiftState, EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED) != KEY_OPTION_SHIFT_PRESSED (&KeyOption)) ||
+ (BitSet (ShiftState, EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED) != KEY_OPTION_CONTROL_PRESSED (&KeyOption)) ||
+ (BitSet (ShiftState, EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED) != KEY_OPTION_ALT_PRESSED (&KeyOption)) ||
+ (BitSet (ShiftState, EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED) != KEY_OPTION_LOGO_PRESSED (&KeyOption)) ||
+ (BitSet (ShiftState, EFI_MENU_KEY_PRESSED) != KEY_OPTION_MENU_PRESSED (&KeyOption)) ||
+ (BitSet (ShiftState, EFI_SYS_REQ_PRESSED) != KEY_OPTION_SYS_REQ_PRESSED (&KeyOption)) ||
+ (CompareMem (&Hotkey->KeyData[Index].Key, &KeyOption.Keys[Index], sizeof (EFI_INPUT_KEY)) != 0)
+ ) {
+ //
+ // Break when any field doesn't match
+ //
+ Match = FALSE;
+ break;
+ }
+ }
+
+ if (Match) {
+ Link = RemoveEntryList (Link);
+ FreePool (Hotkey);
+ } else {
+ Link = GetNextNode (&mHotkeyList, Link);
+ }
+ }
+
+ //
+ // Delete the key option from the variable
+ //
+ Status = EFI_NOT_FOUND;
+ KeyOptions = EfiBootManagerGetKeyOptions (&KeyOptionCount);
+ for (Index = 0; Index < KeyOptionCount; Index++) {
+ if ((KeyOptions[Index].KeyData == KeyOption.KeyData) &&
+ (CompareMem (
+ KeyOptions[Index].Keys, KeyOption.Keys,
+ KEY_OPTION_INPUT_KEY_COUNT (&KeyOption)* sizeof (EFI_INPUT_KEY)) == 0)
+ ) {
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptions[Index].OptionNumber);
+ Status = gRT->SetVariable (
+ KeyOptionName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+ //
+ // Return the deleted key option in case needed by caller
+ //
+ if (DeletedOption != NULL) {
+ CopyMem (DeletedOption, &KeyOptions[Index], sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+ }
+ break;
+ }
+ }
+ EfiBootManagerFreeKeyOptions (KeyOptions, KeyOptionCount);
+
+ EfiReleaseLock (&mHotkeyLock);
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsLoadOption.c b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsLoadOption.c
new file mode 100644
index 0000000..a1caea5
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsLoadOption.c
@@ -0,0 +1,1003 @@
+/** @file
+ Misc BDS library function
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#include "InternalBdsLib.h"
+
+/**
+ Get the Option Number that wasn't used.
+
+ @param OrderVariableName Could be L"BootOrder" or L"DriverOrder".
+ @param FreeOptionNumber To receive the minimal free option number.
+
+ @retval EFI_SUCCESS The option number is found
+ @retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
+ @retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
+
+**/
+EFI_STATUS
+GetFreeOptionNumber (
+ IN CHAR16 *OrderVariableName,
+ OUT UINT16 *FreeOptionNumber
+ )
+{
+
+ UINTN OptionNumber;
+ UINTN Index;
+ UINT16 *OptionOrder;
+ UINTN OptionOrderSize;
+ UINT16 *BootNext;
+
+ if (FreeOptionNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OptionOrder = EfiBootManagerGetVariableAndSize (
+ OrderVariableName,
+ &gEfiGlobalVariableGuid,
+ &OptionOrderSize
+ );
+
+ BootNext = NULL;
+ if (*OrderVariableName == L'B') {
+ GetEfiGlobalVariable2 (L"BootNext", (VOID**)&BootNext, NULL);
+ }
+
+ for (OptionNumber = 0;
+ OptionNumber < OptionOrderSize / sizeof (UINT16)
+ + ((BootNext != NULL) ? 1 : 0);
+ OptionNumber++
+ ) {
+ //
+ // Search in OptionOrder whether the OptionNumber exists
+ //
+ for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
+ if (OptionNumber == OptionOrder[Index]) {
+ break;
+ }
+ }
+
+ //
+ // We didn't find it in the ****Order array and it doesn't equal to BootNext
+ // Otherwise, OptionNumber equals to OptionOrderSize / sizeof (UINT16) + 1
+ //
+ if ((Index == OptionOrderSize / sizeof (UINT16)) &&
+ ((BootNext == NULL) || (OptionNumber != *BootNext))
+ ) {
+ break;
+ }
+ }
+ if (OptionOrder != NULL) {
+ FreePool (OptionOrder);
+ }
+
+ if (BootNext != NULL) {
+ FreePool (BootNext);
+ }
+
+ //
+ // When BootOrder & BootNext conver all numbers in the range [0 ... 0xffff],
+ // OptionNumber equals to 0x10000 which is not valid.
+ //
+ ASSERT (OptionNumber <= 0x10000);
+ if (OptionNumber == 0x10000) {
+ return EFI_OUT_OF_RESOURCES;
+ } else {
+ *FreeOptionNumber = (UINT16) OptionNumber;
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ Create the Boot#### or Driver#### variable from the load option.
+
+ @param LoadOption Pointer to the load option.
+
+ @retval EFI_SUCCESS The variable was created.
+ @retval Others Error status returned by RT->SetVariable.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerLoadOptionToVariable (
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Option
+ )
+{
+ UINTN VariableSize;
+ UINT8 *Variable;
+ UINT8 *Ptr;
+ CHAR16 OptionName[sizeof ("Driver####")];
+ CHAR16 *Description;
+ CHAR16 NullChar;
+
+ if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||
+ (Option->FilePath == NULL) ||
+ (Option->OptionType >= LoadOptionTypeMax)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Convert NULL description to empty description
+ //
+ NullChar = L'\0';
+ Description = Option->Description;
+ if (Description == NULL) {
+ Description = &NullChar;
+ }
+
+ /*
+ UINT32 Attributes;
+ UINT16 FilePathListLength;
+ CHAR16 Description[];
+ EFI_DEVICE_PATH_PROTOCOL FilePathList[];
+ UINT8 OptionalData[];
+TODO: FilePathList[] IS:
+A packed array of UEFI device paths. The first element of the
+array is a device path that describes the device and location of the
+Image for this load option. The FilePathList[0] is specific
+to the device type. Other device paths may optionally exist in the
+FilePathList, but their usage is OSV specific. Each element
+in the array is variable length, and ends at the device path end
+structure.
+ */
+ VariableSize = sizeof (Option->Attributes)
+ + sizeof (UINT16)
+ + StrSize (Description)
+ + GetDevicePathSize (Option->FilePath)
+ + Option->OptionalDataSize;
+
+ Variable = AllocatePool (VariableSize);
+ ASSERT (Variable != NULL);
+
+ Ptr = Variable;
+ *(UINT32 *) Ptr = Option->Attributes;
+ Ptr += sizeof (Option->Attributes);
+ *(UINT16 *) Ptr = (UINT16) GetDevicePathSize (Option->FilePath);
+ Ptr += sizeof (UINT16);
+ CopyMem (Ptr, Description, StrSize (Description));
+ Ptr += StrSize (Description);
+ CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath));
+ Ptr += GetDevicePathSize (Option->FilePath);
+ CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize);
+
+ UnicodeSPrint (
+ OptionName,
+ sizeof (OptionName),
+ (Option->OptionType == LoadOptionTypeBoot) ? L"Boot%04x" : L"Driver%04x",
+ Option->OptionNumber
+ );
+
+ return gRT->SetVariable (
+ OptionName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS
+ | EFI_VARIABLE_RUNTIME_ACCESS
+ | EFI_VARIABLE_NON_VOLATILE,
+ VariableSize,
+ Variable
+ );
+}
+
+/**
+ This function will register the new boot#### or driver#### option.
+ After the boot#### or driver#### updated, the BootOrder or DriverOrder will also be updated.
+
+ @param Option Pointer to load option to add.
+ @param Position Position of the new load option to put in the ****Order variable.
+
+ @retval EFI_SUCCESS The boot#### or driver#### have been successfully registered.
+ @retval EFI_INVALID_PARAMETER The option number exceeds 0xFFFF.
+ @retval EFI_ALREADY_STARTED The option number of Option is being used already.
+ Note: this API only adds new load option, no replacement support.
+ @retval EFI_OUT_OF_RESOURCES There is no free option number that can be used when the
+ option number specified in the Option is LoadOptionNumberUnassigned.
+ @retval EFI_STATUS Return the status of gRT->SetVariable ().
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerAddLoadOptionVariable (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
+ IN UINTN Position
+ )
+{
+ EFI_STATUS Status;
+ UINT16 OptionNumber;
+
+ if (Option == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the free option number if the option number is unassigned
+ //
+ if (Option->OptionNumber == LoadOptionNumberUnassigned) {
+ Status = GetFreeOptionNumber (
+ Option->OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
+ &OptionNumber
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Option->OptionNumber = OptionNumber;
+ }
+
+ if (Option->OptionNumber >= LoadOptionNumberMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AddOptionNumberToOrderVariable (
+ Option->OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
+ (UINT16) Option->OptionNumber,
+ Position
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Save the Boot#### or Driver#### variable
+ //
+ Status = EfiBootManagerLoadOptionToVariable (Option);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AddOptionNumberToOrderVariable (
+ IN CHAR16 *OrderVariableName,
+ IN UINT16 OptionNumber,
+ IN UINTN Position
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINT16 *OptionOrder;
+ UINT16 *NewOptionOrder;
+ UINTN OptionOrderSize;
+ //
+ // Update the option order variable
+ //
+ OptionOrder = EfiBootManagerGetVariableAndSize (
+ OrderVariableName,
+ &gEfiGlobalVariableGuid,
+ &OptionOrderSize
+ );
+
+ Status = EFI_SUCCESS;
+ for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
+ if (OptionOrder[Index] == OptionNumber) {
+ Status = EFI_ALREADY_STARTED;
+ break;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Position = MIN (Position, OptionOrderSize / sizeof (UINT16));
+
+ NewOptionOrder = AllocatePool (OptionOrderSize + sizeof (UINT16));
+ ASSERT (NewOptionOrder != NULL);
+ if (OptionOrderSize != 0) {
+ CopyMem (NewOptionOrder, OptionOrder, Position * sizeof (UINT16));
+ CopyMem (&NewOptionOrder[Position + 1], &OptionOrder[Position], OptionOrderSize - Position * sizeof (UINT16));
+ }
+ NewOptionOrder[Position] = OptionNumber;
+
+ Status = gRT->SetVariable (
+ OrderVariableName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ OptionOrderSize + sizeof (UINT16),
+ NewOptionOrder
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (NewOptionOrder);
+ }
+
+ if (OptionOrder != NULL) {
+ FreePool (OptionOrder);
+ }
+
+ return Status;
+}
+
+/**
+ Sort the load option. The DriverOrder or BootOrder will be re-created to
+ reflect the new order.
+
+ @param OptionType Load option type
+ @param Comparator The comparator
+**/
+VOID
+EFIAPI
+EfiBootManagerSortLoadOptionVariable (
+ EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
+ EFI_BOOT_MANAGER_LOAD_OPTION_COMPARATOR Comparator
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION TempOption;
+ UINTN LoadOptionCount;
+ UINTN IndexI;
+ UINTN IndexJ;
+ UINT16 *OptionOrder;
+ UINTN Start;
+
+ LoadOption = EfiBootManagerGetLoadOptions (&LoadOptionCount, OptionType);
+ Start = 0;
+
+ //
+ // Always put the BootNext as the first
+ //
+ if ((LoadOptionCount > 0) && LoadOption[0].BootNext) {
+ Start = 1;
+ }
+
+ //
+ // Insertion sort algorithm
+ //
+ for (IndexI = Start + 1; IndexI < LoadOptionCount; IndexI++) {
+
+ //
+ // for IndexI, find a proper position in [Start .. IndexI)
+ //
+ for (IndexJ = Start; IndexJ < IndexI; IndexJ++) {
+ if (Comparator (&LoadOption[IndexI], &LoadOption[IndexJ])) {
+ CopyMem (&TempOption, &LoadOption[IndexI], sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+ CopyMem (&LoadOption[IndexJ + 1], &LoadOption[IndexJ], (IndexI - IndexJ) * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+ CopyMem (&LoadOption[IndexJ], &TempOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+ break;
+ }
+ }
+ }
+
+ //
+ // Create new ****Order variable
+ //
+ OptionOrder = AllocatePool ((LoadOptionCount - Start) * sizeof (UINT16));
+ ASSERT (OptionOrder != NULL);
+ for (IndexI = Start; IndexI < LoadOptionCount; IndexI++) {
+ OptionOrder[IndexI - Start] = (UINT16) LoadOption[IndexI].OptionNumber;
+ }
+
+ gRT->SetVariable (
+ OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ (LoadOptionCount - Start)* sizeof (UINT16),
+ OptionOrder
+ );
+
+ FreePool (OptionOrder);
+ EfiBootManagerFreeLoadOptions (LoadOption, LoadOptionCount);
+}
+
+/**
+ Initialize the load option.
+
+ @param OptionNumber Point to option number and NULL requests to auto-generate the option number
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerInitializeLoadOption (
+ IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option,
+ IN UINTN OptionNumber,
+ IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
+ IN UINT32 Attributes,
+ IN CHAR16 *Description,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN UINT8 *OptionalData, OPTIONAL
+ IN UINT32 OptionalDataSize
+ )
+{
+ if ((Option == NULL) || (Description == NULL) || (FilePath == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((OptionalData != NULL) && (OptionalDataSize == 0)) ||
+ ((OptionalData == NULL) && (OptionalDataSize != 0))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+ Option->OptionNumber = OptionNumber;
+ Option->OptionType = OptionType;
+ Option->Attributes = Attributes;
+ Option->Description = AllocateCopyPool (StrSize (Description), Description);
+ Option->FilePath = DuplicateDevicePath (FilePath);
+ if (OptionalData != NULL) {
+ Option->OptionalData = AllocateCopyPool (OptionalDataSize, OptionalData);
+ Option->OptionalDataSize = OptionalDataSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the index of the load option in the load option array.
+
+ The function compares the OptionType, Attributes, Description, FilePath, OptionalData.
+**/
+INTN
+EFIAPI
+EfiBootManagerFindLoadOption (
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
+ IN UINTN Count
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < Count; Index++) {
+ if ((Key->OptionType == Array[Index].OptionType) &&
+ (Key->Attributes == Array[Index].Attributes) &&
+ (StrCmp (Key->Description, Array[Index].Description) == 0) &&
+ (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
+ (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
+ (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
+ return (INTN) Index;
+ }
+ }
+
+ return -1;
+}
+
+EFI_STATUS
+DeleteOptionVariable (
+ IN CHAR16 *OptionOrderVariable,
+ IN UINT16 OptionNumber
+ )
+{
+ UINT16 *OptionOrder;
+ UINTN OptionOrderSize;
+ EFI_STATUS Status;
+ UINTN Index;
+
+ Status = EFI_NOT_FOUND;
+ OptionOrder = EfiBootManagerGetVariableAndSize (
+ OptionOrderVariable,
+ &gEfiGlobalVariableGuid,
+ &OptionOrderSize
+ );
+ for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
+ if (OptionOrder[Index] == OptionNumber) {
+ OptionOrderSize -= sizeof (UINT16);
+ CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16));
+ Status = gRT->SetVariable (
+ OptionOrderVariable,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ OptionOrderSize,
+ OptionOrder
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+ }
+ }
+ if (OptionOrder != NULL) {
+ FreePool (OptionOrder);
+ }
+
+ return Status;
+}
+
+/**
+ Update the BootOrder or DriverOrder according to the OptionType to delete OptionNumber .
+
+ @param OptionNumber Indicate the option number of load option
+ @param OptionType Indicate the type of load option
+
+ @retval EFI_INVALID_PARAMETER OptionType or OptionNumber is invalid.
+ @retval EFI_NOT_FOUND The load option cannot be found
+ @retval EFI_SUCCESS The load option was deleted
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerDeleteLoadOptionVariable (
+ IN UINTN OptionNumber,
+ IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
+ )
+{
+ if ((OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return DeleteOptionVariable (
+ OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
+ (UINT16) OptionNumber
+ );
+}
+
+/**
+ Convert a single character to number.
+ It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'
+**/
+UINTN
+CharToUint (
+ IN CHAR16 Char
+ )
+{
+ if ((Char >= L'0') && (Char <= L'9')) {
+ return (UINTN) (Char - L'0');
+ }
+
+ if ((Char >= L'A') && (Char <= L'F')) {
+ return (UINTN) (Char - L'A' + 0xA);
+ }
+
+ ASSERT (FALSE);
+ return 0;
+}
+
+/**
+ Returns the size of a device path in bytes.
+
+ This function returns the size, in bytes, of the device path data structure
+ specified by DevicePath including the end of device path node. If DevicePath
+ is NULL, then 0 is returned. If the length of the device path is bigger than
+ MaxSize, also return 0 to indicate this is an invalidate device path.
+
+ @param DevicePath A pointer to a device path data structure.
+ @param MaxSize Max valid device path size. If big than this size,
+ return error.
+
+ @retval 0 An invalid device path.
+ @retval Others The size of a device path in bytes.
+
+**/
+UINTN
+GetDevicePathSizeEx (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN UINTN MaxSize
+ )
+{
+ UINTN Size;
+ UINTN NodeSize;
+
+ if (DevicePath == NULL) {
+ return 0;
+ }
+
+ //
+ // Search for the end of the device path structure
+ //
+ Size = 0;
+ while (!IsDevicePathEnd (DevicePath)) {
+ NodeSize = DevicePathNodeLength (DevicePath);
+ if (NodeSize == 0) {
+ return 0;
+ }
+ Size += NodeSize;
+ if (Size > MaxSize) {
+ return 0;
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+ Size += DevicePathNodeLength (DevicePath);
+ if (Size > MaxSize) {
+ return 0;
+ }
+
+ return Size;
+}
+
+/**
+ Returns the length of a Null-terminated Unicode string. If the length is
+ bigger than MaxStringLen, return length 0 to indicate that this is an
+ invalidate string.
+
+ This function returns the number of Unicode characters in the Null-terminated
+ Unicode string specified by String.
+
+ If String is NULL, then ASSERT().
+ If String is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param String A pointer to a Null-terminated Unicode string.
+ @param MaxStringLen Max string len in this string.
+
+ @retval 0 An invalid string.
+ @retval Others The length of String.
+
+**/
+UINTN
+StrSizeEx (
+ IN CONST CHAR16 *String,
+ IN UINTN MaxStringLen
+ )
+{
+ UINTN Length;
+
+ ASSERT (String != NULL && MaxStringLen != 0);
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length+=2);
+
+ if (*String != L'\0' && MaxStringLen == Length) {
+ return 0;
+ }
+
+ return Length + 2;
+}
+
+/**
+ Validate the EFI Boot#### variable (VendorGuid/Name)
+
+ @param Variable Boot#### variable data.
+ @param VariableSize Returns the size of the EFI variable that was read
+
+ @retval TRUE The variable data is correct.
+ @retval FALSE The variable data is corrupted.
+
+**/
+BOOLEAN
+ValidateOption (
+ UINT8 *Variable,
+ UINTN VariableSize
+ )
+{
+ UINT16 FilePathSize;
+ UINT8 *TempPtr;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN TempSize;
+
+ if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
+ return FALSE;
+ }
+
+ //
+ // Skip the option attribute
+ //
+ TempPtr = Variable;
+ TempPtr += sizeof (UINT32);
+
+ //
+ // Get the option's device path size
+ //
+ FilePathSize = *(UINT16 *) TempPtr;
+ TempPtr += sizeof (UINT16);
+
+ //
+ // Get the option's description string size
+ //
+ TempSize = StrSizeEx ((CHAR16 *) TempPtr, VariableSize - sizeof (UINT16) - sizeof (UINT32));
+ TempPtr += TempSize;
+
+ //
+ // Get the option's device path
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
+ TempPtr += FilePathSize;
+
+ //
+ // Validation boot option variable.
+ //
+ if ((FilePathSize == 0) || (TempSize == 0)) {
+ return FALSE;
+ }
+
+ if (TempSize + FilePathSize + sizeof (UINT16) + sizeof (UINT32) > VariableSize) {
+ return FALSE;
+ }
+
+ return (BOOLEAN) (GetDevicePathSizeEx (DevicePath, FilePathSize) != 0);
+}
+
+/**
+ Build the Boot#### or Driver#### option from the VariableName.
+
+ @param VariableName EFI Variable name indicate if it is Boot#### or
+ Driver####
+
+ @retval EFI_SUCCESS Get the option just been created
+ @retval EFI_NOT_FOUND Failed to get the new option
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerVariableToLoadOption (
+ IN CHAR16 *VariableName,
+ IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Attribute;
+ UINT16 FilePathSize;
+ UINT8 *Variable;
+ UINT8 *TempPtr;
+ UINTN VariableSize;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ UINT8 *OptionalData;
+ UINT32 OptionalDataSize;
+ CHAR16 *Description;
+ UINT8 NumOff;
+ EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;
+ UINT16 OptionNumber;
+
+ if ((VariableName == NULL) || (Option == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Read the variable
+ //
+ Variable = EfiBootManagerGetVariableAndSize (
+ VariableName,
+ &gEfiGlobalVariableGuid,
+ &VariableSize
+ );
+ if (Variable == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Validate Boot#### variable data.
+ //
+ if (!ValidateOption(Variable, VariableSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Notes: careful defined the variable of Boot#### or
+ // Driver####, consider use some macro to abstract the code
+ //
+ //
+ // Get the option attribute
+ //
+ TempPtr = Variable;
+ Attribute = *(UINT32 *) Variable;
+ TempPtr += sizeof (UINT32);
+
+ //
+ // Get the option's device path size
+ //
+ FilePathSize = *(UINT16 *) TempPtr;
+ TempPtr += sizeof (UINT16);
+
+ //
+ // Get the option's description string
+ //
+ Description = (CHAR16 *) TempPtr;
+
+ //
+ // Get the option's description string size
+ //
+ TempPtr += StrSize ((CHAR16 *) TempPtr);
+
+ //
+ // Get the option's device path
+ //
+ FilePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
+ TempPtr += FilePathSize;
+
+ OptionalDataSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));
+ if (OptionalDataSize == 0) {
+ OptionalData = NULL;
+ } else {
+ OptionalData = TempPtr;
+ }
+
+ if (*VariableName == L'B') {
+ OptionType = LoadOptionTypeBoot;
+ NumOff = (UINT8) (sizeof (L"Boot") / sizeof (CHAR16) - 1);
+ } else {
+ OptionType = LoadOptionTypeDriver;
+ NumOff = (UINT8) (sizeof (L"Driver") / sizeof (CHAR16) - 1);
+ }
+
+ //
+ // Get the value from VariableName Unicode string
+ // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this
+ // Unicode stream to ASCII without any loss in meaning.
+ //
+ OptionNumber = (UINT16) (CharToUint (VariableName[NumOff+0]) * 0x1000)
+ + (UINT16) (CharToUint (VariableName[NumOff+1]) * 0x100)
+ + (UINT16) (CharToUint (VariableName[NumOff+2]) * 0x10)
+ + (UINT16) (CharToUint (VariableName[NumOff+3]) * 0x1);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ Option,
+ OptionNumber,
+ OptionType,
+ Attribute,
+ Description,
+ FilePath,
+ OptionalData,
+ OptionalDataSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ FreePool (Variable);
+ return Status;
+}
+
+/**
+ Process BootOrder, or DriverOrder variables, by calling
+ BdsLibVariableToOption () for each UINT16 in the variables.
+
+ @param BdsCommonOptionList The header of the option list base on variable
+ VariableName
+ @param VariableName EFI Variable name indicate the BootOrder or
+ DriverOrder
+
+ @retval EFI_SUCCESS Success create the boot option or driver option
+ list
+ @retval EFI_OUT_OF_RESOURCES Failed to get the boot option or driver option list
+
+**/
+EFI_BOOT_MANAGER_LOAD_OPTION *
+EFIAPI
+EfiBootManagerGetLoadOptions (
+ OUT UINTN *OptionCount,
+ IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
+ )
+{
+ EFI_STATUS Status;
+ UINT16 *BootNext;
+ UINT16 *OptionOrder;
+ UINTN OptionOrderSize;
+ UINTN Index;
+ UINTN OptionIndex;
+ EFI_BOOT_MANAGER_LOAD_OPTION *Option;
+ CHAR16 OptionName[sizeof ("Driver####")];
+ UINT16 OptionNumber;
+
+ *OptionCount = 0;
+ BootNext = NULL;
+
+ if (LoadOptionType == LoadOptionTypeBoot) {
+ GetEfiGlobalVariable2 (L"BootNext", (VOID**)&BootNext, NULL);
+ }
+
+ //
+ // Read the BootOrder, or DriverOrder variable.
+ //
+ OptionOrder = EfiBootManagerGetVariableAndSize (
+ (LoadOptionType == LoadOptionTypeBoot) ? L"BootOrder" : L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &OptionOrderSize
+ );
+ if (OptionOrder == NULL && BootNext == NULL) {
+ return NULL;
+ }
+
+ *OptionCount = ((BootNext != NULL) ? 1 : 0) + OptionOrderSize / sizeof (UINT16);
+
+ Option = AllocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+ ASSERT (Option != NULL);
+
+ OptionIndex = 0;
+ for (Index = 0; Index < *OptionCount; Index++) {
+ if (BootNext == NULL) {
+ OptionNumber = OptionOrder[Index];
+ } else {
+ OptionNumber = ((Index == 0) ? *BootNext : OptionOrder[Index - 1]);
+ }
+ if (LoadOptionType == LoadOptionTypeBoot) {
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionNumber);
+ } else {
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionNumber);
+ }
+
+ Status = EfiBootManagerVariableToLoadOption (OptionName, &Option[OptionIndex]);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "[Bds] %s doesn't exist - Update ****Order variable to remove the reference!!", OptionName));
+ EfiBootManagerDeleteLoadOptionVariable (OptionNumber, LoadOptionTypeBoot);
+ } else {
+ ASSERT (Option[OptionIndex].OptionNumber == OptionNumber);
+
+ if ((BootNext != NULL) && (*BootNext == Option[OptionIndex].OptionNumber)) {
+ Option[OptionIndex].BootNext = TRUE;
+ }
+ OptionIndex++;
+ }
+ }
+
+ if (OptionOrder != NULL) {
+ FreePool (OptionOrder);
+ }
+ if (BootNext != NULL) {
+ FreePool (BootNext);
+ }
+
+ if (OptionIndex < *OptionCount) {
+ Option = ReallocatePool (
+ *OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
+ OptionIndex * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
+ Option
+ );
+ *OptionCount = OptionIndex;
+ }
+
+ return Option;
+}
+
+/**
+ Free an EFI_BOOT_MANGER_LOAD_OPTION entry that was allocate by the library.
+
+ @param Option Pointer to boot option to Free.
+
+ @return EFI_SUCCESS BootOption was freed
+ @return EFI_INVALID_PARAMETER BootOption == NULL
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeLoadOption (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
+ )
+{
+ if (LoadOption == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (LoadOption->Description != NULL) {
+ FreePool (LoadOption->Description);
+ }
+ if (LoadOption->FilePath != NULL) {
+ FreePool (LoadOption->FilePath);
+ }
+ if (LoadOption->OptionalData != NULL) {
+ FreePool (LoadOption->OptionalData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Free an EFI_BOOT_MANGER_LOAD_OPTION array that was allocated by
+ EfiBootManagerGetLoadOptions().
+
+ @param BootOption Pointer to boot option array to free.
+ @param BootOptionCount Number of array entries in BootOption
+
+ @return EFI_SUCCESS BootOption was freed
+ @return EFI_NOT_FOUND BootOption == NULL
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeLoadOptions (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
+ IN UINTN OptionCount
+ )
+{
+ UINTN Index;
+
+ if (Option == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0;Index < OptionCount; Index++) {
+ EfiBootManagerFreeLoadOption (&Option[Index]);
+ }
+
+ FreePool (Option);
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsMisc.c b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsMisc.c
new file mode 100644
index 0000000..72206e6
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/BdsMisc.c
@@ -0,0 +1,496 @@
+/** @file
+ Misc BDS library function
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#include "InternalBdsLib.h"
+
+
+/**
+ Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
+ buffer, and the size of the buffer. If failure return NULL.
+
+ @param Name String part of EFI variable name
+ @param VendorGuid GUID part of EFI variable name
+ @param VariableSize Returns the size of the EFI variable that was read
+
+ @return Dynamically allocated memory that contains a copy of the EFI variable
+ Caller is responsible freeing the buffer.
+ @retval NULL Variable was not read
+
+**/
+VOID *
+EFIAPI
+EfiBootManagerGetVariableAndSize (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid,
+ OUT UINTN *VariableSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ VOID *Buffer;
+
+ Buffer = NULL;
+ BufferSize = 0;
+
+ //
+ // Pass in a zero size buffer to find the required buffer size.
+ //
+ Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Allocate the buffer to return
+ //
+ Buffer = AllocatePool (BufferSize);
+ ASSERT (Buffer != NULL);
+ //
+ // Read variable into the allocated buffer.
+ //
+ Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ BufferSize = 0;
+ Buffer = NULL;
+ }
+ }
+
+ ASSERT (((Buffer == NULL) && (BufferSize == 0)) ||
+ ((Buffer != NULL) && (BufferSize != 0))
+ );
+ *VariableSize = BufferSize;
+
+ return Buffer;
+}
+
+/**
+ Delete the instance in Multi which matches partly with Single instance
+
+ @param Multi A pointer to a multi-instance device path data
+ structure.
+ @param Single A pointer to a single-instance device path data
+ structure.
+
+ @return This function will remove the device path instances in Multi which partly
+ match with the Single, and return the result device path. If there is no
+ remaining device path as a result, this function will return NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+EfiBootManagerDelPartMatchInstance (
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,
+ IN EFI_DEVICE_PATH_PROTOCOL *Single
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
+ UINTN InstanceSize;
+ UINTN SingleDpSize;
+
+ NewDevicePath = NULL;
+ TempNewDevicePath = NULL;
+
+ if (Multi == NULL || Single == NULL) {
+ return Multi;
+ }
+
+ Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
+ SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
+ InstanceSize -= END_DEVICE_PATH_LENGTH;
+
+ while (Instance != NULL) {
+
+ if (CompareMem (Instance, Single, MIN (SingleDpSize, InstanceSize)) != 0) {
+ //
+ // Append the device path instance which does not match with Single
+ //
+ TempNewDevicePath = NewDevicePath;
+ NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
+ if (TempNewDevicePath != NULL) {
+ FreePool(TempNewDevicePath);
+ }
+ }
+ FreePool(Instance);
+ Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
+ InstanceSize -= END_DEVICE_PATH_LENGTH;
+ }
+
+ return NewDevicePath;
+}
+
+/**
+ Function compares a device path data structure to that of all the nodes of a
+ second device path instance.
+
+ @param Multi A pointer to a multi-instance device path data
+ structure.
+ @param Single A pointer to a single-instance device path data
+ structure.
+
+ @retval TRUE If the Single device path is contained within Multi device path.
+ @retval FALSE The Single device path is not match within Multi device path.
+
+**/
+BOOLEAN
+EFIAPI
+EfiBootManagerMatchDevicePaths (
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,
+ IN EFI_DEVICE_PATH_PROTOCOL *Single
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
+ UINTN Size;
+
+ if (Multi == NULL || Single == NULL) {
+ return FALSE;
+ }
+
+ DevicePath = Multi;
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
+
+ //
+ // Search for the match of 'Single' in 'Multi'
+ //
+ while (DevicePathInst != NULL) {
+ //
+ // If the single device path is found in multiple device paths,
+ // return success
+ //
+ if (CompareMem (Single, DevicePathInst, Size) == 0) {
+ FreePool (DevicePathInst);
+ return TRUE;
+ }
+
+ FreePool (DevicePathInst);
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
+ }
+
+ return FALSE;
+}
+
+/**
+ Get the headers (dos, image, optional header) from an image
+
+ @param Device SimpleFileSystem device handle
+ @param FileName File name for the image
+ @param DosHeader Pointer to dos header
+ @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
+
+ @retval EFI_SUCCESS Successfully get the machine type.
+ @retval EFI_NOT_FOUND The file is not found.
+ @retval EFI_LOAD_ERROR File is not a valid image file.
+
+**/
+EFI_STATUS
+GetImageHeader (
+ IN EFI_HANDLE Device,
+ IN CHAR16 *FileName,
+ OUT EFI_IMAGE_DOS_HEADER *DosHeader,
+ OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
+ EFI_FILE_HANDLE Root;
+ EFI_FILE_HANDLE ThisFile;
+ UINTN BufferSize;
+ UINT64 FileSize;
+ EFI_FILE_INFO *Info;
+
+ Root = NULL;
+ ThisFile = NULL;
+ //
+ // Handle the file system interface to the device
+ //
+ Status = gBS->HandleProtocol (
+ Device,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID *) &Volume
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = Volume->OpenVolume (
+ Volume,
+ &Root
+ );
+ if (EFI_ERROR (Status)) {
+ Root = NULL;
+ goto Done;
+ }
+ ASSERT (Root != NULL);
+ Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ ASSERT (ThisFile != NULL);
+
+ //
+ // Get file size
+ //
+ BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
+ do {
+ Info = NULL;
+ Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ Status = ThisFile->GetInfo (
+ ThisFile,
+ &gEfiFileInfoGuid,
+ &BufferSize,
+ Info
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ FreePool (Info);
+ goto Done;
+ }
+ FreePool (Info);
+ } while (TRUE);
+
+ FileSize = Info->FileSize;
+ FreePool (Info);
+
+ //
+ // Read dos header
+ //
+ BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
+ Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);
+ if (EFI_ERROR (Status) ||
+ BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||
+ FileSize <= DosHeader->e_lfanew ||
+ DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ Status = EFI_LOAD_ERROR;
+ goto Done;
+ }
+
+ //
+ // Move to PE signature
+ //
+ Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_LOAD_ERROR;
+ goto Done;
+ }
+
+ //
+ // Read and check PE signature
+ //
+ BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
+ Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);
+ if (EFI_ERROR (Status) ||
+ BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||
+ Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ Status = EFI_LOAD_ERROR;
+ goto Done;
+ }
+
+ //
+ // Check PE32 or PE32+ magic
+ //
+ if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
+ Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ Status = EFI_LOAD_ERROR;
+ goto Done;
+ }
+
+ Done:
+ if (ThisFile != NULL) {
+ ThisFile->Close (ThisFile);
+ }
+ if (Root != NULL) {
+ Root->Close (Root);
+ }
+ return Status;
+}
+
+/**
+ This routine adjust the memory information for different memory type and
+ save them into the variables for next boot.
+**/
+VOID
+SetMemoryTypeInformationVariable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation;
+ EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;
+ UINTN VariableSize;
+ UINTN Index;
+ UINTN Index1;
+ UINT32 Previous;
+ UINT32 Current;
+ UINT32 Next;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ BOOLEAN MemoryTypeInformationModified;
+ BOOLEAN MemoryTypeInformationVariableExists;
+ EFI_BOOT_MODE BootMode;
+
+ MemoryTypeInformationModified = FALSE;
+ MemoryTypeInformationVariableExists = FALSE;
+
+
+ BootMode = GetBootModeHob ();
+ //
+ // In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.
+ //
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ return;
+ }
+
+ //
+ // Only check the the Memory Type Information variable in the boot mode
+ // other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type
+ // Information is not valid in this boot mode.
+ //
+ if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {
+ VariableSize = 0;
+ Status = gRT->GetVariable (
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+ &gEfiMemoryTypeInformationGuid,
+ NULL,
+ &VariableSize,
+ NULL
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ MemoryTypeInformationVariableExists = TRUE;
+ }
+ }
+
+ //
+ // Retrieve the current memory usage statistics. If they are not found, then
+ // no adjustments can be made to the Memory Type Information variable.
+ //
+ Status = EfiGetSystemConfigurationTable (
+ &gEfiMemoryTypeInformationGuid,
+ (VOID **) &CurrentMemoryTypeInformation
+ );
+ if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
+ return;
+ }
+
+ //
+ // Get the Memory Type Information settings from Hob if they exist,
+ // PEI is responsible for getting them from variable and build a Hob to save them.
+ // If the previous Memory Type Information is not available, then set defaults
+ //
+ GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
+ if (GuidHob == NULL) {
+ //
+ // If Platform has not built Memory Type Info into the Hob, just return.
+ //
+ return;
+ }
+ PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
+ VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+
+ //
+ // Use a heuristic to adjust the Memory Type Information for the next boot
+ //
+ DEBUG ((EFI_D_INFO, "Memory Previous Current Next \n"));
+ DEBUG ((EFI_D_INFO, " Type Pages Pages Pages \n"));
+ DEBUG ((EFI_D_INFO, "====== ======== ======== ========\n"));
+
+ for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+
+ for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
+ if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
+ break;
+ }
+ }
+ if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
+ continue;
+ }
+
+ //
+ // Previous is the number of pages pre-allocated
+ // Current is the number of pages actually needed
+ //
+ Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
+ Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;
+ Next = Previous;
+
+ //
+ // Inconsistent Memory Reserved across bootings may lead to S4 fail
+ // Write next varible to 125% * current when the pre-allocated memory is:
+ // 1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING
+ // 2. Less than the needed memory
+ //
+ if ((Current + (Current >> 1)) < Previous) {
+ if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+ Next = Current + (Current >> 2);
+ }
+ } else if (Current > Previous) {
+ Next = Current + (Current >> 2);
+ }
+ if (Next > 0 && Next < 4) {
+ Next = 4;
+ }
+
+ if (Next != Previous) {
+ PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
+ MemoryTypeInformationModified = TRUE;
+ }
+
+ DEBUG ((EFI_D_INFO, " %02x %08x %08x %08x\n", PreviousMemoryTypeInformation[Index].Type, Previous, Current, Next));
+ }
+
+ //
+ // If any changes were made to the Memory Type Information settings, then set the new variable value;
+ // Or create the variable in first boot.
+ //
+ if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {
+ Status = gRT->SetVariable (
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+ &gEfiMemoryTypeInformationGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ VariableSize,
+ PreviousMemoryTypeInformation
+ );
+
+ //
+ // If the Memory Type Information settings have been modified, then reset the platform
+ // so the new Memory Type Information setting will be used to guarantee that an S4
+ // entry/resume cycle will not fail.
+ //
+ if (MemoryTypeInformationModified) {
+ DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n"));
+ gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+}
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/Capsules.c b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/Capsules.c
new file mode 100644
index 0000000..d9097d3
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/Capsules.c
@@ -0,0 +1,217 @@
+/** @file
+ BDS routines to handle capsules.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+#include "InternalBdsLib.h"
+
+/**
+
+ This routine is called to see if there are any capsules we need to process.
+ If the boot mode is not UPDATE, then we do nothing. Otherwise find the
+ capsule HOBS and produce firmware volumes for them via the DXE service.
+ Then call the dispatcher to dispatch drivers from them. Finally, check
+ the status of the updates.
+
+ This function should be called by BDS in case we need to do some
+ sort of processing even if there is no capsule to process. We
+ need to do this if an earlier update went away and we need to
+ clear the capsule variable so on the next reset PEI does not see it and
+ think there is a capsule available.
+
+ @retval EFI_INVALID_PARAMETER boot mode is not correct for an update
+ @retval EFI_SUCCESS There is no error when processing capsule
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerProcessCapsules (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS HobPointer;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ UINT32 Size;
+ UINT32 CapsuleNumber;
+ UINT32 CapsuleTotalNumber;
+ EFI_CAPSULE_TABLE *CapsuleTable;
+ UINT32 Index;
+ UINT32 CacheIndex;
+ UINT32 CacheNumber;
+ VOID **CapsulePtr;
+ VOID **CapsulePtrCache;
+ EFI_GUID *CapsuleGuidCache;
+
+ CapsuleNumber = 0;
+ CapsuleTotalNumber = 0;
+ CacheIndex = 0;
+ CacheNumber = 0;
+ CapsulePtr = NULL;
+ CapsulePtrCache = NULL;
+ CapsuleGuidCache = NULL;
+
+ //
+ // We don't do anything else if the boot mode is not flash-update
+ //
+ ASSERT (GetBootModeHob () == BOOT_ON_FLASH_UPDATE);
+
+ Status = EFI_SUCCESS;
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
+ CapsuleTotalNumber ++;
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ if (CapsuleTotalNumber == 0) {
+ //
+ // We didn't find a hob, so had no errors.
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Init temp Capsule Data table.
+ //
+ CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtr != NULL);
+ CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtrCache != NULL);
+ CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);
+ ASSERT (CapsuleGuidCache != NULL);
+
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
+ CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ //
+ //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install
+ //capsuleTable to configure table with EFI_CAPSULE_GUID
+ //
+
+ //
+ // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating
+ // System to have information persist across a system reset. EFI System Table must
+ // point to an array of capsules that contains the same CapsuleGuid value. And agents
+ // searching for this type capsule will look in EFI System Table and search for the
+ // capsule's Guid and associated pointer to retrieve the data. Two steps below describes
+ // how to sorting the capsules by the unique guid and install the array to EFI System Table.
+ // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an
+ // array for later sorting capsules by CapsuleGuid.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ //
+ // For each capsule, we compare it with known CapsuleGuid in the CacheArray.
+ // If already has the Guid, skip it. Whereas, record it in the CacheArray as
+ // an additional one.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {
+ break;
+ }
+ CacheIndex++;
+ }
+ if (CacheIndex == CacheNumber) {
+ CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));
+ }
+ }
+ }
+
+ //
+ // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules
+ // whose guid is the same as it, and malloc memory for an array which preceding
+ // with UINT32. The array fills with entry point of capsules that have the same
+ // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install
+ // this array into EFI System Table, so that agents searching for this type capsule
+ // will look in EFI System Table and search for the capsule's Guid and associated
+ // pointer to retrieve the data.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ CapsuleNumber = 0;
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {
+ //
+ // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.
+ //
+ CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;
+ }
+ }
+ }
+ if (CapsuleNumber != 0) {
+ Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);
+ CapsuleTable = AllocateRuntimePool (Size);
+ ASSERT (CapsuleTable != NULL);
+ CapsuleTable->CapsuleArrayNumber = CapsuleNumber;
+ CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));
+ Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);
+ ASSERT_EFI_ERROR (Status);
+ }
+ CacheIndex++;
+ }
+
+ //
+ // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are
+ // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash
+ // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional
+ // type capsule transaction could be extended. It depends on platform policy.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
+ //
+ // Call capsule library to process capsule image.
+ //
+ ProcessCapsuleImage (CapsuleHeader);
+ }
+ }
+
+ //
+ // Free the allocated temp memory space.
+ //
+ FreePool (CapsuleGuidCache);
+ FreePool (CapsulePtrCache);
+ FreePool (CapsulePtr);
+
+ return Status;
+}
+
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/InternalBdsLib.h b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/InternalBdsLib.h
new file mode 100644
index 0000000..8b8d544
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/InternalBdsLib.h
@@ -0,0 +1,474 @@
+/** @file
+ BDS library definition, include the file and data structure
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#ifndef _INTERNAL_BDS_LIB_H_
+#define _INTERNAL_BDS_LIB_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/Atapi.h>
+
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/IdeControllerInit.h>
+#include <Protocol/BootLogo.h>
+
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/FileInfo.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/Performance.h>
+
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/PerformanceLib.h>
+
+#if !defined (EFI_REMOVABLE_MEDIA_FILE_NAME)
+ #if defined (MDE_CPU_EBC)
+ //
+ // Uefi specification only defines the default boot file name for IA32, X64
+ // and IPF processor, so need define boot file name for EBC architecture here.
+ //
+ #define EFI_REMOVABLE_MEDIA_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"
+ #else
+ #error "Can not determine the default boot file name for unknown processor type!"
+ #endif
+#endif
+
+typedef enum {
+ AcpiFloppyBoot,
+ MessageAtapiBoot,
+ MessageSataBoot,
+ MessageUsbBoot,
+ MessageScsiBoot,
+ MessageNetworkBoot,
+ UnsupportedBoot
+} BOOT_TYPE;
+
+typedef
+CHAR16 *
+(* GET_BOOT_DESCRIPTION) (
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ Get the revision of the EFI_KEY_OPTION structure.
+
+ @param KeyOption Pointer to the EFI_KEY_OPTION structure.
+
+ @return Revision.
+**/
+#define KEY_OPTION_REVISION(KeyOption) ((KeyOption)->KeyData & EFI_KEY_OPTION_REVISION_MASK)
+
+/**
+ Get the actual number of entries in EFI_KEY_OPTION.Keys, from 0-3.
+
+ @param KeyOption Pointer to the EFI_KEY_OPTION structure.
+
+ @return Actual number of entries in EFI_KEY_OPTION.Keys.
+**/
+#define KEY_OPTION_INPUT_KEY_COUNT(KeyOption) (((KeyOption)->KeyData & EFI_KEY_OPTION_INPUT_KEY_COUNT_MASK) >> LowBitSet32 (EFI_KEY_OPTION_INPUT_KEY_COUNT_MASK))
+
+/**
+ Return whether the Shift key needs pressed.
+
+ @param KeyOption Pointer to the EFI_KEY_OPTION structure.
+
+ @retval TRUE Shift key needs pressed.
+ @retval FALSE Shift key needn't pressed.
+**/
+#define KEY_OPTION_SHIFT_PRESSED(KeyOption) (BOOLEAN) (((KeyOption)->KeyData & EFI_KEY_OPTION_SHIFT_PRESSED_MASK) != 0)
+
+/**
+ Return whether the Control key needs pressed.
+
+ @param KeyOption Pointer to the EFI_KEY_OPTION structure.
+
+ @retval TRUE Control key needs pressed.
+ @retval FALSE Control key needn't pressed.
+**/
+#define KEY_OPTION_CONTROL_PRESSED(KeyOption) (BOOLEAN) (((KeyOption)->KeyData & EFI_KEY_OPTION_CONTROL_PRESSED_MASK) != 0)
+
+/**
+ Return whether the Alt key needs pressed.
+
+ @param KeyOption Pointer to the EFI_KEY_OPTION structure.
+
+ @retval TRUE Alt key needs pressed.
+ @retval FALSE Alt key needn't pressed.
+**/
+#define KEY_OPTION_ALT_PRESSED(KeyOption) (BOOLEAN) (((KeyOption)->KeyData & EFI_KEY_OPTION_ALT_PRESSED_MASK) != 0)
+
+/**
+ Return whether the Logo key needs pressed.
+
+ @param KeyOption Pointer to the EFI_KEY_OPTION structure.
+
+ @retval TRUE Logo key needs pressed.
+ @retval FALSE Logo key needn't pressed.
+**/
+#define KEY_OPTION_LOGO_PRESSED(KeyOption) (BOOLEAN) (((KeyOption)->KeyData & EFI_KEY_OPTION_LOGO_PRESSED_MASK) != 0)
+
+/**
+ Return whether the Menu key needs pressed.
+
+ @param KeyOption Pointer to the EFI_KEY_OPTION structure.
+
+ @retval TRUE Menu key needs pressed.
+ @retval FALSE Menu key needn't pressed.
+**/
+#define KEY_OPTION_MENU_PRESSED(KeyOption) (BOOLEAN) (((KeyOption)->KeyData & EFI_KEY_OPTION_MENU_PRESSED_MASK) != 0)
+
+/**
+ Return whether the SysReq key needs pressed.
+
+ @param KeyOption Pointer to the EFI_KEY_OPTION structure.
+
+ @retval TRUE SysReq key needs pressed.
+ @retval FALSE SysReq key needn't pressed.
+**/
+#define KEY_OPTION_SYS_REQ_PRESSED(KeyOption) (BOOLEAN) (((KeyOption)->KeyData & EFI_KEY_OPTION_SYS_REQ_PRESSED_MASK) != 0)
+
+#define HOTKEY_SIGNATURE SIGNATURE_32 ('b', 'm', 'h', 'k')
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ BOOLEAN IsContinue;
+ UINT16 BootOption;
+ UINT8 CodeCount;
+ UINT8 WaitingKey;
+ EFI_KEY_DATA KeyData[3];
+} HOTKEY;
+
+#define HOTKEY_FROM_LINK(a) CR (a, HOTKEY, Link, HOTKEY_SIGNATURE)
+
+/**
+ Get the Option Number that wasn't used.
+
+ @param OrderVariableName Could be L"BootOrder" or L"DriverOrder".
+ @param FreeOptionNumber To receive the minimal free option number.
+
+ @retval EFI_SUCCESS The option number is found
+ @retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
+ @retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
+
+**/
+EFI_STATUS
+GetFreeOptionNumber (
+ IN CHAR16 *OrderVariableName,
+ OUT UINT16 *FreeOptionNumber
+ );
+
+EFI_STATUS
+AddOptionNumberToOrderVariable (
+ IN CHAR16 *OrderVariableName,
+ IN UINT16 OptionNumber,
+ IN UINTN Position
+ );
+
+EFI_STATUS
+DeleteOptionVariable (
+ IN CHAR16 *OptionOrderVariable,
+ IN UINT16 OptionNumber
+ );
+
+/**
+
+ Allocates a block of memory to store performance data.
+
+**/
+VOID
+AllocateMemoryForPerformanceData (
+ VOID
+ );
+
+/**
+
+ Free the memory to store performance data.
+
+**/
+VOID
+FreeMemoryForPerformanceData (
+ VOID
+ );
+
+/**
+
+ Writes performance data of booting into the allocated memory.
+ OS can process these records.
+
+ @param Event The triggered event.
+ @param Context Context for this event.
+
+**/
+VOID
+EFIAPI
+WriteBootToOsPerformanceData (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+/**
+ Get the headers (dos, image, optional header) from an image
+
+ @param Device SimpleFileSystem device handle
+ @param FileName File name for the image
+ @param DosHeader Pointer to dos header
+ @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
+
+ @retval EFI_SUCCESS Successfully get the machine type.
+ @retval EFI_NOT_FOUND The file is not found.
+ @retval EFI_LOAD_ERROR File is not a valid image file.
+
+**/
+EFI_STATUS
+GetImageHeader (
+ IN EFI_HANDLE Device,
+ IN CHAR16 *FileName,
+ OUT EFI_IMAGE_DOS_HEADER *DosHeader,
+ OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
+ );
+
+INTN
+FindLoadOption (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *Key,
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *Array,
+ IN UINTN Count
+ );
+
+/**
+ For a bootable Device path, return its boot type.
+
+ @param DevicePath The bootable device Path to check
+
+ @retval AcpiFloppyBoot If given device path contains ACPI_DEVICE_PATH type device path node
+ which HID is floppy device.
+ @retval MessageAtapiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_ATAPI_DP.
+ @retval MessageSataBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_SATA_DP.
+ @retval MessageScsiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_SCSI_DP.
+ @retval MessageUsbBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_USB_DP.
+ @retval MessageNetworkBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
+ and its last device path node's subtype is MSG_MAC_ADDR_DP, MSG_VLAN_DP,
+ MSG_IPv4_DP or MSG_IPv6_DP.
+ @retval MiscBoot Other boot type,
+
+**/
+BOOT_TYPE
+BootTypeFromDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ This routine adjust the memory information for different memory type and
+ save them into the variables for next boot.
+**/
+VOID
+SetMemoryTypeInformationVariable (
+ VOID
+ );
+
+/**
+ Check whether there is a instance in BlockIoDevicePath, which contain multi device path
+ instances, has the same partition node with HardDriveDevicePath device path
+
+ @param BlockIoDevicePath Multi device path instances which need to check
+ @param HardDriveDevicePath A device path which starts with a hard drive media
+ device path.
+
+ @retval TRUE There is a matched device path instance.
+ @retval FALSE There is no matched device path instance.
+
+**/
+BOOLEAN
+MatchPartitionDevicePathNode (
+ IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
+ );
+
+/**
+ This function will register the new boot#### or driver#### options.
+ After the boot#### or driver#### updated, the BootOrder or DriverOrder will also be updated.
+
+ @param Options Pointer to array of load options to add.
+ @param OptionCount Number of load options.
+ @param Position Position of the new load option to put in the ****Order variable.
+
+ @retval EFI_SUCCESS The boot#### or driver#### have been success
+ registered
+ @retval EFI_STATUS Return the status of gRT->SetVariable ().
+
+**/
+EFI_STATUS
+AddLoadOptions (
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Options,
+ IN UINTN OptionCount,
+ IN UINTN Position
+ );
+
+/**
+ This function will connect all current system handles recursively.
+ gBS->ConnectController() service is invoked for each handle exist in system handler buffer.
+ If the handle is bus type handler, all childrens will be connected recursively by gBS->ConnectController().
+**/
+VOID
+ConnectAllEfi (
+ VOID
+ );
+
+
+/**
+ Connect all the drivers to all the controllers.
+
+ This function makes sure all the current system drivers manage the correspoinding
+ controllers if have. And at the same time, makes sure all the system controllers
+ have driver to manage it if have.
+**/
+VOID
+ConnectAllDriversToAllControllers (
+ VOID
+ );
+
+/**
+ Return the array of key options.
+
+ @param Count Return the number of key options.
+
+ @retval NULL No key option.
+ @retval Other Pointer to the key options.
+**/
+EFI_BOOT_MANAGER_KEY_OPTION *
+EFIAPI
+EfiBootManagerGetKeyOptions (
+ OUT UINTN *Count
+ );
+
+/**
+ Free the key options returned from EfiBootManagerGetKeyOptions.
+
+ @param KeyOptions Pointer to the key options.
+ @param KeyOptionCount Number of the key options.
+
+ @retval EFI_SUCCESS The key options are freed.
+ @retval EFI_NOT_FOUND KeyOptions is NULL.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeKeyOptions (
+ IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions,
+ IN UINTN KeyOptionCount
+ );
+
+/**
+ Connect the specific Usb device which match the short form device path.
+
+ @param DevicePath A short-form device path that starts with the first
+ element being a USB WWID or a USB Class device
+ path
+
+ @return EFI_INVALID_PARAMETER DevicePath is NULL pointer.
+ DevicePath is not a USB device path.
+
+ @return EFI_SUCCESS Success to connect USB device
+ @return EFI_NOT_FOUND Fail to find handle for USB controller to connect.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerConnectUsbShortFormDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ This function will create all handles associate with every device
+ path node. If the handle associate with one device path node can not
+ be created successfully, Dispatch service which load the missing drivers
+ is called according to input parameter, since in some cases no driver
+ dependency is assumed exist, so may need not to call this service.
+
+ @param DevicePathToConnect The device path which will be connected, it CANNOT be
+ a multi-instance device path
+ @param NeedDispatch Whether requires dispatch service during connection
+ @param MatchingHandle Return the controller handle closest to the DevicePathToConnect
+
+ @retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.
+ @retval EFI_NOT_FOUND Failed to create all handles associate with every device path node.
+ @retval EFI_SUCCESS Successful to create all handles associate with every device path node.
+
+**/
+EFI_STATUS
+ConnectDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
+ IN BOOLEAN NeedDispatch,
+ OUT EFI_HANDLE *MatchingHandle OPTIONAL
+ );
+
+extern EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION mEfiBootManagerRefreshLegacyBootOption;
+extern EFI_BOOT_MANAGER_LEGACY_BOOT mEfiBootManagerLegacyBoot;
+#endif // _BDS_LIB_H_
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/Performance.c b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/Performance.c
new file mode 100644
index 0000000..ac8d6ad
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/Performance.c
@@ -0,0 +1,413 @@
+/** @file
+ This file include the file which can help to get the system
+ performance, all the function will only include if the performance
+ switch is set.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#include "InternalBdsLib.h"
+
+PERF_HEADER mPerfHeader;
+PERF_DATA mPerfData;
+EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase = 0x0FFFFFFFFULL;
+UINT32 mAcpiLowMemoryLength = 0x4000;
+
+/**
+ Get the short verion of PDB file name to be
+ used in performance data logging.
+
+ @param PdbFileName The long PDB file name.
+ @param GaugeString The output string to be logged by performance logger.
+
+**/
+VOID
+GetShortPdbFileName (
+ IN CONST CHAR8 *PdbFileName,
+ OUT CHAR8 *GaugeString
+ )
+{
+ UINTN Index;
+ UINTN Index1;
+ UINTN StartIndex;
+ UINTN EndIndex;
+
+ if (PdbFileName == NULL) {
+ AsciiStrCpy (GaugeString, " ");
+ } else {
+ StartIndex = 0;
+ for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
+ ;
+
+ for (Index = 0; PdbFileName[Index] != 0; Index++) {
+ if (PdbFileName[Index] == '\\') {
+ StartIndex = Index + 1;
+ }
+
+ if (PdbFileName[Index] == '.') {
+ EndIndex = Index;
+ }
+ }
+
+ Index1 = 0;
+ for (Index = StartIndex; Index < EndIndex; Index++) {
+ GaugeString[Index1] = PdbFileName[Index];
+ Index1++;
+ if (Index1 == PERF_TOKEN_LENGTH - 1) {
+ break;
+ }
+ }
+
+ GaugeString[Index1] = 0;
+ }
+
+ return ;
+}
+
+/**
+ Get the name from the Driver handle, which can be a handle with
+ EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
+ This name can be used in performance data logging.
+
+ @param Handle Driver handle.
+ @param GaugeString The output string to be logged by performance logger.
+
+**/
+VOID
+GetNameFromHandle (
+ IN EFI_HANDLE Handle,
+ OUT CHAR8 *GaugeString
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ CHAR8 *PdbFileName;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+
+ AsciiStrCpy (GaugeString, " ");
+
+ //
+ // Get handle name from image protocol
+ //
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &Image
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ //
+ // Get handle name from image protocol
+ //
+ Status = gBS->HandleProtocol (
+ DriverBinding->ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &Image
+ );
+ }
+
+ PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
+
+ if (PdbFileName != NULL) {
+ GetShortPdbFileName (PdbFileName, GaugeString);
+ }
+
+ return ;
+}
+
+/**
+
+ Allocates a block of memory to store performance data.
+
+**/
+VOID
+AllocateMemoryForPerformanceData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
+ //
+ // Allocate a block of memory that contain performance data to OS
+ //
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (mAcpiLowMemoryLength),
+ &mAcpiLowMemoryBase
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gRT->SetVariable (
+ L"PerfDataMemAddr",
+ &gPerformanceProtocolGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (EFI_PHYSICAL_ADDRESS),
+ &mAcpiLowMemoryBase
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+}
+
+/**
+
+ Free the memory to store performance data.
+
+**/
+VOID
+FreeMemoryForPerformanceData (
+ VOID
+ )
+{
+ ASSERT (mAcpiLowMemoryBase != 0x0FFFFFFFF);
+ FreePages ((VOID *) (UINTN) mAcpiLowMemoryBase, EFI_SIZE_TO_PAGES (mAcpiLowMemoryLength));
+ mAcpiLowMemoryBase = 0x0FFFFFFFF;
+}
+
+/**
+
+ Writes performance data of booting into the allocated memory.
+ OS can process these records.
+
+ @param Event The triggered event.
+ @param Context Context for this event.
+
+**/
+VOID
+EFIAPI
+WriteBootToOsPerformanceData (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINT32 LimitCount;
+ EFI_HANDLE *Handles;
+ UINTN NoHandles;
+ CHAR8 GaugeString[PERF_TOKEN_LENGTH];
+ UINT8 *Ptr;
+ UINT32 Index;
+ UINT64 Ticker;
+ UINT64 Freq;
+ UINT32 Duration;
+ UINTN LogEntryKey;
+ CONST VOID *Handle;
+ CONST CHAR8 *Token;
+ CONST CHAR8 *Module;
+ UINT64 StartTicker;
+ UINT64 EndTicker;
+ UINT64 StartValue;
+ UINT64 EndValue;
+ BOOLEAN CountUp;
+ UINTN EntryIndex;
+ UINTN NumPerfEntries;
+ //
+ // List of flags indicating PerfEntry contains DXE handle
+ //
+ BOOLEAN *PerfEntriesAsDxeHandle;
+
+ //
+ // Record the performance data for End of BDS
+ //
+ PERF_END(NULL, "BDS", NULL, 0);
+
+ if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
+ return;
+ }
+
+ //
+ // Retrieve time stamp count as early as possible
+ //
+ Ticker = GetPerformanceCounter ();
+
+ Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
+
+ Freq = DivU64x32 (Freq, 1000);
+
+ mPerfHeader.CpuFreq = Freq;
+
+ //
+ // Record BDS raw performance data
+ //
+ if (EndValue >= StartValue) {
+ mPerfHeader.BDSRaw = Ticker - StartValue;
+ CountUp = TRUE;
+ } else {
+ mPerfHeader.BDSRaw = StartValue - Ticker;
+ CountUp = FALSE;
+ }
+
+ //
+ // Put Detailed performance data into memory
+ //
+ Handles = NULL;
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &NoHandles,
+ &Handles
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));
+ LimitCount = (mAcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
+
+ NumPerfEntries = 0;
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurement (
+ LogEntryKey,
+ &Handle,
+ &Token,
+ &Module,
+ &StartTicker,
+ &EndTicker)) != 0) {
+ NumPerfEntries++;
+ }
+ PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
+ ASSERT (PerfEntriesAsDxeHandle != NULL);
+
+ //
+ // Get DXE drivers performance
+ //
+ for (Index = 0; Index < NoHandles; Index++) {
+ Ticker = 0;
+ LogEntryKey = 0;
+ EntryIndex = 0;
+ while ((LogEntryKey = GetPerformanceMeasurement (
+ LogEntryKey,
+ &Handle,
+ &Token,
+ &Module,
+ &StartTicker,
+ &EndTicker)) != 0) {
+ if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
+ PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
+ }
+ EntryIndex++;
+ if ((Handle == Handles[Index]) && (EndTicker != 0)) {
+ if (StartTicker == 1) {
+ StartTicker = StartValue;
+ }
+ if (EndTicker == 1) {
+ EndTicker = StartValue;
+ }
+ Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
+ }
+ }
+
+ Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
+
+ if (Duration > 0) {
+
+ GetNameFromHandle (Handles[Index], GaugeString);
+
+ AsciiStrCpy (mPerfData.Token, GaugeString);
+ mPerfData.Duration = Duration;
+
+ CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
+ Ptr += sizeof (PERF_DATA);
+
+ mPerfHeader.Count++;
+ if (mPerfHeader.Count == LimitCount) {
+ goto Done;
+ }
+ }
+ }
+
+ //
+ // Get inserted performance data
+ //
+ LogEntryKey = 0;
+ EntryIndex = 0;
+ while ((LogEntryKey = GetPerformanceMeasurement (
+ LogEntryKey,
+ &Handle,
+ &Token,
+ &Module,
+ &StartTicker,
+ &EndTicker)) != 0) {
+ if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {
+
+ ZeroMem (&mPerfData, sizeof (PERF_DATA));
+
+ AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
+ if (StartTicker == 1) {
+ StartTicker = StartValue;
+ }
+ if (EndTicker == 1) {
+ EndTicker = StartValue;
+ }
+ Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
+
+ mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
+
+ CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
+ Ptr += sizeof (PERF_DATA);
+
+ mPerfHeader.Count++;
+ if (mPerfHeader.Count == LimitCount) {
+ goto Done;
+ }
+ }
+ EntryIndex++;
+ }
+
+Done:
+
+ FreePool (Handles);
+ FreePool (PerfEntriesAsDxeHandle);
+
+ mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
+
+ //
+ // Put performance data to Reserved memory
+ //
+ CopyMem (
+ (UINTN *) (UINTN) mAcpiLowMemoryBase,
+ &mPerfHeader,
+ sizeof (PERF_HEADER)
+ );
+
+ return ;
+}
diff --git a/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/UefiBootManagerLib.inf
new file mode 100644
index 0000000..35db0b4
--- /dev/null
+++ b/QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/UefiBootManagerLib.inf
@@ -0,0 +1,132 @@
+## @file
+#
+# General BDS defines and produce general interfaces for platform BDS driver including:
+# 1) BDS boot policy interface;
+# 2) BDS boot device connect interface;
+# 3) BDS Misc interfaces for mainting boot variable, ouput string, etc.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UefiBootManagerLib
+ FILE_GUID = 8D4752BC-595E-49a2-B4AF-F3F57B601DE9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UefiBootManagerLib|DXE_DRIVER UEFI_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ Performance.c
+ BdsConnect.c
+ BdsMisc.c
+ BdsConsole.c
+ BdsBoot.c
+ BdsLoadOption.c
+ BdsHotkey.c
+ InternalBdsLib.h
+ Capsules.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ HobLib
+ PcdLib
+ BaseLib
+ UefiLib
+ TimerLib
+ DebugLib
+ PrintLib
+ BaseMemoryLib
+ DevicePathLib
+ PerformanceLib
+ PeCoffGetEntryPointLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ DxeServicesLib
+ ReportStatusCodeLib
+ CapsuleLib
+ PerformanceLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid ## CONSUMES ## GUID (The identifier of memory type information type in system table)
+ ## CONSUMES ## GUID HOB (The hob holding memory type information)
+ gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" (The boot option of current boot)
+ ## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable)
+ ## CONSUMES ## Variable:L"Timeout" (The time out value in second of showing progress bar)
+ ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array)
+ ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list)
+ ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)
+ ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)
+ ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)
+ gEfiFileInfoGuid ## CONSUMES ## GUID
+ gPerformanceProtocolGuid ## SOMETIMES_PRODUCES ## Variable:L"PerfDataMemAddr" (The ACPI address of performance data)
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid # PROTOCOL CONSUMES
+ gEfiSimpleFileSystemProtocolGuid # PROTOCOL CONSUMES
+ gEfiLoadFileProtocolGuid # PROTOCOL CONSUMES
+ gEfiSimpleTextOutProtocolGuid # PROTOCOL CONSUMES
+ gEfiPciIoProtocolGuid # PROTOCOL CONSUMES
+ gEfiLoadedImageProtocolGuid # PROTOCOL CONSUMES
+ gEfiSimpleNetworkProtocolGuid # PROTOCOL CONSUMES
+ gEfiSimpleTextInProtocolGuid # PROTOCOL CONSUMES
+ gEfiBlockIoProtocolGuid # PROTOCOL CONSUMES
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL CONSUMES
+ gEfiDevicePathProtocolGuid # PROTOCOL CONSUMES
+ gEfiBootLogoProtocolGuid # PROTOCOL CONSUMES
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL SOMETIMES_CONSUMES
+ gEfiUsbIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMES
+ gEfiDiskInfoProtocolGuid # PROTOCOL SOMETIMES_CONSUMES
+ gEfiDevicePathToTextProtocolGuid # PROTOCOL SOMETIMES_CONSUMES
+
+[FeaturePcd]
+ gQuarkPlatformTokenSpaceGuid.PcdShortformBootSupport
+ gQuarkPlatformTokenSpaceGuid.PcdBdsFindDisplay
+
+[FixedPcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange
+ gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad
+ gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart
+ gQuarkPlatformTokenSpaceGuid.PcdBootManagerMenuFile
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand
diff --git a/QuarkPlatformPkg/Binary/Payload/PayloadSample.efi b/QuarkPlatformPkg/Binary/Payload/PayloadSample.efi
new file mode 100644
index 0000000..7f6396a
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/Payload/PayloadSample.efi
Binary files differ
diff --git a/QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.bin b/QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.bin
new file mode 100644
index 0000000..8643fe5
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.bin
Binary files differ
diff --git a/QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.bin b/QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.bin
new file mode 100644
index 0000000..ad5595f
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.bin
Binary files differ
diff --git a/QuarkPlatformPkg/Binary/PlatformData/galileo-fabe-platform-data.bin b/QuarkPlatformPkg/Binary/PlatformData/galileo-fabe-platform-data.bin
new file mode 100644
index 0000000..da17eb4
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/PlatformData/galileo-fabe-platform-data.bin
Binary files differ
diff --git a/QuarkPlatformPkg/Binary/PlatformData/galileo-gen2-platform-data.bin b/QuarkPlatformPkg/Binary/PlatformData/galileo-gen2-platform-data.bin
new file mode 100644
index 0000000..0d5a3bd
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/PlatformData/galileo-gen2-platform-data.bin
Binary files differ
diff --git a/QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.bin b/QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.bin
new file mode 100644
index 0000000..78c4b89
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.bin
Binary files differ
diff --git a/QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin b/QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin
new file mode 100644
index 0000000..da04ab0
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin
Binary files differ
diff --git a/QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.bin b/QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.bin
new file mode 100644
index 0000000..6c53efd
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.bin
Binary files differ
diff --git a/QuarkPlatformPkg/Binary/SIZE_8KB.bin b/QuarkPlatformPkg/Binary/SIZE_8KB.bin
new file mode 100644
index 0000000..b4033a7
--- /dev/null
+++ b/QuarkPlatformPkg/Binary/SIZE_8KB.bin
@@ -0,0 +1 @@
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/QuarkPlatformPkg/Cpu/Sec/ResetVector/CallbackServices.c b/QuarkPlatformPkg/Cpu/Sec/ResetVector/CallbackServices.c
new file mode 100644
index 0000000..e952584
--- /dev/null
+++ b/QuarkPlatformPkg/Cpu/Sec/ResetVector/CallbackServices.c
@@ -0,0 +1,98 @@
+/** @file
+ C funtions in SEC
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+
+#include "CallbackServices.h"
+
+/*! \fn BOOLEAN ValidateModuleCallBack( const QuarkSecurityHeader_t * const Header,
+ const RSA2048PublicKey_t * const RsaKey,
+ ScratchMemory_t * const MemoryBuffer
+ )
+ * \brief Callback function to be used by BIOS/OS for validation of signed modules.
+ * This function is uncalled by ROM code, though is reference bt flat32.asm
+ * as a data constant to ensure the linker includes the function (i.e.
+ * it isn't optimised away.
+ * \param Header: Pointer to the header of the module to be validated.
+ * \param RsaKey: Pointer to key to be used for validation.
+ * \param MemoryBuffer: Pointer to scratchpad memory the validation code can use.
+ * \return BOOLEAN: TRUE if module validates, FALSE if it fails for any reason.
+ */
+BOOLEAN ValidateModuleCallBack( const QuarkSecurityHeader_t * const Header,
+ const RSA2048PublicKey_t * const RsaKey,
+ ScratchMemory_t * const MemoryBuffer
+ )
+{
+ return TRUE;
+}
+
+/** Validate key module routine.
+
+ Checks the SHA256 digest of the Oem Key in a module header against
+ that of the key held in fuse bank and then uses that key to validate
+ key module.
+
+ @param[in] Header A pointer to a header structure of a key
+ module in memory to be validated..
+ @param[in] Data Pointer to the signed data associated with
+ this module.
+ @param[in] ModuleKey The key used to sign the data.
+ @param[in] Signature The signature of the data.
+ @param[in] MemoryBuffer Pointer to crypto heap management structure.
+ @param[in] KeyBankNumber Which fuse bank are we pulling the Intel key from.
+
+ @retval QUARK_ROM_NO_ERROR If Key Module Validates
+ Successfully.
+ @retval QUARK_ROM_FATAL_KEY_MODULE_FUSE_COMPARE_FAIL if the Digest of the Intel Key
+ in the Header does not match
+ that stored in the fuse.
+ @retval QUARK_ROM_FATAL_KEY_MODULE_VALIDATION_FAIL if the RSA signature
+ is not successfully validated.
+ @retval QUARK_ROM_FATAL_INVALID_KEYBANK_NUM If key bank number too large.
+ @return Other Unexpected error.
+
+**/
+EFI_STATUS
+EFIAPI
+ValidateKeyModCallBack (
+ const QuarkSecurityHeader_t * const Header,
+ const UINT8 * const Data,
+ const RSA2048PublicKey_t * const ModuleKey,
+ const UINT8 * const Signature,
+ ScratchMemory_t * const MemoryBuffer,
+ const UINT8 KeyBankNumber
+ )
+{
+ return QUARK_ROM_NO_ERROR;
+}
+
diff --git a/QuarkPlatformPkg/Cpu/Sec/ResetVector/CallbackServices.h b/QuarkPlatformPkg/Cpu/Sec/ResetVector/CallbackServices.h
new file mode 100644
index 0000000..4646c5b
--- /dev/null
+++ b/QuarkPlatformPkg/Cpu/Sec/ResetVector/CallbackServices.h
@@ -0,0 +1,39 @@
+/** @file
+ Header file for CallbackServices.c.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _CALLBACK_SERVICES_H_
+#define _CALLBACK_SERVICES_H_
+
+#include <Library/QuarkBootRomLib.h>
+
+#endif
diff --git a/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Flat32.S b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Flat32.S
new file mode 100755
index 0000000..5300a70
--- /dev/null
+++ b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Flat32.S
@@ -0,0 +1,787 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# Flat32.S
+#
+# Abstract:
+#
+# This is the code that goes from real-mode to protected mode.
+# It consumes the reset vector, configures the stack.
+#
+#
+#------------------------------------------------------------------------------
+
+
+ASM_GLOBAL ASM_PFX(ValidateModuleCallBack)
+ASM_GLOBAL ASM_PFX(ValidateKeyModCallBack)
+
+#
+# CR0 cache control bit definition
+#
+.equ CR0_CACHE_DISABLE, 0x040000000
+.equ CR0_NO_WRITE, 0x020000000
+
+.macro RET32
+ jmp %esp
+.endm
+
+#
+# ROM/SPI/MEMORY Definitions
+#
+.equ QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000) # Memory Base Address = 0
+.equ QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000) # DDR3 Memory Size = 2GB
+.equ QUARK_ESRAM_MEM_BASE_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES) # eSRAM Memory above DDR3
+.equ QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000) # eSRAM Memory Size = 512K
+.equ QUARK_STACK_SIZE_BYTES, (0x008000) # Quark stack size = 32K
+.equ QUARK_STACK_BASE_ADDRESS, (QUARK_ESRAM_MEM_BASE_ADDRESS + QUARK_ESRAM_MEM_SIZE_BYTES) - QUARK_STACK_SIZE_BYTES # Top of eSRAM - stack size
+.equ QUARK_CMH_SIZE_BYTES, (0x0400) # Quark Module Header size = 1024bytes
+.equ QUARK_ESRAM_STAGE1_BASE_ADDRESS, (QUARK_ESRAM_MEM_BASE_ADDRESS + QUARK_CMH_SIZE_BYTES) # Start of Stage1 code in eSRAM
+
+#
+# RTC/CMOS definitions
+#
+.equ RTC_INDEX, (0x70)
+.equ NMI_DISABLE, (0x80) # Bit7=1 disables NMI
+.equ NMI_ENABLE, (0x00) # Bit7=0 disables NMI
+.equ RTC_DATA, (0x71)
+
+#
+# PCI Configuration definitions
+#
+.equ PCI_CFG, (0x80000000) # PCI configuration access mechanism
+.equ PCI_ADDRESS_PORT, (0xCF8)
+.equ PCI_DATA_PORT, (0xCFC)
+
+#
+# Quark PCI devices
+#
+.equ HOST_BRIDGE_PFA, (0x0000) # B0:D0:F0 (Host Bridge)
+.equ ILB_PFA, (0x00F8) # B0:D31:F0 (Legacy Block)
+
+#
+# ILB PCI Config Registers
+#
+.equ BDE, (0x0D4) # BIOS Decode Enable register
+.equ DECODE_ALL_REGIONS_ENABLE, (0xFF000000) # Decode all BIOS decode ranges
+
+#
+# iLB Reset Register
+#
+.equ ILB_RESET_REG, (0x0CF9)
+.equ CF9_WARM_RESET, (0x02)
+.equ CF9_COLD_RESET, (0x08)
+
+#
+# Host Bridge PCI Config Registers
+#
+.equ MESSAGE_BUS_CONTROL_REG, (0xD0) # Message Bus Control Register
+.equ SB_OPCODE_FIELD, (0x18) # Bit location of Opcode field
+.equ OPCODE_SIDEBAND_REG_READ, (0x10) # Read opcode
+.equ OPCODE_SIDEBAND_REG_WRITE, (0x11) # Write opcode
+.equ OPCODE_SIDEBAND_ALT_REG_READ, (0x06) # Alternate Read opcode
+.equ OPCODE_SIDEBAND_ALT_REG_WRITE, (0x07) # Alternate Write opcode
+.equ OPCODE_WARM_RESET_REQUEST, (0xF4) # Reset Warm
+.equ OPCODE_COLD_RESET_REQUEST, (0xF5) # Reset Cold
+.equ SB_PORT_FIELD, (0x10) # Bit location of Port ID field
+.equ MEMORY_ARBITER_PORT_ID, (0x00)
+.equ HOST_BRIDGE_PORT_ID, (0x03)
+.equ RMU_PORT_ID, (0x04)
+.equ MEMORY_MANAGER_PORT_ID, (0x05)
+.equ SOC_UNIT_PORT_ID, (0x31)
+.equ SB_ADDR_FIELD, (0x08) # Bit location of Register field
+.equ SB_BE_FIELD, (0x04) # Bit location of Byte Enables field
+.equ ALL_BYTE_EN, (0x0F) # All Byte Enables
+.equ MESSAGE_DATA_REG, (0xD4) # Message Data Register
+
+#
+# Memory Arbiter Config Registers
+#
+.equ AEC_CTRL_OFFSET, (0x00)
+
+#
+# Host Bridge Config Registers
+#
+.equ HMISC2_OFFSET, (0x03) # PCI configuration access mechanism
+.equ OR_PM_FIELD, (0x10)
+.equ SMI_EN, (0x00080000)
+
+.equ HMBOUND_OFFSET, (0x08)
+.equ HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
+.equ HMBOUND_LOCK, (0x01)
+.equ HECREG_OFFSET, (0x09)
+.equ EC_BASE, (0xE0000000)
+.equ EC_ENABLE, (0x01)
+
+#
+# Memory Manager Config Registers
+#
+.equ ESRAMPGCTRL_BLOCK_OFFSET, (0x82)
+.equ BLOCK_ENABLE_PG, (0x10000000)
+.equ ESRAM_ADDRESS_2G, (0x10000080)
+.equ BIMRVCTL_OFFSET, (0x19)
+.equ ENABLE_IMR_INTERRUPT, (0x80000000)
+
+#
+# SOC UNIT Debug Registers
+#
+.equ CFGSTICKY_W1_OFFSET, (0x50)
+.equ FORCE_COLD_RESET, (0x00000001)
+.equ CFGSTICKY_RW_OFFSET, (0x51)
+.equ RESET_FOR_ESRAM_LOCK, (0x00000020)
+.equ RESET_FOR_HMBOUND_LOCK, (0x00000040)
+.equ CFGNONSTICKY_W1_OFFSET, (0x52)
+.equ FORCE_WARM_RESET, (0x00000001)
+
+#
+# Contrary to the name, this file contains 16 bit code as well.
+#
+.text
+#----------------------------------------------------------------------------
+#
+# Procedure: _ModuleEntryPoint
+#
+# Input: None
+#
+# Output: None
+#
+# Destroys: Assume all registers
+#
+# Description:
+#
+# 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 a while in PEI and possibly DXE.
+#
+# After enabling protected mode, a far jump is executed to
+# transfer to PEI using the newly loaded GDT.
+#
+# Return: None
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+ #
+ # Store the the BIST value in EBP
+ #
+ #
+ # Warm Reset (INIT#) check.
+ #
+ .byte 0xbe,0x00,0xf0 #movw $0xF000, %si
+ .byte 0x8e,0xde #movw %si, %ds
+ .byte 0xbe,0xf0,0xff #movw $0xFFF0, %si
+ .byte 0x80,0x3c,0xea #cmpb $0xEA, (%si) # Is it warm reset ?
+ jne NotWarmReset # Jump if not.
+ .byte 0xb0,0x08 #movb $0x08, %al
+ .byte 0xba,0xf9,0x0c #movw $0xcf9, %dx
+ .byte 0xee #outb %al, %dx
+ .byte 0xb0,0x55 #movb $0x55, %al
+ .byte 0xe6,0x80 #outb %al, $0x80
+ jmp .
+NotWarmReset:
+ .byte 0x66,0x8b,0xe8 #movl %eax, %ebp
+
+ #
+ # Load the GDT table in GdtDesc
+ #
+ .byte 0x66,0xbe #movl $GdtDesc, %esi
+ .long GdtDesc
+
+ .byte 0x66,0x2e,0x0f,0x01,0x14 #lgdt %cs:(%si)
+
+ #
+ # Transition to 16 bit protected mode
+ #
+ .byte 0x0f,0x20,0xc0 #movl %cr0, %eax # Get control register 0
+ .byte 0x66,0x83,0xc8,0x03 #orl $0x0000003, %eax # Set PE bit (bit #0) & MP bit (bit #1)
+ .byte 0x0f,0x22,0xc0 #movl %eax, %cr0 # Activate protected mode
+
+ #
+ # Now we're in 16 bit protected mode
+ # Set up the selectors for 32 bit protected mode entry
+ #
+ .byte 0xb8 #movw SYS_DATA_SEL, %ax
+ .word SYS_DATA_SEL
+
+ .byte 0x8e,0xd8 #movw %ax, %ds
+ .byte 0x8e,0xc0 #movw %ax, %es
+ .byte 0x8e,0xe0 #movw %ax, %fs
+ .byte 0x8e,0xe8 #movw %ax, %gs
+ .byte 0x8e,0xd0 #movw %ax, %ss
+
+ #
+ # Transition to Flat 32 bit protected mode
+ # The jump to a far pointer causes the transition to 32 bit mode
+ #
+ .byte 0x66,0xbe #movl ProtectedModeEntryLinearAddress, %esi
+ .long ProtectedModeEntryLinearAddress
+ .byte 0x66,0x2e,0xff,0x2c #jmp %cs:(%esi)
+
+#
+# Protected mode portion initializes stack, configures cache, and calls C entry point
+#
+
+#----------------------------------------------------------------------------
+#
+# Procedure: ProtectedModeEntryPoint
+#
+# Input: Executing in 32 Bit Protected (flat) mode
+# cs: 0-4GB
+# ds: 0-4GB
+# es: 0-4GB
+# fs: 0-4GB
+# gs: 0-4GB
+# ss: 0-4GB
+#
+# Output: This function never returns
+#
+# Destroys:
+# ecx
+# edi
+# esi
+# esp
+#
+# Description:
+# Perform any essential early platform initilaisation
+# Setup a stack
+# Transfer control to EDKII code in eSRAM
+#
+#----------------------------------------------------------------------------
+ProtectedModeEntryPoint:
+ leal L0, %esp
+ jmp stackless_EarlyPlatformInit
+L0:
+
+ #
+ # Set up stack pointer
+ #
+ movl $QUARK_STACK_BASE_ADDRESS, %esp
+ movl $QUARK_STACK_SIZE_BYTES, %esi
+ addl %esi, %esp # ESP = top of stack (stack grows downwards).
+
+ #
+ # Check if force recovery conditions met.
+ #
+ call ASM_PFX(PlatformIsForceRecoveryConditionsMet)
+ testl %eax, %eax
+ jz NormalBoot
+
+ #
+ # Copy fixed recovery image to SRAM and call it.
+ # eax has address of routine to copy Fixed Recovery image to SRAM and call it.
+ # copy this routine to QUARK_STACK_BASE_ADDRESS, we have just setup the stack
+ # so it won't reach down to QUARK_STACK_BASE_ADDRESS yet.
+ # Doing this since we don't want the copy routine to copy over itself.
+ #
+ mov $(0x00000100), %ecx # 256 DWORDs = 1K
+ movl $QUARK_STACK_BASE_ADDRESS, %edi # The destination address in QUARK_STACK_BASE_ADDRESS.
+CopyRoutineLoop:
+ movl %ds:(%eax), %ebx
+ movl %ebx, %ds:(%edi)
+ addl $(0x04), %eax
+ addl $(0x04), %edi
+ loopl CopyRoutineLoop
+
+ #
+ # call routine which will copy & call fixed recovery image.
+ #
+ movl $QUARK_STACK_BASE_ADDRESS, %eax
+ call *%eax
+
+ #
+ # Forever loop at end of last routine so should not return here.
+ #
+ jmp .
+
+NormalBoot:
+
+ #
+ # Copy and call Stage1 code to bottom of eSRAM
+ #
+ call ASM_PFX(PlatformCopyBootStage1ImageToSramAndCall)
+
+ #
+ # Forever loop at end of last routine so should not return here.
+ #
+ jmp .
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_EarlyPlatformInit
+#
+# Input: esp - Return address
+#
+# Output: None
+#
+# Destroys: Assume all registers
+#
+# Description:
+# Any early platform initialisation required
+#
+# Return:
+# None
+#
+#----------------------------------------------------------------------------
+stackless_EarlyPlatformInit:
+
+ #
+ # Save return address
+ #
+ movl %esp, %ebp
+
+ #
+ # Ensure cache is disabled.
+ #
+ movl %cr0, %eax
+ orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax
+ invd
+ movl %eax, %cr0
+
+ #
+ # Disable NMI operation
+ # Good convention suggests you should read back RTC data port after
+ # accessing the RTC index port.
+ #
+ movb $(NMI_DISABLE), %al
+ movw $(RTC_INDEX), %dx
+ outb %al, %dx
+ movw $(RTC_DATA), %dx
+ inb %dx, %al
+
+ #
+ # Disable SMI (Disables SMI wire, not SMI messages)
+ #
+ movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L1, %esp
+ jmp stackless_SideBand_Read
+L1:
+ andl $(~SMI_EN), %eax
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L2, %esp
+ jmp stackless_SideBand_Write
+L2:
+
+ #
+ # Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
+ #
+ movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L3, %esp
+ jmp stackless_SideBand_Read
+L3:
+ andl $(FORCE_WARM_RESET), %eax
+ jz TestForceColdReset # Zero means bit clear, we're not requested to warm reset so continue as normal
+ jmp IssueWarmReset
+
+TestForceColdReset:
+ movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L4, %esp
+ jmp stackless_SideBand_Read
+L4:
+ andl $(FORCE_COLD_RESET), %eax
+ jz TestHmboundLock # Zero means bit clear, we're not requested to cold reset so continue as normal
+ jmp IssueColdReset
+
+ #
+ # Before setting HMBOUND, check it's not locked
+ #
+TestHmboundLock:
+ movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L5, %esp
+ jmp stackless_SideBand_Read
+L5:
+ andl $(HMBOUND_LOCK), %eax
+ jz ConfigHmbound # Zero means bit clear, we have the config we want so continue as normal
+ #
+ # Failed to config - store sticky bit debug
+ #
+ movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L6, %esp
+ jmp stackless_SideBand_Read
+L6:
+ orl $(RESET_FOR_HMBOUND_LOCK), %eax
+ movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L7, %esp
+ jmp stackless_SideBand_Write
+L7:
+ jmp IssueWarmReset
+
+ #
+ # Set up the HMBOUND register
+ #
+ConfigHmbound:
+ movl $(HMBOUND_ADDRESS), %eax # Data (Set HMBOUND location)
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L8, %esp
+ jmp stackless_SideBand_Write
+L8:
+
+ #
+ # Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
+ #
+ movl $(ENABLE_IMR_INTERRUPT), %eax # Data (Set interrupt enable mask)
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (BIMRVCTL_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L9, %esp
+ jmp stackless_SideBand_Write
+L9:
+
+ #
+ # Move eSRAM memory to 2GB
+ #
+ movl $(ESRAM_ADDRESS_2G), %eax # Data (Set eSRAM location)
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L10, %esp
+ jmp stackless_SideBand_Write
+L10:
+
+ #
+ # Check that we're not blocked from setting the config that we want.
+ #
+ movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L11, %esp
+ jmp stackless_SideBand_Read
+L11:
+ andl $(BLOCK_ENABLE_PG), %eax
+ jnz ConfigPci # Non-zero means bit set, we have the config we want so continue as normal
+ #
+ # Failed to config - store sticky bit debug
+ #
+ movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L12, %esp
+ jmp stackless_SideBand_Read
+L12:
+ orl $(RESET_FOR_ESRAM_LOCK), %eax # Set the bit we're interested in
+ movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L13, %esp
+ jmp stackless_SideBand_Write
+L13:
+ jmp IssueWarmReset
+
+ #
+ # Enable PCIEXBAR
+ #
+ConfigPci:
+ movl $(EC_BASE + EC_ENABLE), %eax # Data
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L14, %esp
+ jmp stackless_SideBand_Write
+L14:
+
+ movl $(EC_BASE + EC_ENABLE), %eax # Data
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L15, %esp
+ jmp stackless_SideBand_Write
+L15:
+
+ #
+ # Open up full 8MB SPI decode
+ #
+ movl $(PCI_CFG | (ILB_PFA << 8) | BDE), %ebx # PCI Configuration address
+ movl $(DECODE_ALL_REGIONS_ENABLE), %eax
+ leal L16, %esp
+ jmp stackless_PCIConfig_Write
+L16:
+
+ #
+ # Restore return address
+ #
+ movl %ebp, %esp
+ RET32
+
+IssueWarmReset:
+ #
+ # Issue Warm Reset request to Remote Management Unit via iLB
+ #
+ movw $(CF9_WARM_RESET), %ax
+ movw $(ILB_RESET_REG), %dx
+ outw %ax, %dx
+ jmp . # Stay here until we are reset.
+
+IssueColdReset:
+ #
+ # Issue Cold Reset request to Remote Management Unit via iLB
+ #
+ movw $(CF9_COLD_RESET), %ax
+ movw $(ILB_RESET_REG), %dx
+ outw %ax, %dx
+ jmp . # Stay here until we are reset.
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_SideBand_Read
+#
+# Input: esp - return address
+# ecx[15:8] - Register offset
+# ecx[23:16] - Port ID
+# ecx[31:24] - Opcode
+#
+# Output: eax - Data read
+#
+# Destroys:
+# eax
+# ebx
+# cl
+# esi
+#
+# Description:
+# Perform requested sideband read
+#
+#----------------------------------------------------------------------------
+stackless_SideBand_Read:
+
+ movl %esp, %esi # Save the return address
+
+ #
+ # Load the SideBand Packet Register to generate the transaction
+ #
+ movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
+ movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
+ xchgl %ecx, %eax
+ leal L17, %esp
+ jmp stackless_PCIConfig_Write
+L17:
+ xchgl %ecx, %eax
+
+ #
+ # Read the SideBand Data Register
+ #
+ movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
+ leal L18, %esp
+ jmp stackless_PCIConfig_Read
+L18:
+
+ movl %esi, %esp # Restore the return address
+ RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_SideBand_Write
+#
+# Input: esp - return address
+# eax - Data
+# ecx[15:8] - Register offset
+# ecx[23:16] - Port ID
+# ecx[31:24] - Opcode
+#
+# Output: None
+#
+# Destroys:
+# ebx
+# cl
+# esi
+#
+# Description:
+# Perform requested sideband write
+#
+#
+#----------------------------------------------------------------------------
+stackless_SideBand_Write:
+
+ movl %esp, %esi # Save the return address
+
+ #
+ # Load the SideBand Data Register with the data
+ #
+ movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
+ leal L19, %esp
+ jmp stackless_PCIConfig_Write
+L19:
+
+ #
+ # Load the SideBand Packet Register to generate the transaction
+ #
+ movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
+ movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
+ xchgl %ecx, %eax
+ leal L20, %esp
+ jmp stackless_PCIConfig_Write
+L20:
+ xchgl %ecx, %eax
+
+ movl %esi, %esp # Restore the return address
+ RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_PCIConfig_Write
+#
+# Input: esp - return address
+# eax - Data to write
+# ebx - PCI Config Address
+#
+# Output: None
+#
+# Destroys:
+# dx
+#
+# Description:
+# Perform a DWORD PCI Configuration write
+#
+#----------------------------------------------------------------------------
+stackless_PCIConfig_Write:
+
+ #
+ # Write the PCI Config Address to the address port
+ #
+ xchgl %ebx, %eax
+ movw $(PCI_ADDRESS_PORT), %dx
+ outl %eax, %dx
+ xchgl %ebx, %eax
+
+ #
+ # Write the PCI DWORD Data to the data port
+ #
+ movw $(PCI_DATA_PORT), %dx
+ outl %eax, %dx
+
+ RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_PCIConfig_Read
+#
+# Input: esp - return address
+# ebx - PCI Config Address
+#
+# Output: eax - Data read
+#
+# Destroys:
+# eax
+# dx
+#
+# Description:
+# Perform a DWORD PCI Configuration read
+#
+#----------------------------------------------------------------------------
+stackless_PCIConfig_Read:
+
+ #
+ # Write the PCI Config Address to the address port
+ #
+ xchgl %ebx, %eax
+ movw $(PCI_ADDRESS_PORT), %dx
+ outl %eax, %dx
+ xchgl %ebx, %eax
+
+ #
+ # Read the PCI DWORD Data from the data port
+ #
+ movw $(PCI_DATA_PORT), %dx
+ inl %dx, %eax
+
+ RET32
+
+#----------------------------------------------------------------------------
+#
+# Procedure: AsmValidateModuleCallBack
+#
+# Input: Refer to ValidateModuleCallBack
+#
+# Output: This function never returns
+#
+# Destroys: None
+#
+# Description:
+# Jump to ValidateModuleCallBack 'C' function
+#
+#----------------------------------------------------------------------------
+.byte 0x56,0x61,0x6c,0x69,0x64,0x61,0x74,0x65,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x43,0x61,0x6c,0x6c,0x42,0x61,0x63,0x6b #'ValidateModuleCallBack'
+AsmValidateModuleCallBack:
+ jmp ValidateModuleCallBack
+
+#----------------------------------------------------------------------------
+#
+# Procedure: AsmValidateKeyModCallBack
+#
+# Input: Refer to ValidateKeyModCallBack
+#
+# Output: This function never returns
+#
+# Destroys: None
+#
+# Description:
+# Jump to ValidateKeyModCallBack 'C' function
+#
+#----------------------------------------------------------------------------
+.byte 0x56,0x61,0x6c,0x69,0x64,0x61,0x74,0x65,0x4b,0x65,0x79,0x4d,0x6f,0x64,0x43,0x61,0x6c,0x6c,0x42,0x61,0x63,0x6b #'ValidateKeyModCallBack'
+AsmValidateKeyModCallBack:
+ jmp ValidateKeyModCallBack
+
+#
+# ROM-based Global-Descriptor Table for the Tiano PEI Phase
+#
+.align 16
+#
+# GDT[0]: 000h: Null entry, never used.
+#
+.equ NULL_SEL, . - GDT_BASE # Selector [0]
+GDT_BASE:
+BootGdtTable:
+ .long 0
+ .long 0
+#
+# Linear code segment descriptor
+#
+.equ LINEAR_CODE_SEL, . - GDT_BASE # Selector [08h]
+ .word 0xFFFF # limit 0FFFFh
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9B # present, ring 0, data, expand-up, not-writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+#
+# System data segment descriptor
+#
+.equ SYS_DATA_SEL, . - GDT_BASE # Selector [010h]
+ .word 0xFFFF # limit 0FFFFh
+ .word 0 # base 0
+ .byte 0
+ .byte 0x93 # present, ring 0, data, expand-up, not-writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+.equ GDT_SIZE, . - BootGdtTable # Size, in bytes
+
+#
+# GDT Descriptor
+#
+GdtDesc: # GDT descriptor
+ .word GDT_SIZE - 1
+ .long BootGdtTable
+
+ProtectedModeEntryLinearAddress:
+ProtectedModeEntryLinearOffset:
+ .long ProtectedModeEntryPoint
+ .word LINEAR_CODE_SEL
diff --git a/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Flat32.asm b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Flat32.asm
new file mode 100644
index 0000000..c892ebe
--- /dev/null
+++ b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Flat32.asm
@@ -0,0 +1,669 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; Flat32.asm
+;
+; Abstract:
+;
+; This is the code that goes from real-mode to protected mode.
+; It consumes the reset vector, configures the stack.
+;
+;
+;------------------------------------------------------------------------------
+
+
+;
+; Define assembler characteristics
+;
+.586p
+.model flat, c
+
+INCLUDE Platform.inc
+
+PlatformCopyBootStage1ImageToSramAndCall PROTO C
+PlatformIsForceRecoveryConditionsMet PROTO C
+
+;
+; CR0 cache control bit definition
+;
+CR0_CACHE_DISABLE EQU 040000000h
+CR0_NO_WRITE EQU 020000000h
+
+EXTERN ValidateModuleCallBack:NEAR
+EXTERN ValidateKeyModCallBack:NEAR
+
+;
+; Contrary to the name, this file contains 16 bit code as well.
+;
+_TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
+
+;----------------------------------------------------------------------------
+;
+; Procedure: _ModuleEntryPoint
+;
+; Input: None
+;
+; Output: None
+;
+; Destroys: Assume all registers
+;
+; Description:
+;
+; 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 a while in PEI and possibly DXE.
+;
+; After enabling protected mode, a far jump is executed to
+; transfer to PEI using the newly loaded GDT.
+;
+; Return: None
+;
+;----------------------------------------------------------------------------
+align 16
+_ModuleEntryPoint PROC C PUBLIC
+
+ ;
+ ; Warm Reset (INIT#) check.
+ ;
+ mov si, 0F000h
+ mov ds, si
+ mov si, 0FFF0h
+ cmp BYTE PTR [si], 0EAh ; Is it warm reset ?
+ jne NotWarmReset ; JIf not.
+
+ mov al, 08
+ mov dx, 0cf9h
+ out dx, al
+ mov al, 055h
+ out 080h, al;
+ jmp $
+NotWarmReset:
+
+ ;
+ ; Load the GDT table in GdtDesc
+ ;
+ mov esi, OFFSET GdtDesc
+ db 66h
+ lgdt fword ptr cs:[si]
+
+ ;
+ ; Transition to 16 bit protected mode
+ ;
+ 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
+
+ ;
+ ; Now we're in 16 bit protected mode
+ ; Set up the selectors for 32 bit protected mode entry
+ ;
+ mov ax, SYS_DATA_SEL
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ ;
+ ; Transition to Flat 32 bit protected mode
+ ; The jump to a far pointer causes the transition to 32 bit mode
+ ;
+ mov esi, offset ProtectedModeEntryLinearAddress
+ jmp fword ptr cs:[si]
+
+_ModuleEntryPoint ENDP
+
+_TEXT_REALMODE ENDS
+
+.code
+;
+; Protected mode portion initializes stack, configures cache, and calls C entry point
+;
+
+;----------------------------------------------------------------------------
+;
+; Procedure: ProtectedModeEntryPoint
+;
+; Input: Executing in 32 Bit Protected (flat) mode
+; cs: 0-4GB
+; ds: 0-4GB
+; es: 0-4GB
+; fs: 0-4GB
+; gs: 0-4GB
+; ss: 0-4GB
+;
+; Output: This function never returns
+;
+; Destroys:
+; ecx
+; edi
+; esi
+; esp
+;
+; Description:
+; Perform any essential early platform initilaisation
+; Setup a stack
+; Transfer control to EDKII code in eSRAM
+;
+;----------------------------------------------------------------------------
+
+ProtectedModeEntryPoint PROC NEAR C PUBLIC
+
+ JMP32 stackless_EarlyPlatformInit
+
+ ;
+ ; Set up stack pointer
+ ;
+ mov esp, QUARK_STACK_BASE_ADDRESS
+ mov esi, QUARK_STACK_SIZE_BYTES
+ add esp, esi ; ESP = top of stack (stack grows downwards).
+
+ ;
+ ; Check if force recovery conditions met.
+ ;
+ call PlatformIsForceRecoveryConditionsMet
+ test eax, eax
+ jz NormalBoot
+
+ ;
+ ; Copy fixed recovery image to SRAM and call it.
+ ; eax has address of routine to copy Fixed Recovery image to SRAM and call it.
+ ; copy this routine to QUARK_STACK_BASE_ADDRESS, we have just setup the stack
+ ; so it won't reach down to QUARK_STACK_BASE_ADDRESS yet.
+ ; Doing this since we don't want the copy routine to copy over itself.
+ ;
+ mov ecx, 000000100h ; 256 DWORDs = 1K
+ mov edi, QUARK_STACK_BASE_ADDRESS ; The destination address in QUARK_STACK_BASE_ADDRESS.
+CopyRoutineLoop:
+ mov ebx, DWORD PTR ds:[eax]
+ mov DWORD PTR ds:[edi], ebx
+ add eax, 04h
+ add edi, 04h
+ loopd CopyRoutineLoop
+
+ ;
+ ; call routine which will copy & call fixed recovery image.
+ ;
+ mov eax, QUARK_STACK_BASE_ADDRESS
+ call eax
+
+ ;
+ ; Forever loop at end of last routine so should not return here.
+ ;
+ jmp $
+
+NormalBoot:
+
+ ;
+ ; Copy and call Stage1 code to bottom of eSRAM and call it
+ ;
+ call PlatformCopyBootStage1ImageToSramAndCall
+
+ ;
+ ; Forever loop at end of last routine so should not return here.
+ ;
+ jmp $
+
+ProtectedModeEntryPoint ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_EarlyPlatformInit
+;
+; Input: esp - Return address
+;
+; Output: None
+;
+; Destroys:
+; eax
+; ecx
+; dx
+; ebp
+;
+; Description:
+; Any essential early platform initialisation required:
+; (1) Disable Cache
+; (2) Disable NMI's/SMI's
+; (3) Setup HMBOUND (defines what memory accesses go to MMIO/RAM)
+; (4) Setup eSRAM (provide early memory to the system)
+; (5) Setup PCIEXBAR access mechanism
+; (6) Open up full SPI flash decode
+;
+;----------------------------------------------------------------------------
+stackless_EarlyPlatformInit PROC NEAR C PUBLIC
+
+ ;
+ ; Save return address
+ ;
+ mov ebp, esp
+
+ ;
+ ; Ensure cache is disabled.
+ ;
+ mov eax, cr0
+ or eax, CR0_CACHE_DISABLE + CR0_NO_WRITE
+ invd
+ mov cr0, eax
+
+ ;
+ ; Disable NMI
+ ; Good convention suggests you should read back RTC data port after
+ ; accessing the RTC index port.
+ ;
+ mov al, NMI_DISABLE
+ mov dx, RTC_INDEX
+ out dx, al
+ mov dx, RTC_DATA
+ in al, dx
+
+ ;
+ ; Disable SMI (Disables SMI wire, not SMI messages)
+ ;
+ mov ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMISC2_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Read
+ and eax, NOT (SMI_EN)
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMISC2_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+ ;
+ ; Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
+ ;
+ mov ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGNONSTICKY_W1_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Read
+ and eax, FORCE_WARM_RESET
+ jz TestForceColdReset ; Zero means bit clear, we're not requested to warm reset so continue as normal
+ jmp IssueWarmReset
+
+TestForceColdReset:
+ mov ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_W1_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Read
+ and eax, FORCE_COLD_RESET
+ jz TestHmboundLock ; Zero means bit clear, we're not requested to cold reset so continue as normal
+ jmp IssueColdReset
+
+ ;
+ ; Before setting HMBOUND, check it's not locked
+ ;
+TestHmboundLock:
+ mov ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Read
+ and eax, HMBOUND_LOCK
+ jz ConfigHmbound ; Zero means bit clear, we have the config we want so continue as normal
+ ;
+ ; Failed to config - store sticky bit debug
+ ;
+ mov ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Read
+ or eax, RESET_FOR_HMBOUND_LOCK ; Set the bit we're interested in
+ mov ecx, (OPCODE_SIDEBAND_ALT_REG_WRITE SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+ jmp IssueWarmReset
+
+ ;
+ ; Set up the HMBOUND register
+ ;
+ConfigHmbound:
+ mov eax, HMBOUND_ADDRESS ; Data (Set HMBOUND location)
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+ ;
+ ; Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
+ ;
+ mov eax, ENABLE_IMR_INTERRUPT ; Data (Set interrupt enable mask)
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (BIMRVCTL_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+ ;
+ ; Move eSRAM memory to 2GB
+ ;
+ mov eax, ESRAM_ADDRESS_2G ; Data (Set eSRAM location)
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (ESRAMPGCTRL_BLOCK_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+ ;
+ ; Check that we're not blocked from setting the config that we want.
+ ;
+ mov ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (ESRAMPGCTRL_BLOCK_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Read
+ and eax, BLOCK_ENABLE_PG
+ jnz ConfigPci ; Non-zero means bit set, we have the config we want so continue as normal
+ ;
+ ; Failed to config - store sticky bit debug
+ ;
+ mov ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Read
+ or eax, RESET_FOR_ESRAM_LOCK ; Set the bit we're interested in
+ mov ecx, (OPCODE_SIDEBAND_ALT_REG_WRITE SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+ jmp IssueWarmReset
+
+ ;
+ ; Enable PCIEXBAR
+ ;
+ConfigPci:
+ mov eax, (EC_BASE + EC_ENABLE) ; Data
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_ARBITER_PORT_ID SHL SB_PORT_FIELD) OR (AEC_CTRL_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+ mov eax, (EC_BASE + EC_ENABLE) ; Data
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HECREG_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+ ;
+ ; Open up full 8MB SPI decode
+ ;
+ mov ebx, PCI_CFG OR (ILB_PFA SHL 8) OR BDE ; PCI Configuration address
+ mov eax, DECODE_ALL_REGIONS_ENABLE
+ JMP32 stackless_PCIConfig_Write
+
+ ;
+ ; Restore return address
+ ;
+ mov esp, ebp
+ RET32
+
+IssueWarmReset:
+ ;
+ ; Issue Warm Reset request to Remote Management Unit via iLB
+ ;
+ mov ax, CF9_WARM_RESET
+ mov dx, ILB_RESET_REG
+ out dx, ax
+ jmp $ ; Stay here until we are reset.
+
+IssueColdReset:
+ ;
+ ; Issue Cold Reset request to Remote Management Unit via iLB
+ ;
+ mov ax, CF9_COLD_RESET
+ mov dx, ILB_RESET_REG
+ out dx, ax
+ jmp $ ; Stay here until we are reset.
+
+stackless_EarlyPlatformInit ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_SideBand_Read
+;
+; Input: esp - return address
+; ecx[15:8] - Register offset
+; ecx[23:16] - Port ID
+; ecx[31:24] - Opcode
+;
+; Output: eax - Data read
+;
+; Destroys:
+; eax
+; ebx
+; cl
+; esi
+;
+; Description:
+; Perform requested sideband read
+;
+;----------------------------------------------------------------------------
+stackless_SideBand_Read PROC NEAR C PUBLIC
+
+ mov esi, esp ; Save the return address
+
+ ;
+ ; Load the SideBand Packet Register to generate the transaction
+ ;
+ mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG ; PCI Configuration address
+ mov cl, (ALL_BYTE_EN SHL SB_BE_FIELD) ; Set all Byte Enable bits
+ xchg eax, ecx
+ JMP32 stackless_PCIConfig_Write
+ xchg eax, ecx
+
+ ;
+ ; Read the SideBand Data Register
+ ;
+ mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG ; PCI Configuration address
+ JMP32 stackless_PCIConfig_Read
+
+ mov esp, esi ; Restore the return address
+ RET32
+
+stackless_SideBand_Read ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_SideBand_Write
+;
+; Input: esp - return address
+; eax - Data
+; ecx[15:8] - Register offset
+; ecx[23:16] - Port ID
+; ecx[31:24] - Opcode
+;
+; Output: None
+;
+; Destroys:
+; ebx
+; cl
+; esi
+;
+; Description:
+; Perform requested sideband write
+;
+;
+;----------------------------------------------------------------------------
+stackless_SideBand_Write PROC NEAR C PUBLIC
+
+ mov esi, esp ; Save the return address
+
+ ;
+ ; Load the SideBand Data Register with the data
+ ;
+ mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG ; PCI Configuration address
+ JMP32 stackless_PCIConfig_Write
+
+ ;
+ ; Load the SideBand Packet Register to generate the transaction
+ ;
+ mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG ; PCI Configuration address
+ mov cl, (ALL_BYTE_EN SHL SB_BE_FIELD) ; Set all Byte Enable bits
+ xchg eax, ecx
+ JMP32 stackless_PCIConfig_Write
+ xchg eax, ecx
+
+ mov esp, esi ; Restore the return address
+ RET32
+
+stackless_SideBand_Write ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_PCIConfig_Write
+;
+; Input: esp - return address
+; eax - Data to write
+; ebx - PCI Config Address
+;
+; Output: None
+;
+; Destroys:
+; dx
+;
+; Description:
+; Perform a DWORD PCI Configuration write
+;
+;----------------------------------------------------------------------------
+stackless_PCIConfig_Write PROC NEAR C PUBLIC
+
+ ;
+ ; Write the PCI Config Address to the address port
+ ;
+ xchg eax, ebx
+ mov dx, PCI_ADDRESS_PORT
+ out dx, eax
+ xchg eax, ebx
+
+ ;
+ ; Write the PCI DWORD Data to the data port
+ ;
+ mov dx, PCI_DATA_PORT
+ out dx, eax
+
+ RET32
+
+stackless_PCIConfig_Write ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_PCIConfig_Read
+;
+; Input: esp - return address
+; ebx - PCI Config Address
+;
+; Output: eax - Data read
+;
+; Destroys:
+; eax
+; dx
+;
+; Description:
+; Perform a DWORD PCI Configuration read
+;
+;----------------------------------------------------------------------------
+stackless_PCIConfig_Read PROC NEAR C PUBLIC
+
+ ;
+ ; Write the PCI Config Address to the address port
+ ;
+ xchg eax, ebx
+ mov dx, PCI_ADDRESS_PORT
+ out dx, eax
+ xchg eax, ebx
+
+ ;
+ ; Read the PCI DWORD Data from the data port
+ ;
+ mov dx, PCI_DATA_PORT
+ in eax, dx
+
+ RET32
+
+stackless_PCIConfig_Read ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: AsmValidateModuleCallBack
+;
+; Input: Refer to ValidateModuleCallBack
+;
+; Output: This function never returns
+;
+; Destroys: None
+;
+; Description:
+; Jump to ValidateModuleCallBack 'C' function
+;
+;----------------------------------------------------------------------------
+VALIDATE_MODULE_ENTRY_SIGNATURE DB 01h DUP ('ValidateModuleCallBack')
+AsmValidateModuleCallBack PROC NEAR C PUBLIC
+
+ jmp ValidateModuleCallBack
+
+AsmValidateModuleCallBack ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: AsmValidateKeyModCallBack
+;
+; Input: Refer to ValidateKeyModCallBack
+;
+; Output: This function never returns
+;
+; Destroys: None
+;
+; Description:
+; Jump to ValidateKeyModCallBack 'C' function
+;
+;----------------------------------------------------------------------------
+VALIDATE_KEYMOD_ENTRY_SIGNATURE DB 01h DUP ('ValidateKeyModCallBack')
+AsmValidateKeyModCallBack PROC NEAR C PUBLIC
+ jmp ValidateKeyModCallBack
+AsmValidateKeyModCallBack ENDP
+
+;
+; SPI-based Global-Descriptor Table for the Tiano PEI Phase
+;
+align 16
+PUBLIC BootGdtTable
+
+;
+; GDT[0]: 0x00: Null entry, never used.
+;
+NULL_SEL equ $ - GDT_BASE ; Selector [0]
+GDT_BASE:
+BootGdtTable DD 0
+ DD 0
+;
+; Linear code segment descriptor
+;
+LINEAR_CODE_SEL equ $ - GDT_BASE ; Selector [0x8]
+ DW 0FFFFh ; limit 0xFFFF
+ 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 [0x10]
+ DW 0FFFFh ; limit 0xFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 093h ; present, ring 0, data, expand-up, not-writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+
+GDT_SIZE EQU $ - BootGDTtable ; Size, in bytes
+
+;
+; GDT Descriptor
+;
+GdtDesc: ; GDT descriptor
+ DW GDT_SIZE - 1 ; GDT limit
+ DD OFFSET BootGdtTable ; GDT base address
+
+ProtectedModeEntryLinearAddress LABEL FWORD
+ProtectedModeEntryLinearOffset LABEL DWORD
+ DD OFFSET ProtectedModeEntryPoint ; Offset of our 32 bit code
+ DW LINEAR_CODE_SEL
+
+END
diff --git a/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Platform.inc b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Platform.inc
new file mode 100644
index 0000000..dac72ae
--- /dev/null
+++ b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/Platform.inc
@@ -0,0 +1,162 @@
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;------------------------------------------------------------------------------
+;
+; Module Name:
+;
+; Platform.inc
+;
+; Abstract:
+;
+; Quark A0 Platform Specific Definitions
+;
+;------------------------------------------------------------------------------
+
+JMP32 MACRO FunctionName
+ lea esp, @F
+ jmp FunctionName
+@@:
+ENDM
+
+RET32 MACRO
+ jmp esp
+ENDM
+
+;
+; ROM/SPI/MEMORY Definitions
+;
+QUARK_DDR3_MEM_BASE_ADDRESS EQU 000000000h ; Memory Base Address = 0
+QUARK_MAX_DDR3_MEM_SIZE_BYTES EQU 080000000h ; DDR3 Memory Size = 2GB
+QUARK_ESRAM_MEM_BASE_ADDRESS EQU (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES) ; eSRAM Memory above DDR3
+QUARK_ESRAM_MEM_SIZE_BYTES EQU 000080000h ; eSRAM Memory Size = 512K
+QUARK_STACK_SIZE_BYTES EQU 008000h ; Quark stack size = 32K
+QUARK_STACK_BASE_ADDRESS EQU (QUARK_ESRAM_MEM_BASE_ADDRESS+QUARK_ESRAM_MEM_SIZE_BYTES)-QUARK_STACK_SIZE_BYTES ; Top of eSRAM - stack size
+QUARK_CMH_SIZE_BYTES EQU 0400h ; Quark Module Header size = 1024bytes
+QUARK_ESRAM_STAGE1_BASE_ADDRESS EQU (QUARK_ESRAM_MEM_BASE_ADDRESS + QUARK_CMH_SIZE_BYTES) ; Start of Stage1 code in eSRAM
+
+;
+; RTC/CMOS definitions
+;
+RTC_INDEX EQU 070h
+ NMI_DISABLE EQU 080h ; Bit7 disables NMI
+RTC_DATA EQU 071h
+
+;
+; PCI Configuration definitions
+;
+PCI_CFG EQU 1 SHL 01Fh ; PCI configuration access mechanism
+PCI_ADDRESS_PORT EQU 0CF8h
+PCI_DATA_PORT EQU 0CFCh
+
+;
+; Quark PCI devices
+;
+HOST_BRIDGE_PFA EQU 0000h ; B0:D0:F0 (Host Bridge)
+ILB_PFA EQU 00F8h ; B0:D31:F0 (Legacy Block)
+
+;
+; ILB PCI Config Registers
+;
+BDE EQU 0D4h ; BIOS Decode Enable register
+ DECODE_ALL_REGIONS_ENABLE EQU 0FF000000h ; Decode all BIOS decode ranges
+
+
+;
+; iLB Reset Register
+;
+ILB_RESET_REG EQU 0CF9h
+ CF9_WARM_RESET EQU 02h
+ CF9_COLD_RESET EQU 08h
+
+;
+; Host Bridge PCI Config Registers
+;
+MESSAGE_BUS_CONTROL_REG EQU 0D0h ; Message Bus Control Register
+ SB_OPCODE_FIELD EQU 018h ; Bit location of Opcode field
+ OPCODE_SIDEBAND_REG_READ EQU 010h ; Read opcode
+ OPCODE_SIDEBAND_REG_WRITE EQU 011h ; Write opcode
+ OPCODE_SIDEBAND_ALT_REG_READ EQU 06h ; Alternate Read opcode
+ OPCODE_SIDEBAND_ALT_REG_WRITE EQU 07h ; Alternate Write opcode
+ OPCODE_WARM_RESET_REQUEST EQU 0F4h ; Reset Warm
+ OPCODE_COLD_RESET_REQUEST EQU 0F5h ; Reset Cold
+ SB_PORT_FIELD EQU 010h ; Bit location of Port ID field
+ MEMORY_ARBITER_PORT_ID EQU 00h
+ HOST_BRIDGE_PORT_ID EQU 03h
+ RMU_PORT_ID EQU 04h
+ MEMORY_MANAGER_PORT_ID EQU 05h
+ SOC_UNIT_PORT_ID EQU 031h
+ SB_ADDR_FIELD EQU 008h ; Bit location of Register field
+ SB_BE_FIELD EQU 004h ; Bit location of Byte Enables field
+ ALL_BYTE_EN EQU 00Fh ; All Byte Enables
+MESSAGE_DATA_REG EQU 0D4h ; Message Data Register
+
+;
+; Memory Arbiter Config Registers
+;
+AEC_CTRL_OFFSET EQU 00h
+
+;
+; Host Bridge Config Registers
+;
+HMISC2_OFFSET EQU 03h
+ OR_PM_FIELD EQU 010h
+ SMI_EN EQU 1 SHL 13h
+
+HMBOUND_OFFSET EQU 08h
+ HMBOUND_ADDRESS EQU (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
+ HMBOUND_LOCK EQU 00000001h
+HECREG_OFFSET EQU 09h
+ EC_BASE EQU 0E0000000h
+ EC_ENABLE EQU 01h
+
+
+;
+; Memory Manager Config Registers
+;
+ESRAMPGCTRL_BLOCK_OFFSET EQU 082h
+ BLOCK_ENABLE_PG EQU 010000000h
+ ESRAM_ADDRESS_2G EQU ((01h SHL 1Ch) + (QUARK_ESRAM_MEM_BASE_ADDRESS SHR 18h))
+BIMRVCTL_OFFSET EQU 019h
+ ENABLE_IMR_INTERRUPT EQU 080000000h
+
+;
+; SOC UNIT Debug Registers
+;
+CFGSTICKY_W1_OFFSET EQU 050h
+ FORCE_COLD_RESET EQU 00000001h
+CFGSTICKY_RW_OFFSET EQU 051h
+ RESET_FOR_ESRAM_LOCK EQU 00000020h
+ RESET_FOR_HMBOUND_LOCK EQU 00000040h
+CFGNONSTICKY_W1_OFFSET EQU 052h
+ FORCE_WARM_RESET EQU 00000001h
+
+
+
+
diff --git a/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/ResetVec.S16 b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/ResetVec.S16
new file mode 100644
index 0000000..699ee39
--- /dev/null
+++ b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/ResetVec.S16
@@ -0,0 +1,107 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# ResetVec.S16
+#
+# Abstract:
+#
+# Reset Vector Data structure
+# This structure is located at 0xFFFFFFD0
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX (_start)
+ASM_PFX(_start):
+#
+# This is located at 0xFFFFFFD0h
+#
+ .byte 0xBF, 0x50, 0x41 # mov di, "AP"
+ jmp ApStartup
+ .fill ValidateModuleCallBack - ., 1, 0
+
+ .align 16
+#
+# Pointer to the entry point of the 'ValidateModuleCallBack' routine
+# 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.
+#
+ValidateModuleCallBack:
+ .long 0x87654321
+
+#
+# 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:
+ jmp .
+ iret
+ .fill ResetHandler - ., 1, 0
+
+ .align 16
+#
+# For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
+# Execution starts here upon power-on/platform-reset.
+#
+ResetHandler:
+ wbinvd
+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.
+ #
+ # Typically, SEC entry point is the function _ModuleEntryPoint() defined in
+ # SecEntry.asm
+ #
+ .byte 0xe9
+ .word -3
+ .fill ApSegAddress - ., 1, 0
+
+ .align 8
+#
+# 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:
+ .long 0x12345678
+
+#
+# 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:
+ .long 0x12345678
diff --git a/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/ResetVec.asm16 b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/ResetVec.asm16
new file mode 100644
index 0000000..86e2ade
--- /dev/null
+++ b/QuarkPlatformPkg/Cpu/Sec/ResetVector/Ia32/ResetVec.asm16
@@ -0,0 +1,118 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; ResetVec.asm
+;
+; Abstract:
+;
+; Reset Vector Data structure
+; This structure is located at 0xFFFFFFD0
+;
+;------------------------------------------------------------------------------
+
+ .model tiny
+ .686p
+ .stack 0h
+ .code
+
+;
+; The layout of this file is fixed. The build tool makes assumption of the layout.
+;
+
+ ORG 0h
+;
+; This is located at 0xFFFFFFD0h
+;
+ mov di, "AP"
+ jmp ApStartup
+
+ ORG 10h
+;
+; Pointer to the entry point of the 'ValidateModuleCallBack' routine
+; 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.
+;
+ValidateModuleCallBack 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 20h
+;
+; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
+; Execution starts here upon power-on/platform-reset.
+;
+ResetHandler:
+ wbinvd
+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.
+ ;
+ ; Typically, SEC entry point is the function _ModuleEntryPoint() defined in
+ ; SecEntry.asm
+ ;
+ DB 0e9h
+ DW -3
+
+
+ ORG 28h
+;
+; 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 2ch
+;
+; 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
+
+;
+; Nothing can go here, otherwise the layout of this file would change.
+;
+
+ END
diff --git a/QuarkPlatformPkg/Cpu/Sec/ResetVector/QuarkResetVector.inf b/QuarkPlatformPkg/Cpu/Sec/ResetVector/QuarkResetVector.inf
new file mode 100755
index 0000000..18a19cd
--- /dev/null
+++ b/QuarkPlatformPkg/Cpu/Sec/ResetVector/QuarkResetVector.inf
@@ -0,0 +1,74 @@
+## @file
+# This is the first module taking control of the platform upon power-on/reset.
+#
+# This module implements the first phase of Tiano - SEC. SecEntry.asm contains the entry point of this module.
+# Blank1.pad and Blank2.pad file tagged with "ToolCode="DUMMY"" is for adjusting alignment of VTF section.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QuarkResetVector
+ FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CallbackServices.c
+ CallbackServices.h
+
+[Sources.IA32]
+ Ia32/ResetVec.asm16 | MSFT
+ Ia32/ResetVec.S16 | GCC
+ Ia32/Flat32.asm
+ Ia32/Flat32.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ PlatformSecServicesLib
+
+[Ppis]
+
+[FixedPcd]
diff --git a/QuarkPlatformPkg/Include/CommonIncludes.h b/QuarkPlatformPkg/Include/CommonIncludes.h
new file mode 100644
index 0000000..c1a4705
--- /dev/null
+++ b/QuarkPlatformPkg/Include/CommonIncludes.h
@@ -0,0 +1,142 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ CommonIncludes.h
+
+Abstract:
+
+ This file defines common equates.
+
+--*/
+
+#ifndef _COMMON_INCLUDES_H_
+#define _COMMON_INCLUDES_H_
+
+//#include "BackCompatible.h"
+
+#define V_INTEL_VID 0x8086
+
+//
+// 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 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
+
+#define BIT63 0x8000000000000000
+#define BIT62 0x4000000000000000
+#define BIT61 0x2000000000000000
+#define BIT60 0x1000000000000000
+#define BIT59 0x0800000000000000
+#define BIT58 0x0400000000000000
+#define BIT57 0x0200000000000000
+#define BIT56 0x0100000000000000
+#define BIT55 0x0080000000000000
+#define BIT54 0x0040000000000000
+#define BIT53 0x0020000000000000
+#define BIT52 0x0010000000000000
+#define BIT51 0x0008000000000000
+#define BIT50 0x0004000000000000
+#define BIT49 0x0002000000000000
+#define BIT48 0x0001000000000000
+#define BIT47 0x0000800000000000
+#define BIT46 0x0000400000000000
+#define BIT45 0x0000200000000000
+#define BIT44 0x0000100000000000
+#define BIT43 0x0000080000000000
+#define BIT42 0x0000040000000000
+#define BIT41 0x0000020000000000
+#define BIT40 0x0000010000000000
+#define BIT39 0x0000008000000000
+#define BIT38 0x0000004000000000
+#define BIT37 0x0000002000000000
+#define BIT36 0x0000001000000000
+#define BIT35 0x0000000800000000
+#define BIT34 0x0000000400000000
+#define BIT33 0x0000000200000000
+#define BIT32 0x0000000100000000
+#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))
+
+//
+// Align length up to the next step.
+//
+#define ALIGN_LENGTH(len, step) (((UINTN)(len) + (((step) - ((UINTN) (len))) & ((step) - 1))))
+
+#endif
+
diff --git a/QuarkPlatformPkg/Include/Cpu/CpuRegs.h b/QuarkPlatformPkg/Include/Cpu/CpuRegs.h
new file mode 100644
index 0000000..93d4fc1
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Cpu/CpuRegs.h
@@ -0,0 +1,60 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ CpuRegs.h
+
+Abstract:
+
+--*/
+
+#ifndef _CPU_REGS_H_
+#define _CPU_REGS_H_
+
+#include <CommonIncludes.h>
+
+#define EFI_CPUID_VERSION_INFO 0x1
+#define EFI_CPUID_EXTENDED_FUNCTION 0x80000000
+#define EFI_CPUID_VIR_PHY_ADDRESS_SIZE 0x80000008
+
+#define EFI_IA32_MTRR_CAP 0x000000FE
+#define B_EFI_IA32_MTRR_VARIABLE_SUPPORT 0xFF
+
+#define EFI_CACHE_VARIABLE_MTRR_BASE 0x00000200
+
+typedef struct {
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+} EFI_CPUID_REGISTER;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/EfiFlashMap.h b/QuarkPlatformPkg/Include/EfiFlashMap.h
new file mode 100644
index 0000000..e6a2d09
--- /dev/null
+++ b/QuarkPlatformPkg/Include/EfiFlashMap.h
@@ -0,0 +1,148 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ EfiFlashMap.h
+
+Abstract:
+
+ Defines for the EFI Flash Map functionality
+
+--*/
+
+#ifndef _EFI_FLASH_MAP_H_
+#define _EFI_FLASH_MAP_H_
+
+#include <Pi/PiHob.h>
+
+//
+// Definition for flash map GUIDed HOBs
+//
+typedef UINT32 EFI_FLASH_AREA_ATTRIBUTES;
+
+#define EFI_FLASH_AREA_FV 0x0001
+#define EFI_FLASH_AREA_SUBFV 0x0002
+#define EFI_FLASH_AREA_MEMMAPPED_FV 0x0004
+#define EFI_FLASH_AREA_REQUIRED 0x0008
+#define EFI_FLASH_AREA_CORRUPT 0x0010
+
+typedef UINT8 EFI_FLASH_AREA_TYPE;
+
+#define EFI_FLASH_AREA_RECOVERY_BIOS 0x0 // Recovery code
+#define EFI_FLASH_AREA_MAIN_BIOS 0x1 // Regular BIOS code
+#define EFI_FLASH_AREA_PAL_B 0x2 // PAL-B
+#define EFI_FLASH_AREA_RESERVED_03 0x3 // Reserved for backwards compatibility
+#define EFI_FLASH_AREA_RESERVED_04 0x4 // Reserved for backwards compatibility
+#define EFI_FLASH_AREA_DMI_FRU 0x5 // DMI FRU information
+#define EFI_FLASH_AREA_OEM_BINARY 0x6 // OEM Binary Code/data
+#define EFI_FLASH_AREA_RESERVED_07 0x7 // Reserved for backwards compatibility
+#define EFI_FLASH_AREA_RESERVED_08 0x8 // Reserved for backwards compatibility
+#define EFI_FLASH_AREA_RESERVED_09 0x9 // Reserved for backwards compatibility
+#define EFI_FLASH_AREA_RESERVED_0A 0x0a // Reserved for backwards compatibility
+#define EFI_FLASH_AREA_EFI_VARIABLES 0x0b // EFI variables
+#define EFI_FLASH_AREA_MCA_LOG 0x0c // MCA error log
+#define EFI_FLASH_AREA_SMBIOS_LOG 0x0d // SMBIOS error log
+#define EFI_FLASH_AREA_FTW_BACKUP 0x0e // A backup block during FTW operations
+#define EFI_FLASH_AREA_FTW_STATE 0x0f // State information during FTW operations
+#define EFI_FLASH_AREA_UNUSED 0x0fd // Not used
+#define EFI_FLASH_AREA_GUID_DEFINED 0x0fe // Usage defined by a GUID
+#pragma pack(1)
+//
+// An individual sub-area Entry.
+// A single flash area may consist of more than one sub-area.
+//
+typedef struct {
+ EFI_FLASH_AREA_ATTRIBUTES Attributes;
+ UINT32 Reserved;
+ EFI_PHYSICAL_ADDRESS Base;
+ EFI_PHYSICAL_ADDRESS Length;
+ EFI_GUID FileSystem;
+} EFI_FLASH_SUBAREA_ENTRY;
+
+typedef struct {
+ UINT8 Reserved[3];
+ EFI_FLASH_AREA_TYPE AreaType;
+ EFI_GUID AreaTypeGuid;
+ UINT32 NumEntries;
+ EFI_FLASH_SUBAREA_ENTRY Entries[1];
+} EFI_FLASH_MAP_ENTRY_DATA;
+
+typedef struct {
+ UINT8 Reserved[3];
+ EFI_FLASH_AREA_TYPE AreaType;
+ EFI_GUID AreaTypeGuid;
+ UINT32 NumberOfEntries;
+ EFI_FLASH_SUBAREA_ENTRY Entries[1];
+ //
+ // Extended Hob data.
+ //
+ // VolumeId and FilePath indicating a unique file.
+ //
+ UINT32 VolumeId;
+ CHAR16 FilePath[256];
+ UINT32 ActuralSize;
+ UINT32 Offset;
+} EFI_FLASH_MAP_FS_ENTRY_DATA;
+
+typedef struct {
+ EFI_HOB_GENERIC_HEADER Header;
+ EFI_GUID Name;
+ UINT8 Reserved[3];
+ EFI_FLASH_AREA_TYPE AreaType;
+ EFI_GUID AreaTypeGuid;
+ UINT32 NumEntries;
+ EFI_FLASH_SUBAREA_ENTRY Entries[1];
+} EFI_HOB_FLASH_MAP_ENTRY_TYPE;
+
+//
+// Internal definitions
+//
+typedef struct {
+ UINT8 Reserved[3];
+ EFI_FLASH_AREA_TYPE AreaType;
+ EFI_GUID AreaTypeGuid;
+ UINT32 NumberOfEntries;
+ EFI_FLASH_SUBAREA_ENTRY SubAreaData;
+} EFI_FLASH_AREA_HOB_DATA;
+
+typedef struct {
+ UINTN Base;
+ UINTN Length;
+ EFI_FLASH_AREA_ATTRIBUTES Attributes;
+ EFI_FLASH_AREA_TYPE AreaType;
+ UINT8 Reserved[3];
+ EFI_GUID AreaTypeGuid;
+} EFI_FLASH_AREA_DATA;
+
+#pragma pack()
+
+#endif // #ifndef _EFI_FLASH_MAP_H_
diff --git a/QuarkPlatformPkg/Include/FlashLayout.h b/QuarkPlatformPkg/Include/FlashLayout.h
new file mode 100755
index 0000000..5056f2b
--- /dev/null
+++ b/QuarkPlatformPkg/Include/FlashLayout.h
@@ -0,0 +1,66 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ FlashLayout.h
+
+Abstract:
+
+ Platform specific flash layout.
+
+--*/
+
+#ifndef _FLASH_LAYOUT_H_
+#define _FLASH_LAYOUT_H_
+
+#include "EfiFlashMap.h"
+#include <FlashMap.h>
+
+//
+// Length of Efi Runtime Updatable Firmware Volume Header
+//
+#define EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH 0x48
+#define FLASH_BLOCK_SIZE 0x1000
+
+//
+// Flash supports 32K block size
+//
+#define FVB_MEDIA_BLOCK_SIZE FLASH_BLOCK_SIZE
+
+#define RUNTIME_FV_BASE_ADDRESS FLASH_REGION_RUNTIME_UPDATABLE_BASE
+#define RUNTIME_FV_LENGTH (FLASH_REGION_RUNTIME_UPDATABLE_SIZE + FLASH_REGION_NV_FTW_SPARE_SIZE)
+#define RUNTIME_FV_BLOCK_NUM (RUNTIME_FV_LENGTH / FVB_MEDIA_BLOCK_SIZE)
+
+#define FV_MAIN_BASE_ADDRESS FLASH_REGION_FVMAIN_BASE
+#define MAIN_BIOS_BLOCK_NUM (FLASH_REGION_FVMAIN_SIZE / FVB_MEDIA_BLOCK_SIZE)
+
+#endif
diff --git a/QuarkPlatformPkg/Include/FlashMap.h b/QuarkPlatformPkg/Include/FlashMap.h
new file mode 100644
index 0000000..eaee0a8
--- /dev/null
+++ b/QuarkPlatformPkg/Include/FlashMap.h
@@ -0,0 +1,172 @@
+//
+// Copyright (c) 2013 Intel Corporation.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _FLASH_MAP_H_
+#define _FLASH_MAP_H_
+
+#define FLASH_REGION_BOOTROM_OVERRIDE_MAX_SIZE 0x00020000 // 128K
+#define FLASH_REGION_BOOTROM_OVERRIDE_BASE 0xFFFE0000
+
+//
+// #defines based on Fixed PCDs.
+//
+
+#define FLASH_BASE (FixedPcdGet32 (PcdFlashAreaBaseAddress))
+#define FLASH_SIZE (FixedPcdGet32 (PcdFlashAreaSize))
+
+#define FLASH_REGION_FV_SECPEI_RECOVERY_BASE (FixedPcdGet32 (PcdFlashFvFixedStage1AreaBase) + FixedPcdGet32 (PcdFvSecurityHeaderSize))
+#define FLASH_REGION_FV_SECPEI_RECOVERY_SIZE (FixedPcdGet32 (PcdFlashFvFixedStage1AreaSize))
+#define FLASH_REGION_FV_SECPEI_RECOVERY_OFFSET (FLASH_REGION_FV_SECPEI_RECOVERY_BASE - FLASH_BASE)
+
+#define FLASH_REGION_BIOS_NV_STORAGE_BASE (FixedPcdGet32 (PcdFlashNvStorageBase))
+#define FLASH_REGION_BIOS_NV_STORAGE_SIZE (FixedPcdGet32 (PcdFlashNvStorageSize))
+
+//
+// Hard coded defines.
+//
+
+#define FLASH_REGION_RUNTIME_UPDATABLE_BASE (FixedPcdGet32 (PcdFlashNvStorageBase))
+#define FLASH_REGION_RUNTIME_UPDATABLE_SIZE 0x00010000
+#define FLASH_REGION_RUNTIME_UPDATABLE_OFFSET (FLASH_REGION_RUNTIME_UPDATABLE_BASE - FixedPcdGet32 (PcdFlashAreaBaseAddress))
+
+#define FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_BASE FLASH_REGION_RUNTIME_UPDATABLE_BASE
+#define FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_SIZE 0x0000E000
+#define FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_OFFSET FLASH_REGION_RUNTIME_UPDATABLE_OFFSET
+
+#define FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_BASE (FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_BASE + FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_SIZE)
+#define FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_SIZE 0x00002000
+#define FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_OFFSET (FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_OFFSET + FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_SIZE)
+
+#define FLASH_REGION_NV_FTW_SPARE_BASE (FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_BASE + FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_SIZE)
+#define FLASH_REGION_NV_FTW_SPARE_SIZE 0x00010000
+#define FLASH_REGION_NV_FTW_SPARE_OFFSET (FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_OFFSET + FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_SIZE)
+
+#define FLASH_REGION_OEM_NV_STORAGE_BASE (FLASH_REGION_BIOS_NV_STORAGE_BASE + FLASH_REGION_BIOS_NV_STORAGE_SIZE)
+#define FLASH_REGION_OEM_NV_STORAGE_SIZE 0x00000000
+
+//
+// #defines based on dynamic PCDs.
+// These PCDs should only be accessed after PlatformConfigPei has set them up.
+//
+
+#define FLASH_REGION_FVMAIN_BASE (PcdGet32 (PcdFlashFvMainBase))
+#define FLASH_REGION_FVMAIN_SIZE (PcdGet32 (PcdFlashFvMainSize))
+#define FLASH_REGION_FVMAIN_OFFSET (FLASH_REGION_FVMAIN_BASE - FLASH_BASE)
+
+#define FLASH_REGION_FV_SECPEI_NORMAL_BASE (PcdGet32 (PcdFlashFvRecoveryBase))
+#define FLASH_REGION_FV_SECPEI_NORMAL_SIZE (PcdGet32 (PcdFlashFvRecoverySize))
+#define FLASH_REGION_FV_SECPEI_NORMAL_OFFSET (FLASH_REGION_FV_SECPEI_NORMAL_BASE - FLASH_BASE)
+
+#define FLASH_REGION_FV_SECPEI_BASE FLASH_REGION_FV_SECPEI_NORMAL_BASE
+#define FLASH_REGION_FV_SECPEI_SIZE FLASH_REGION_FV_SECPEI_NORMAL_SIZE
+#define FLASH_REGION_FV_SECPEI_OFFSET FLASH_REGION_FV_SECPEI_NORMAL_OFFSET
+
+#define EFI_FLASH_AREA_DATA_DEFINITION \
+ /* FVMAIN region - Base/Size are Dynamic so determined at run time.*/\
+ {\
+ 0,\
+ 0,\
+ EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV,\
+ EFI_FLASH_AREA_MAIN_BIOS,\
+ 0, 0, 0,\
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\
+ },\
+ /* RUNTIME_UPDATABLE region */\
+ {\
+ FLASH_REGION_RUNTIME_UPDATABLE_BASE,\
+ FLASH_REGION_RUNTIME_UPDATABLE_SIZE,\
+ EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV,\
+ EFI_FLASH_AREA_GUID_DEFINED,\
+ 0, 0, 0,\
+ EFI_SYSTEM_NV_DATA_HOB_GUID, \
+ },\
+ /* NV_FTW_SPARE region */\
+ {\
+ FLASH_REGION_NV_FTW_SPARE_BASE,\
+ FLASH_REGION_NV_FTW_SPARE_SIZE,\
+ EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV,\
+ EFI_FLASH_AREA_FTW_BACKUP,\
+ 0, 0, 0,\
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\
+ },\
+ /* FV_SECPEI region - Base/Size are Dynamic so determined at run time.*/\
+ {\
+ 0,\
+ 0,\
+ EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV,\
+ EFI_FLASH_AREA_RECOVERY_BIOS,\
+ 0, 0, 0,\
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\
+ },\
+
+
+//
+// EFI_HOB_FLASH_MAP_ENTRY_TYPE definition
+//
+#define EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION \
+ /* RUNTIME_UPDATABLE.NV_VARIABLE_STORE Subregion */\
+ {\
+ EFI_HOB_TYPE_GUID_EXTENSION,\
+ sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\
+ 0,\
+ EFI_FLASH_MAP_HOB_GUID, \
+ 0, 0, 0,\
+ EFI_FLASH_AREA_EFI_VARIABLES,\
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\
+ 1,\
+ {\
+ EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV,\
+ 0,\
+ FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_BASE,\
+ FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_VARIABLE_STORE_SIZE,\
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\
+ },\
+ }, \
+ /* RUNTIME_UPDATABLE.NV_FTW_WORKING Subregion */\
+ {\
+ EFI_HOB_TYPE_GUID_EXTENSION,\
+ sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\
+ 0,\
+ EFI_FLASH_MAP_HOB_GUID, \
+ 0, 0, 0,\
+ EFI_FLASH_AREA_FTW_STATE,\
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\
+ 1,\
+ {\
+ EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV,\
+ 0,\
+ FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_BASE,\
+ FLASH_REGION_RUNTIME_UPDATABLE_SUBREGION_NV_FTW_WORKING_SIZE,\
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\
+ },\
+ },
+
+#endif // #ifndef _FLASH_MAP_H_
+
diff --git a/QuarkPlatformPkg/Include/Guid/AcpiVariable.h b/QuarkPlatformPkg/Include/Guid/AcpiVariable.h
new file mode 100644
index 0000000..fc8ec18
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/AcpiVariable.h
@@ -0,0 +1,187 @@
+// DEPRECATED: Moved to EDK II IntelFrameworkModulePkg/Include/Guid
+/** @file
+Provides the data format and Name and GUID definition for the EFI Variable ACPI_VARIABLE_SET and the Framework version's correponding
+EFI Variable.
+This variable is the persistent data that will be saved to NV EFI Variable. It is the central repository
+for configuration data saved by the CPU Driver, Platform SMM Handler. It is read by
+Platform PEIM and PEIM on S3 boot path to restore the system configuration.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _ACPI_VARIABLE_H_
+#define _ACPI_VARIABLE_H_
+
+#define EFI_ACPI_VARIABLE_GUID \
+ { \
+ 0xaf9ffd67, 0xec10, 0x488a, {0x9d, 0xfc, 0x6c, 0xbf, 0x5e, 0xe2, 0x2c, 0x2e } \
+ }
+
+#define ACPI_GLOBAL_VARIABLE L"AcpiGlobalVariable"
+
+#define EFI_ACPI_VARIABLE_COMPATIBILITY_GUID \
+ { \
+ 0xc020489e, 0x6db2, 0x4ef2, {0x9a, 0xa5, 0xca, 0x6, 0xfc, 0x11, 0xd3, 0x6a } \
+ }
+//
+// The following structure boosts performance by combining all ACPI related variables into one.
+//
+#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_COMPATIBILITY;
+
+typedef struct {
+ //
+ // Acpi Related variables
+ //
+ EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase;
+ UINT32 AcpiReservedMemorySize;
+ EFI_PHYSICAL_ADDRESS S3ReservedLowMemoryBase;
+ EFI_PHYSICAL_ADDRESS AcpiBootScriptTable;
+ EFI_PHYSICAL_ADDRESS RuntimeScriptTableBase;
+ EFI_PHYSICAL_ADDRESS AcpiFacsTable;
+ UINT64 SystemMemoryLength;
+ ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData;
+ //
+ // VGA OPROM to support Video Re-POST for Linux S3
+ //
+ EFI_PHYSICAL_ADDRESS VideoOpromAddress;
+ UINT32 VideoOpromSize;
+
+ //
+ // S3 Debug extension
+ //
+ EFI_PHYSICAL_ADDRESS S3DebugBufferAddress;
+ EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint;
+} ACPI_VARIABLE_SET_COMPATIBILITY;
+
+typedef struct {
+ BOOLEAN APState;
+ EFI_PHYSICAL_ADDRESS StartupVector;
+ EFI_PHYSICAL_ADDRESS GdtrProfile;
+ EFI_PHYSICAL_ADDRESS IdtrProfile;
+ EFI_PHYSICAL_ADDRESS StackAddress;
+ UINT32 StackSize;
+ UINT32 NumberOfCpus;
+ EFI_PHYSICAL_ADDRESS MtrrTable;
+ EFI_PHYSICAL_ADDRESS RegisterTable;
+ EFI_PHYSICAL_ADDRESS Microcode;
+ EFI_PHYSICAL_ADDRESS ApMachineCheckHandlerBase;
+ UINT32 ApMachineCheckHandlerSize;
+} ACPI_CPU_DATA;
+
+typedef struct {
+ //
+ // Acpi Related variables
+ //
+ EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase;
+ UINT32 AcpiReservedMemorySize;
+ EFI_PHYSICAL_ADDRESS S3ReservedLowMemoryBase;
+ EFI_PHYSICAL_ADDRESS AcpiFacsTable;
+ UINT64 SystemMemoryLength;
+ ACPI_CPU_DATA AcpiCpuData;
+
+ //
+ // VGA OPROM to support Video Re-POST for Linux S3
+ //
+ EFI_PHYSICAL_ADDRESS VideoOpromAddress;
+ UINT32 VideoOpromSize;
+ EFI_PHYSICAL_ADDRESS S3PostVideoStatusRestoreEntryPoint;
+
+ EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress;
+ EFI_PHYSICAL_ADDRESS S3DebugBufferAddress;
+} ACPI_VARIABLE_SET;
+
+#define SMM_S3_RESUME_SMM_32 SIGNATURE_64 ('S','M','M','S','3','_','3','2')
+#define SMM_S3_RESUME_SMM_64 SIGNATURE_64 ('S','M','M','S','3','_','6','4')
+
+typedef struct {
+ UINT64 Signature;
+ EFI_PHYSICAL_ADDRESS SmmS3ResumeEntryPoint;
+ EFI_PHYSICAL_ADDRESS SmmS3StackBase;
+ UINT64 SmmS3StackSize;
+ UINT64 SmmS3Cr0;
+ UINT64 SmmS3Cr3;
+ UINT64 SmmS3Cr4;
+ UINT16 ReturnCs;
+ EFI_PHYSICAL_ADDRESS ReturnEntryPoint;
+ EFI_PHYSICAL_ADDRESS ReturnContext1;
+ EFI_PHYSICAL_ADDRESS ReturnContext2;
+ EFI_PHYSICAL_ADDRESS ReturnStackPointer;
+ EFI_PHYSICAL_ADDRESS Smst;
+} SMM_S3_RESUME_STATE;
+
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS AcpiFacsTable;
+ EFI_PHYSICAL_ADDRESS IdtrProfile;
+ EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress;
+ EFI_PHYSICAL_ADDRESS BootScriptStackBase;
+ UINT64 BootScriptStackSize;
+ EFI_PHYSICAL_ADDRESS S3DebugBufferAddress;
+} ACPI_S3_CONTEXT;
+
+typedef struct {
+ UINT16 ReturnCs;
+ EFI_PHYSICAL_ADDRESS ReturnEntryPoint;
+ EFI_PHYSICAL_ADDRESS ReturnStackPointer;
+ EFI_PHYSICAL_ADDRESS AsmTransferControl;
+ PSEUDO_DESCRIPTOR Idtr;
+} PEI_S3_RESUME_STATE;
+
+#define EFI_ACPI_S3_CONTEXT_GUID \
+ { \
+ 0xef98d3a, 0x3e33, 0x497a, {0xa4, 0x1, 0x77, 0xbe, 0x3e, 0xb7, 0x4f, 0x38} \
+ }
+
+extern EFI_GUID gEfiAcpiS3ContextGuid;
+
+extern EFI_GUID gEfiAcpiVariableGuid;
+extern EFI_GUID gEfiAcpiVariableCompatiblityGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/CapsuleOnDataCD.h b/QuarkPlatformPkg/Include/Guid/CapsuleOnDataCD.h
new file mode 100644
index 0000000..09b5cfb
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/CapsuleOnDataCD.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ CapsuleOnDataCD.h
+
+Abstract:
+
+ Capsule on Data CD GUID.
+
+ This is the contract between the recovery module and device recovery module
+ in order to convey the name of a given recovery module type
+
+--*/
+
+#ifndef _CAPSULE_ON_DATA_CD_H
+#define _CAPSULE_ON_DATA_CD_H
+
+#define PEI_CAPSULE_ON_DATA_CD_GUID \
+ { \
+ 0x5cac0099, 0x0dc9, 0x48e5, {0x80, 0x68, 0xbb, 0x95, 0xf5, 0x40, 0x0a, 0x9f } \
+ };
+
+extern EFI_GUID gPeiCapsuleOnDataCDGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/CapsuleOnFatFloppyDisk.h b/QuarkPlatformPkg/Include/Guid/CapsuleOnFatFloppyDisk.h
new file mode 100644
index 0000000..ad58616
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/CapsuleOnFatFloppyDisk.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ CapsuleOnFatFloppyDisk.h
+
+Abstract:
+
+ Capsule on Fat Floppy Disk GUID.
+
+ This is the contract between the recovery module and device recovery module
+ in order to convey the name of a given recovery module type
+
+--*/
+
+#ifndef _CAPSULE_ON_FAT_FLOPPY_DISK_H
+#define _CAPSULE_ON_FAT_FLOPPY_DISK_H
+
+#define PEI_CAPSULE_ON_FAT_FLOPPY_DISK_GUID \
+ { \
+ 0x2e3d2e75, 0x9b2e, 0x412d, {0xb4, 0xb1, 0x70, 0x41, 0x6b, 0x87, 0x0, 0xff }\
+ };
+
+extern EFI_GUID gPeiCapsuleOnFatFloppyDiskGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/CapsuleOnFatIdeDisk.h b/QuarkPlatformPkg/Include/Guid/CapsuleOnFatIdeDisk.h
new file mode 100644
index 0000000..e969d4e
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/CapsuleOnFatIdeDisk.h
@@ -0,0 +1,55 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ CapsuleOnFatIdeDisk.h
+
+Abstract:
+
+ Capsule on Fat Ide Disk GUID.
+
+ This is the contract between the recovery module and device recovery module
+ in order to convey the name of a given recovery module type
+
+--*/
+
+#ifndef _CAPSULE_ON_FAT_IDE_DISK_H
+#define _CAPSULE_ON_FAT_IDE_DISK_H
+
+#define PEI_CAPSULE_ON_FAT_IDE_DISK_GUID \
+ { \
+ 0xb38573b6, 0x6200, 0x4ac5, {0xb5, 0x1d, 0x82, 0xe6, 0x59, 0x38, 0xd7, 0x83 }\
+ };
+
+extern EFI_GUID gPeiCapsuleOnFatIdeDiskGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/CapsuleOnFatUsbDisk.h b/QuarkPlatformPkg/Include/Guid/CapsuleOnFatUsbDisk.h
new file mode 100644
index 0000000..c4d0cf8
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/CapsuleOnFatUsbDisk.h
@@ -0,0 +1,55 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ CapsuleOnFatUsbDisk.h
+
+Abstract:
+
+ Capsule on Fat Usb Disk GUID.
+
+ This is the contract between the recovery module and device recovery module
+ in order to convey the name of a given recovery module type
+
+--*/
+
+#ifndef _PEI_CAPSULE_ON_FAT_USB_DISK_H
+#define _PEI_CAPSULE_ON_FAT_USB_DISK_H
+
+#define PEI_CAPSULE_ON_FAT_USB_DISK_GUID \
+ { \
+ 0x0ffbce19, 0x324c, 0x4690, {0xa0, 0x09, 0x98, 0xc6, 0xae, 0x2e, 0xb1, 0x86 } \
+ };
+
+extern EFI_GUID gPeiCapsuleOnFatUsbDiskGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/FlashMapHob.h b/QuarkPlatformPkg/Include/Guid/FlashMapHob.h
new file mode 100644
index 0000000..f154682
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/FlashMapHob.h
@@ -0,0 +1,52 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ FlashMapHob.h
+
+Abstract:
+
+ GUID used for Flash Map HOB entries in the HOB list.
+
+--*/
+
+#ifndef _FLASH_MAP_HOB_H_
+#define _FLASH_MAP_HOB_H_
+
+//
+// Definitions for Flash Map
+//
+#define EFI_FLASH_MAP_HOB_GUID \
+ { 0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59} }
+
+extern EFI_GUID gEfiFlashMapHobGuid;
+
+#endif // _FLASH_MAP_HOB_GUID_H_
diff --git a/QuarkPlatformPkg/Include/Guid/MemoryConfigData.h b/QuarkPlatformPkg/Include/Guid/MemoryConfigData.h
new file mode 100644
index 0000000..a34995d
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/MemoryConfigData.h
@@ -0,0 +1,47 @@
+/**@file
+Define a GUID name for GUID HOB which is used to pass Memory
+Configuration Data information to different modules.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _MEMORY_CONFIG_DATA_H_
+#define _MEMORY_CONFIG_DATA_H_
+
+#define EFI_MEMORY_CONFIG_DATA_GUID \
+ { \
+ 0x80dbd530, 0xb74c, 0x4f11, {0x8c, 0x03, 0x41, 0x86, 0x65, 0x53, 0x28, 0x31 } \
+ }
+
+#define EFI_MEMORY_CONFIG_DATA_NAME L"MemoryConfig"
+
+extern EFI_GUID gEfiMemoryConfigDataGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/PlatformDataFileNameGuids.h b/QuarkPlatformPkg/Include/Guid/PlatformDataFileNameGuids.h
new file mode 100644
index 0000000..de01552
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/PlatformDataFileNameGuids.h
@@ -0,0 +1,102 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformDataFileNameGuids.h
+
+Abstract:
+
+ GUIDs used for finding platform data files in firmware volumes.
+
+ To Add file to build do the followings steps.
+ 1)
+ Create platform data bin file and copy file to
+ QuarkPlatformPkg/Binary/PlatformData directory.
+
+ 2)
+ Create a guid for the new platform data file (files in EDK firmware
+ volumes have a file name guid associated with them).
+
+ 3)
+ Place the new guid define below and also add it to the
+ PDAT_FILE_NAME_TABLE_DEFINITION marco below.
+
+ 4)
+ Add file specifier in the stage1 FV volumes in the platform .fdf file.
+ example for kips bay platform is :-
+ FILE FREEFORM = 956EDAD3-8440-45cb-89AC-D1930C004E34 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin
+ }
+
+--*/
+
+#ifndef _PLATFORM_DATA_FILE_NAME_GUIDS_H_
+#define _PLATFORM_DATA_FILE_NAME_GUIDS_H_
+
+#define SVP_PDAT_FILE_NAME_GUID \
+ { 0xa975562, 0xdf47, 0x4dc3, { 0x8a, 0xb0, 0x3b, 0xa2, 0xc3, 0x52, 0x23, 0x2 } }
+
+#define KIPSBAY_PDAT_FILE_NAME_GUID \
+ { 0x956edad3, 0x8440, 0x45cb, { 0x89, 0xac, 0xd1, 0x93, 0xc, 0x0, 0x4e, 0x34 } }
+
+#define CROSSHILL_PDAT_FILE_NAME_GUID \
+ { 0x95b3c16, 0x6d67, 0x4c85, { 0xb5, 0x28, 0x33, 0x9d, 0x9f, 0xf6, 0x22, 0x2c } }
+
+#define CLANTONHILL_PDAT_FILE_NAME_GUID \
+ { 0xee84c5e7, 0x9412, 0x42cc, { 0xb7, 0x55, 0xa9, 0x15, 0xa7, 0xb6, 0x85, 0x36 } }
+
+#define GALILEO_PDAT_FILE_NAME_GUID \
+ { 0xe4ad87c8, 0xd20e, 0x40ce, { 0x97, 0xf5, 0x97, 0x56, 0xfd, 0xe, 0x81, 0xd4 } }
+
+#define GALILEO_FABE_PDAT_FILE_NAME_GUID \
+ { 0xe27ada6a, 0x9f8a, 0x4f2e, { 0xb0, 0x9e, 0x4c, 0xcd, 0xd8, 0x2c, 0x2f, 0x54 } }
+
+#define GALILEO_GEN2_PDAT_FILE_NAME_GUID \
+ { 0x23b3c10d, 0x46e3, 0x4a78, { 0x8a, 0xaa, 0x21, 0x7b, 0x6a, 0x39, 0xef, 0x4 } }
+
+
+#define PDAT_FILE_NAME_TABLE_DEFINITION \
+ /* EFI_PLATFORM_TYPE - ClantonPeakSVP*/\
+ SVP_PDAT_FILE_NAME_GUID,\
+ /* EFI_PLATFORM_TYPE - KipsBay*/\
+ KIPSBAY_PDAT_FILE_NAME_GUID,\
+ /* EFI_PLATFORM_TYPE - CrossHill*/\
+ CROSSHILL_PDAT_FILE_NAME_GUID,\
+ /* EFI_PLATFORM_TYPE - ClantonHill*/\
+ CLANTONHILL_PDAT_FILE_NAME_GUID,\
+ /* EFI_PLATFORM_TYPE - Galileo*/\
+ GALILEO_PDAT_FILE_NAME_GUID,\
+ /* EFI_PLATFORM_TYPE - GalileoFabE*/\
+ GALILEO_FABE_PDAT_FILE_NAME_GUID,\
+ /* EFI_PLATFORM_TYPE - GalileoGen2*/\
+ GALILEO_GEN2_PDAT_FILE_NAME_GUID,\
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/PlatformInfo.h b/QuarkPlatformPkg/Include/Guid/PlatformInfo.h
new file mode 100755
index 0000000..ee86b0f
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/PlatformInfo.h
@@ -0,0 +1,120 @@
+/** @file
+ PlatformInfo GUID
+
+ These GUIDs point the ACPI tables as defined in the ACPI specifications.
+ ACPI 2.0 specification defines the ACPI 2.0 GUID. UEFI 2.0 defines the
+ ACPI 2.0 Table GUID and ACPI Table GUID.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ @par Revision Reference:
+ GUIDs defined in UEFI 2.0 spec.
+
+**/
+
+#ifndef _PLATFORM_INFO_GUID_H_
+#define _PLATFORM_INFO_GUID_H_
+
+#include "PlatformData.h"
+#include <Uefi.h>
+
+extern EFI_GUID gEfiPlatformInfoGuid;
+extern CHAR16 EfiPlatformInfoVariable[];
+
+#pragma pack(1)
+
+typedef struct {
+ //
+ // These are global resource mapping of the system. Per IOH resource mapping is available in UDS.
+ //
+ UINT16 PciResourceIoBase;
+ UINT16 PciResourceIoLimit;
+ UINT32 PciResourceMem32Base;
+ UINT32 PciResourceMem32Limit;
+ UINT64 PciResourceMem64Base;
+ UINT64 PciResourceMem64Limit;
+ UINT64 PciExpressBase;
+ UINT32 PciExpressSize;
+} EFI_PLATFORM_PCI_DATA;
+
+typedef struct {
+ UINT8 CpuAddressWidth;
+ UINT8 UncoreBusNum[4];
+} EFI_PLATFORM_CPU_DATA;
+
+typedef struct {
+ UINT8 SysIoApicEnable;
+ UINT8 SysSioExist;
+ UINT8 IohMac0Address[6];
+ UINT8 IohMac1Address[6];
+} EFI_PLATFORM_SYS_DATA;
+
+typedef struct {
+ UINT32 MemTolm;
+ UINT32 MemMaxTolm;
+ UINT32 MemTsegSize;
+ UINT32 MemIedSize;
+ UINT64 MemMir0;
+ UINT64 MemMir1;
+ PDAT_MRC_ITEM MemMrcConfig;
+} EFI_PLATFORM_MEM_DATA;
+
+//
+// This HOB definition must be consistent with what is created in the
+// PlatformInfo protocol definition. This way the information in the
+// HOB can be directly copied upon the protocol and only the strings
+// will need to be updated.
+//
+typedef struct _EFI_PLATFORM_INFO_HOB {
+ UINT8 SystemUuid[16]; // 16 bytes
+ UINT32 Signature; // "$PIT" 0x54495024
+ UINT32 Size; // Size of the table
+ UINT16 Revision; // Revision of the table
+ UINT16 Type; // Platform Type
+ UINT32 TypeRevisionId; // Board Revision ID
+ UINT8 CpuType; // Cpu Type
+ UINT8 CpuStepping; // Cpu Stepping
+ UINT16 IioSku;
+ UINT16 IioRevision;
+ UINT16 QncSku;
+ UINT16 QncRevision;
+ UINT32 FirmwareVersion;
+ BOOLEAN ExtendedInfoValid; // If TRUE then below fields are Valid
+ UINT8 Checksum; // Checksum minus SystemUuid is valid in DXE only.
+ EFI_STRING TypeStringPtr;
+ EFI_GUID BiosPlatformDataFile;
+ EFI_PLATFORM_PCI_DATA PciData;
+ EFI_PLATFORM_CPU_DATA CpuData;
+ EFI_PLATFORM_MEM_DATA MemData;
+ EFI_PLATFORM_SYS_DATA SysData;
+} EFI_PLATFORM_INFO;
+
+#pragma pack()
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/PlatformMemoryLayout.h b/QuarkPlatformPkg/Include/Guid/PlatformMemoryLayout.h
new file mode 100644
index 0000000..b45c767
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/PlatformMemoryLayout.h
@@ -0,0 +1,92 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PlatformMemoryLayout.h
+
+Abstract:
+
+ GUID used by platform drivers to keep track of memory layout across system boots.
+
+--*/
+
+#ifndef _PLATFORM_MEMORY_LAYOUT_H_
+#define _PLATFORM_MEMORY_LAYOUT_H_
+
+//
+// GUID, used for variable vendor GUID and the GUIDed HOB.
+//
+#define EFI_PLATFORM_MEMORY_LAYOUT_GUID \
+ { \
+ 0x41c7b74e, 0xb839, 0x40d9, {0xa0, 0x56, 0xe3, 0xca, 0xfc, 0x98, 0xa, 0xac } \
+ }
+
+//
+// Variable name
+//
+#define EFI_PLATFORM_MEMORY_LAYOUT_NAME L"Platform Memory Layout"
+
+//
+// Variable attributes
+//
+#define EFI_PLATFORM_MEMORY_LAYOUT_ATTRIBUTES (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE)
+
+//
+// Structure for tracking a single DIMM state
+//
+typedef struct {
+ UINT8 Present : 1;
+ UINT8 Configured : 1;
+ UINT8 Disabled : 1;
+ UINT8 Reserved : 5;
+} EFI_DIMM_STATE;
+
+//
+// Structure for tracking DIMM layout information
+// This must be packed.
+//
+#pragma pack(1)
+typedef struct {
+ UINT8 DimmSets;
+ UINT8 DimmsPerSet;
+ UINT8 RowsPerSet;
+ EFI_DIMM_STATE State[1];
+} EFI_DIMM_LAYOUT;
+#pragma pack()
+//
+// The format of the variable or GUIDed HOB is a single EFI_DIMM_LAYOUT
+// structure followed by an array of (DimmSets * DimmsPerSet) of
+// EFI_DIMM_STATES structures.
+//
+extern EFI_GUID gEfiPlatformMemoryLayoutGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/QuarkCapsuleGuid.h b/QuarkPlatformPkg/Include/Guid/QuarkCapsuleGuid.h
new file mode 100755
index 0000000..217c273
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/QuarkCapsuleGuid.h
@@ -0,0 +1,73 @@
+/*++
+
+Capsule format guid for Quark capsule image.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#ifndef _QUARK_CAPSULE_GUID_H_
+#define _QUARK_CAPSULE_GUID_H_
+
+#define QUARK_CAPSULE_GUID \
+ { 0xd400d1e4, 0xa314, 0x442b, { 0x89, 0xed, 0xa9, 0x2e, 0x4c, 0x81, 0x97, 0xcb } }
+
+#define QUARK_CAPSULE_SECURITY_HEADER_GUID \
+ { 0xc3cdd08c, 0x796d, 0x491c, { 0x93, 0x54, 0x5d, 0x59, 0xc2, 0x89, 0xf2, 0xd6 }}
+
+#define SMI_INPUT_UPDATE_CAP 0x27
+#define SMI_INPUT_GET_CAP 0x28
+
+#define SMI_CAP_FUNCTION 0xEF
+
+#pragma pack(1)
+typedef struct {
+ UINT64 Address;
+ UINT32 BufferOffset;
+ UINT32 Size;
+ UINT32 Flags;
+ UINT32 Reserved;
+} CAPSULE_FRAGMENT;
+
+typedef struct {
+ UINTN CapsuleLocation; // Top of the capsule that point to structure CAPSULE_FRAGMENT
+ UINTN CapsuleSize; // Size of the capsule
+ EFI_STATUS Status; // Returned status
+} CAPSULE_INFO_PACKET;
+
+typedef struct {
+ UINTN BlocksCompleted; // # of blocks processed
+ UINTN TotalBlocks; // Total # of blocks to be processed
+ EFI_STATUS Status; // returned status
+} UPDATE_STATUS_PACKET;
+#pragma pack()
+
+extern EFI_GUID gEfiQuarkCapsuleGuid;
+extern EFI_GUID gEfiQuarkCapsuleSecurityHeaderGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/QuarkVariableLock.h b/QuarkPlatformPkg/Include/Guid/QuarkVariableLock.h
new file mode 100644
index 0000000..ce80a6f
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/QuarkVariableLock.h
@@ -0,0 +1,47 @@
+/*++
+
+ Guid and variable name used to trigger quark lock of specific UEFI variables.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--*/
+
+#ifndef _QUARK_VARIABLE_LOCK_GUID_H_
+#define _QUARK_VARIABLE_LOCK_GUID_H_
+
+#define QUARK_VARIABLE_LOCK_GUID \
+ { \
+ 0xeef749c2, 0xc047, 0x4d6e, { 0xb1, 0xbc, 0xd3, 0x6e, 0xb3, 0xa5, 0x55, 0x9c } \
+ }
+
+#define QUARK_VARIABLE_LOCK_NAME L"QuarkVariableLock"
+
+extern EFI_GUID gQuarkVariableLockGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Guid/SystemNvDataHobGuid.h b/QuarkPlatformPkg/Include/Guid/SystemNvDataHobGuid.h
new file mode 100644
index 0000000..9d4db84
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Guid/SystemNvDataHobGuid.h
@@ -0,0 +1,60 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SystemNvDataHobGuid.h
+
+Abstract:
+
+ GUIDs used for System Non Volatile HOB entries in the in the HOB list and FV Guids carrying
+ the System specific information.
+
+--*/
+
+#ifndef _SYSTEM_NV_DATA_HOB_GUID_H_
+#define _SYSTEM_NV_DATA_HOB_GUID_H_
+
+#define EFI_SYSTEM_NV_DATA_HOB_GUID \
+ {0xd6e5092d, 0xc7b2, 0x4872, {0xaf, 0x66, 0xfd, 0xc0, 0xe6, 0xf9, 0x5e, 0x78}}
+
+typedef struct {
+ EFI_GUID SystemNvDataHobGuid;
+ EFI_GUID SystemNvDataFvGuid;
+ EFI_LBA StartLba;
+ UINTN StartLbaOffset;
+ EFI_LBA EndLba;
+ UINTN EndLbaOffset;
+ UINT32 DataTypeSignature;
+} NV_SYSTEM_DATA_GUID_TYPE;
+
+extern EFI_GUID gEfiSystemNvDataHobGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Iio/IioRegs.h b/QuarkPlatformPkg/Include/Iio/IioRegs.h
new file mode 100644
index 0000000..e9d58bc
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Iio/IioRegs.h
@@ -0,0 +1,51 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ IioRegs.h
+
+Abstract:
+
+ IIO constants.
+
+Revision History:
+
+--*/
+
+#ifndef _IIO_REGS_H_
+#define _IIO_REGS_H_
+
+#include "CommonIncludes.h"
+
+#define MaxIIO 1
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Iio/IioUniversalData.h b/QuarkPlatformPkg/Include/Iio/IioUniversalData.h
new file mode 100644
index 0000000..e631bbf
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Iio/IioUniversalData.h
@@ -0,0 +1,94 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+ IioUniveralData.h
+
+Abstract:
+ Data format for Universal Data Structure
+
+--*/
+
+#ifndef _IIO_UNIVERSAL_DATA_
+#define _IIO_UNIVERSAL_DATA_
+
+#define IIO_UNIVERSAL_DATA_GUID { 0x7FF396A1, 0xEE7D, 0x431E, 0xBA, 0x53, 0x8F, 0xCA, 0x12, 0x7C, 0x44, 0xC0 }
+#include "IioRegs.h"
+#include "Platform.h"
+
+//--------------------------------------------------------------------------------------//
+// Structure definitions for Universal Data Store (UDS)
+//--------------------------------------------------------------------------------------//
+#define UINT64 unsigned long long
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 Valid;
+ UINT8 SocketID; // Socket ID of the IIO (0..3)
+ UINT8 BusBase;
+ UINT8 BusLimit;
+ UINT16 PciResourceIoBase;
+ UINT16 PciResourceIoLimit;
+ UINT32 IoApicBase;
+ UINT32 IoApicLimit;
+ UINT32 PciResourceMem32Base;
+ UINT32 PciResourceMem32Limit;
+ UINT64 PciResourceMem64Base;
+ UINT64 PciResourceMem64Limit;
+ UINT32 RcbaAddress;
+} IIO_RESOURCE_INSTANCE;
+
+typedef struct {
+ UINT8 PfSbspId; // Socket ID of SBSP
+ UINT8 PfGBusBase; // Global IIO Bus base
+ UINT8 PfGBusLimit; // Global IIO Bus limit
+ UINT16 PfGIoBase; // Global IIO IO base
+ UINT16 PfGIoLimit; // Global IIO IO limit
+ UINT32 PfGMmiolBase; // Global Mmiol base
+ UINT32 PfGMmiolLimit; // Global Mmiol limit
+ UINT64 PfGMmiohBase; // Global Mmioh Base [43:0]
+ UINT64 PfGMmiohLimit; // Global Mmioh Limit [43:0]
+ UINT32 MemTsegSize;
+ UINT64 PciExpressBase;
+ UINT32 PciExpressSize;
+ UINT8 Pci64BitResourceAllocation;
+ IIO_RESOURCE_INSTANCE IIO_resource[MAX_NODE];
+ UINT8 numofIIO;
+ UINT8 MaxBusNumber;
+} PLATFORM_DATA;
+
+typedef struct {
+ PLATFORM_DATA PlatformData;
+} IIO_UDS;
+#pragma pack()
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Iio/PciAccess.h b/QuarkPlatformPkg/Include/Iio/PciAccess.h
new file mode 100644
index 0000000..d1ca642
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Iio/PciAccess.h
@@ -0,0 +1,51 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciAccess.h
+
+Abstract:
+
+ Macros to simplify and abstract the interface to PCI configuration.
+
+--*/
+
+#ifndef _PCIACCESS_H_
+#define _PCIACCESS_H_
+
+//
+// Define PCI express offse
+//
+#define PCIE_OFF(Bus, Device, Function, Register) \
+ ((UINT64) ((UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) (Function << 12) + (UINTN) (Register)))
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Library/LogoLib.h b/QuarkPlatformPkg/Include/Library/LogoLib.h
new file mode 100644
index 0000000..24edeb4
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/LogoLib.h
@@ -0,0 +1,92 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+
+#ifndef _LOGO_LIB_H_
+#define _LOGO_LIB_H_
+
+/**
+ Use SystemTable ConOut to stop video based Simple Text Out consoles from going
+ to the video device. Put up LogoFile on every video device that is a console.
+
+ @param[in] LogoFile The file name of logo to display on the center of the screen.
+
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
+ @retval EFI_UNSUPPORTED Logo not found.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableQuietBoot (
+ IN EFI_GUID *LogoFile
+ );
+
+
+/**
+ Use SystemTable ConOut to turn on video based Simple Text Out consoles. The
+ Simple Text Out screens will now be synced up with all non-video output devices.
+
+ @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableQuietBoot (
+ VOID
+ );
+
+/**
+
+ Show progress bar with title above it. It only works in Graphics mode.
+
+
+ @param TitleForeground Foreground color for Title.
+ @param TitleBackground Background color for Title.
+ @param Title Title above progress bar.
+ @param ProgressColor Progress bar color.
+ @param Progress Progress (0-100)
+ @param PreviousValue The previous value of the progress.
+
+ @retval EFI_STATUS Success update the progress bar
+
+**/
+EFI_STATUS
+EFIAPI
+ShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ );
+#endif
+
diff --git a/QuarkPlatformPkg/Include/Library/MfhLib.h b/QuarkPlatformPkg/Include/Library/MfhLib.h
new file mode 100644
index 0000000..e0e8ba6
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/MfhLib.h
@@ -0,0 +1,252 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ MfhLib.h
+
+Abstract:
+
+ MfhLib function prototype definitions.
+
+--*/
+
+#ifndef __MFH_LIB_H__
+#define __MFH_LIB_H__
+
+#include "Mfh.h"
+
+//
+// Get bitmask for Flash Item Type (FIT) to be used in find filter routines.
+//
+#define MFH_FIT_BM(type) (LShiftU64 (1, (UINTN) (type)))
+
+//
+// Is type match in filter bitmap.
+//
+#define MFH_IS_FILTER_MATCH(filter, type) \
+ (((MFH_FIT_BM(type)) & (filter)) != 0)
+
+//
+// Some common find filters.
+//
+#define MFH_FIND_ANY_FIT_FILTER ((UINT64) -1) // Find any flash item.
+#define MFH_FIND_ALL_STAGE1_FILTER \
+ ((UINT64) ((MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE1)) | (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE1_SIGNED))))
+
+#define MFH_FIND_ALL_STAGE2_FILTER \
+ ((UINT64) ((MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE2)) | (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE2_SIGNED))))
+
+#define MFH_FIND_ALL_BOOTLOADER_FILTER \
+ ((UINT64) ((MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_BOOTLOADER)) | (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_BOOTLOADER_SIGNED))))
+
+#define MFH_FIND_IMAGE_VERSION_FILTER \
+ ((UINT64) (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_IMAGE_VERSION)))
+
+//
+// Filter to find any firmware flash item.
+//
+#define MFH_FIND_ANY_FW_FIT_FILTER ((UINT64) ( \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE1)) | \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE1_SIGNED)) | \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE2)) | \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE2_SIGNED)) | \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE2_CFG)) | \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_STAGE2_CFG_SIGNED)) | \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_PARAMETERS)) | \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_RECOVERY)) | \
+ (MFH_FIT_BM(MFH_FLASH_ITEM_TYPE_FW_RECOVERY_SIGNED)) \
+ ))
+
+
+///
+/// Context structure to be used with FindFirst & FindNext routines
+///
+typedef struct {
+ MFH_HEADER *MfhHeader; // Pointer to MFH Data structure in flash, filled out by FindFirst.
+ UINT32 *BootPriorityList; // Pointer to boot priority list.
+ MFH_FLASH_ITEM *FlashItemList; // Pointer to flash item list.
+ UINT32 CurrBootPriorityListIndex; // Current found boot priority index.
+ UINT32 CurrFlashItemIndex; // Current found flash item index.
+ BOOLEAN OnlyBootFlashItems; // Only finding items refed in boot priority list.
+} MFH_LIB_FINDCONTEXT;
+
+/** Find First flash Item using item type filter.
+
+ The bit position for a particular type is (1 << MFH_FLASH_ITEM_TYPE_XXX)
+
+ @param[in] ItemTypeFilter Filter of item types to search for.
+ @param[in] OnlyBootFlashItems Only find flash items referenced in boot
+ priority list.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if MFH not found, corrupt or no items found for specified type.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindFirstWithFilter (
+ IN CONST UINT64 ItemTypeFilter,
+ IN CONST BOOLEAN OnlyBootFlashItems,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ );
+
+/** Find next flash Item using item type filter.
+
+ @param[in] ItemTypeFilter Filter of item types to search for.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if no items match filter.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindNextWithFilter (
+ IN CONST UINT64 ItemTypeFilter,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ );
+
+/** Find First flash Item of a specific type.
+
+ @param[in] FlashItemType One of MFH_FLASH_ITEM defs in Mfh.h.
+ @param[in] OnlyBootFlashItems Only find flash items referenced in boot
+ priority list.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if MFH not found, corrupt or no items found for specified type.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindFirstOfType (
+ IN CONST UINT32 FlashItemType,
+ IN CONST BOOLEAN OnlyBootFlashItems,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ );
+
+/** Find next flash Item of a specific type.
+
+ @param[in] FlashItemType One of MFH_FLASH_ITEM defs in Mfh.h.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if no more items found for specified type.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindNextOfType (
+ IN CONST UINT32 FlashItemType,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ );
+
+/** Validate if MFH at specified base address is valid.
+
+ Optional return of pointers to resources within MFH.
+
+ @param[in] MfhBaseAddress Check memory at this location
+ points to a valid MFH.
+ @param[out] MfhHeaderPtr Optional return header part of MFH.
+ @param[out] BootPriorityListPtr Optional return of boot priority list.
+ points to a valid MFH.
+ @param[out] FlashItemListPtr Optional return of flash item list.
+
+ @retval TRUE if MfhBaseAddress points to a valid MFH.
+ @retval FALSE if MfhBaseAddress points to an invalid MFH.
+**/
+BOOLEAN
+EFIAPI
+MfhLibValidateMfhBaseAddress (
+ IN CONST UINT32 MfhBaseAddress,
+ OUT MFH_HEADER **MfhHeaderPtr OPTIONAL,
+ OUT UINT32 **BootPriorityListPtr OPTIONAL,
+ OUT MFH_FLASH_ITEM **FlashItemListPtr OPTIONAL
+ );
+
+/** Return string for printing flash item type.
+
+ @param[in] FlashItemType One of MFH_FLASH_ITEM defs in Mfh.h.
+
+ @return string for printing flash item type.
+**/
+CHAR16 *
+EFIAPI
+MfhLibFlashItemTypePrintString (
+ IN CONST UINT32 FlashItemType
+ );
+
+/** Find First stage1 flash module info or fixed recovery module info.
+
+ @param[out] FlashItemBuffer Caller storage to receive flash item
+ fields.
+ @param[out] GotFixedRecovery TRUE if buffer filled with fixed
+ recovery module info.
+
+ @retval TRUE if found flash module.
+ @retval FALSE if no flash module found.
+**/
+BOOLEAN
+EFIAPI
+MfhLibFindFirstStage1OrFixedRecovery (
+ OUT MFH_FLASH_ITEM *FlashItemBuffer,
+ OUT BOOLEAN *GotFixedRecovery OPTIONAL
+ );
+
+/** Check if Address within firmware flash item.
+
+ @param[in] CheckAddress Address to check.
+
+ @retval TRUE if check address with FW flash item.
+ @retval FALSE if check address outside FW flash item.
+**/
+BOOLEAN
+EFIAPI
+MfhLibIsAddressWithinFwFlashItem (
+ IN CONST UINT32 CheckAddress
+ );
+
+/** Find flash Item for boot priority index.
+
+ @param[in] BootPriorityIndex Boot priority index of flash item
+ we are looking for.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if MFH not found, corrupt or BootPriorityIndex >= ListCount.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindFlashItemForBootPriorityIndex (
+ IN CONST UINT32 BootPriorityIndex
+ );
+
+#endif // #ifndef __MFH_LIB_H__
diff --git a/QuarkPlatformPkg/Include/Library/PlatformBootManagerLib.h b/QuarkPlatformPkg/Include/Library/PlatformBootManagerLib.h
new file mode 100644
index 0000000..2b6bcf6
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/PlatformBootManagerLib.h
@@ -0,0 +1,90 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+
+#ifndef __PLATFORM_BOOT_MANAGER_LIB_H_
+#define __PLATFORM_BOOT_MANAGER_LIB_H_
+#include <Library/UefiBootManagerLib.h>
+
+//
+// Bit mask returned from PlatformBootManagerInit
+// We can define more value in future per requirement
+//
+#define PLATFORM_BOOT_MANAGER_ENABLE_HOTKEY 0x00000001
+#define PLATFORM_BOOT_MANAGER_ENABLE_TIMEOUT 0x00000002
+#define PLATFORM_BOOT_MANAGER_ENABLE_ALL 0xFFFFFFFF
+
+/**
+ Do the platform specific action before the console is ready
+ Possible things that can be done in PlatformBootManagerInit:
+ > Update console variable
+ > Register new Driver#### or Boot####
+ > Signal ReadyToLock event
+ > Authentication action: 1. connect Auth devices; 2. Identify auto logon user.
+
+ @return Bit mask to indicate the platform boot manager requirement.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+ VOID
+ );
+
+/**
+ Do the platform specific action after the console is ready
+ Possible things that can be done in PlatformBootManagerConsoleReady:
+ > Dynamically switch output mode
+ > Signal console ready platform customized event
+ > Run diagnostics: 1. driver health check; 2. memory test
+ > Connect certain devices: 1. connect all; 2. connect nothing; 3. connect platform specified devices
+ > Dispatch aditional option roms
+ @param PlatformBdsRequest Original platform boot manager requirement.
+
+ @return Bit mask to indicate the udpated platform boot manager requirement.
+**/
+UINT32
+EFIAPI
+PlatformBootManagerAfterConsole (
+ VOID
+ );
+
+/**
+ This function is called each second during the boot manager waits the timeout.
+
+ @param TimeoutRemain The remaining timeout.
+**/
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+ UINT16 TimeoutRemain
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Library/PlatformDataLib.h b/QuarkPlatformPkg/Include/Library/PlatformDataLib.h
new file mode 100755
index 0000000..9b2bd1d
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/PlatformDataLib.h
@@ -0,0 +1,223 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformDataLib.h
+
+Abstract:
+
+ PlatformDataLib function prototype definitions.
+
+--*/
+
+#ifndef __PLATFORM_DATA_LIB_H__
+#define __PLATFORM_DATA_LIB_H__
+
+#include "PlatformData.h"
+
+///
+/// Get bitmask for Platform Item ID to be used in find filter routines.
+///
+#define PDAT_ITEM_ID_MASK(id) (LShiftU64 ((UINT64)1, (UINTN) (id)))
+
+///
+/// Is id match in filter bitmap.
+///
+#define PDAT_IS_FILTER_MATCH(filter, id) \
+ (((PDAT_ITEM_ID_MASK(id)) & (filter)) != 0)
+
+//
+// Some common find filters.
+//
+
+#define PDAT_FIND_ANY_ITEM_FILTER ((UINT64) -1) // Find any flash item.
+#define PDAT_FIND_ACCOUNTING_ITEMS \
+ ((UINT64) ((PDAT_ITEM_ID_MASK(PDAT_ITEM_ID_PLATFORM_ID)) | (PDAT_ITEM_ID_MASK(PDAT_ITEM_ID_SERIAL_NUM))))
+
+#define PDAT_FIND_NETWORK_ITEMS \
+ ((UINT64) ((PDAT_ITEM_ID_MASK(PDAT_ITEM_ID_MAC0)) | (PDAT_ITEM_ID_MASK(PDAT_ITEM_ID_MAC1))))
+
+#define PDAT_FIND_MEMORY_ITEMS \
+ ((UINT64) ((PDAT_ITEM_ID_MASK(PDAT_ITEM_ID_MEM_CFG)) | (PDAT_ITEM_ID_MASK(PDAT_ITEM_ID_MRC_VARS))))
+
+//
+// Type defs for data types specific to this library.
+//
+
+///
+/// Context structure to be used with FindFirst & FindNext routines.
+///
+typedef struct {
+ PDAT_AREA *Area; ///< Pointer to Platform Data structure in flash, filled out by FindFirst.
+ UINT8 *Limit; ///< Pointer to 1st memory location after Platform Data Area.
+ UINT8 *CurrMemLocation; ///< Pointer to current position in platform data area.
+} PDAT_LIB_FINDCONTEXT;
+
+//
+// Function prototypes for routines exported by this library.
+//
+
+/** Validate Platform Data Area.
+
+ @param[in] Area Area to Validate.
+ @param[in] DoCrcCheck Do CRC Check on area.
+
+ @retval EFI_SUCCESS Area validated.
+ @retval EFI_NOT_FOUND Signature not found in area.
+ @retval EFI_BAD_BUFFER_SIZE Area has invalid length.
+ @retval EFI_CRC_ERROR Area CRC Fail.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+PDatLibValidateArea (
+ IN CONST PDAT_AREA *Area,
+ IN CONST BOOLEAN DoCrcCheck
+ );
+
+/** Get pointer to System Platform Data Area.
+
+ @param[in] DoCrcCheck Do CRC Check on area.
+ @param[out] AreaPtr Pointer to pointer to receive address of
+ platform data area.
+
+ @retval EFI_SUCCESS Area validated.
+ @retval EFI_NOT_FOUND Signature not found in area.
+ @retval EFI_BAD_BUFFER_SIZE Area has invalid length.
+ @retval EFI_CRC_ERROR Area CRC Fail.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+PDatLibGetSystemAreaPointer (
+ IN CONST BOOLEAN DoCrcCheck,
+ OUT PDAT_AREA **AreaPtr
+ );
+
+/** Find platform data item.
+
+ @param[in] UserArea Platform Data Area to search
+ if == NULL then use System area.
+ @param[in] ItemId One of PDAT_ITEM_ID_XXXX constants
+ indicating item to find.
+ @param[in] DoCrcCheck Do CRC Check on area.
+ @param[out] ItemData Optional pointer to buffer to receive
+ Item Data, caller reponsible that buffer
+ is large enough.
+
+ @return pointer to PDAT_ITEM struct for found item.
+ @retval NULL if item not found or validate fails.
+**/
+PDAT_ITEM *
+EFIAPI
+PDatLibFindItem (
+ IN PDAT_AREA *UserArea, OPTIONAL
+ IN CONST UINT16 ItemId,
+ IN CONST BOOLEAN DoCrcCheck,
+ OUT VOID *ItemData OPTIONAL
+ );
+
+/** Find First Item using item id filter.
+
+ This routine will alway validate the platform data area (including CRC).
+
+ WARNING:
+ FindFirst / FindNext limited to item ids 0x0000 - 0x0003f.
+
+ @param[in] UserArea Platform Data Area to search
+ if == NULL then use System area.
+ @param[in] ItemIdFilter Filter of item types to search for.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+ @param[out] ItemData Optional pointer to buffer to receive
+ Item Data, caller reponsible that buffer
+ is large enough.
+
+ @return pointer to PDAT_ITEM struct for found item.
+ @retval NULL if item not found, area corrupt or reached end of platform data area.
+**/
+PDAT_ITEM *
+EFIAPI
+PDatLibFindFirstWithFilter (
+ IN PDAT_AREA *UserArea, OPTIONAL
+ IN CONST UINT64 ItemIdFilter,
+ IN OUT PDAT_LIB_FINDCONTEXT *FindContext,
+ OUT VOID *ItemData OPTIONAL
+ );
+
+/** Find next Item using item id filter.
+
+ WARNING:
+ FindFirst / FindNext limited to item ids 0x0000 - 0x0003f.
+
+ @param[in] ItemIdFilter Filter of item types to search for.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+ @param[out] ItemData Optional pointer to buffer to receive
+ Item Data, caller reponsible that buffer
+ is large enough.
+
+ @return pointer to PDAT_ITEM struct for found item.
+ @retval NULL if reached end of platform data area.
+**/
+PDAT_ITEM *
+EFIAPI
+PDatLibFindNextWithFilter (
+ IN CONST UINT64 ItemIdFilter,
+ IN OUT PDAT_LIB_FINDCONTEXT *FindContext,
+ OUT VOID *ItemData OPTIONAL
+ );
+
+/** Copy platform data area and filter out specified items.
+
+ Only able to filter out item ids 0x0000 - 0x0003f.
+
+ @param[out] DestArea User allocated buffer to receive
+ SrcArea with ItemIdFilter items
+ removed.
+ @param[in] SrcArea Area to copy.
+ @param[in] ItemIdFilter Filter of items not to copy into DestArea.
+
+ @retval EFI_SUCCESS Operation success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval Others Unexpected error happened.
+**/
+EFI_STATUS
+EFIAPI
+PDatLibCopyAreaWithFilterOut (
+ OUT PDAT_AREA *DestArea,
+ IN PDAT_AREA *SrcArea,
+ IN CONST UINT64 ItemIdFilter
+ );
+
+#endif // #ifndef __PLATFORM_DATA_LIB_H__
diff --git a/QuarkPlatformPkg/Include/Library/PlatformHelperLib.h b/QuarkPlatformPkg/Include/Library/PlatformHelperLib.h
new file mode 100644
index 0000000..f5af79d
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/PlatformHelperLib.h
@@ -0,0 +1,305 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformHelperLib.h
+
+Abstract:
+
+ PlatformHelperLib function prototype definitions.
+
+--*/
+
+#ifndef __PLATFORM_HELPER_LIB_H__
+#define __PLATFORM_HELPER_LIB_H__
+
+#include "PlatformData.h"
+
+//
+// Function prototypes for routines exported by this library.
+//
+
+/**
+ The PlatformCalculateCrc32 routine.
+
+ @param Data The buffer containing the data to be processed.
+ @param DataSize The size of data to be processed.
+ @param CrcOut A pointer to the caller allocated UINT32 that
+ on return contains the CRC32 checksum of Data.
+
+ @retval EFI_SUCCESS Calculation is successful.
+ @retval EFI_INVALID_PARAMETER Data / CrcOut = NULL, or DataSize = 0.
+ @retval EFI_NOT_FOUND Firmware volume file not found.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformCalculateCrc32 (
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN OUT UINT32 *CrcOut
+ );
+
+/**
+ Find pointer to RAW data in Firmware volume file.
+
+ @param FvNameGuid Firmware volume to search. If == NULL search all.
+ @param FileNameGuid Firmware volume file to search for.
+ @param SectionData Pointer to RAW data section of found file.
+ @param SectionDataSize Pointer to UNITN to get size of RAW data.
+
+ @retval EFI_SUCCESS Raw Data found.
+ @retval EFI_INVALID_PARAMETER FileNameGuid == NULL.
+ @retval EFI_NOT_FOUND Firmware volume file not found.
+ @retval EFI_UNSUPPORTED Unsupported in current enviroment (PEI or DXE).
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFindFvFileRawDataSection (
+ IN CONST EFI_GUID *FvNameGuid OPTIONAL,
+ IN CONST EFI_GUID *FileNameGuid,
+ OUT VOID **SectionData,
+ OUT UINTN *SectionDataSize
+ );
+
+/**
+ Read 8bit character from debug stream.
+
+ Block until character is read.
+
+ @return 8bit character read from debug stream.
+
+**/
+CHAR8
+EFIAPI
+PlatformDebugPortGetChar8 (
+ VOID
+ );
+
+/**
+ Return platform type string given platform type enum.
+
+ ASSERT if invalid platform type enum.
+
+ ASSERT if EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION has no entries.
+
+ ASSERT if EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION has no string for type.
+
+ @return string for platform type enum.
+
+**/
+CHAR16 *
+EFIAPI
+PlatformTypeString (
+ IN CONST UINT16 Type
+ );
+
+/**
+ Find free spi protect register and write to it to protect a flash region.
+
+ @param DirectValue Value to directly write to register.
+ if DirectValue == 0 the use Base & Length below.
+ @param BaseAddress Base address of region in Flash Memory Map.
+ @param Length Length of region to protect.
+
+ @retval EFI_SUCCESS Free spi protect register found & written.
+ @retval EFI_NOT_FOUND Free Spi protect register not found.
+ @retval EFI_DEVICE_ERROR Unable to write to spi protect register.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformWriteFirstFreeSpiProtect (
+ IN CONST UINT32 DirectValue,
+ IN CONST UINT32 BaseAddress,
+ IN CONST UINT32 Length
+ );
+
+/**
+ Lock legacy SPI static configuration information.
+
+ Function will assert if unable to lock config.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockConfig (
+ VOID
+ );
+
+/**
+ Lock regions and config of SPI flash given the policy for this platform.
+
+ Function will assert if unable to lock regions or config.
+
+ @param PreBootPolicy If TRUE do Pre Boot Flash Lock Policy.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockPolicy (
+ IN CONST BOOLEAN PreBootPolicy
+ );
+
+/** Auto provision Secure Boot Resources.
+
+ Provision from platform data, and only provision if PK public cert found.
+
+ @retval TRUE UEFI 2.3.1 Secure Boot enabled.
+ @retval FALSE UEFI 2.3.1 Secure Boot Disabled.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformAutoProvisionSecureBoot (
+ VOID
+ );
+
+/** Validate Secure boot variables setup correctly for this platform.
+
+ ASSERT if problem found.
+ Only validate if PcdSupportSecureBoot AND SecureBootEnabled.
+
+**/
+VOID
+EFIAPI
+PlatformValidateSecureBootVars (
+ VOID
+ );
+
+/**
+ Erase and Write to platform flash.
+
+ Routine accesses one flash block at a time, each access consists
+ of an erase followed by a write of FLASH_BLOCK_SIZE. One or both
+ of DoErase & DoWrite params must be TRUE.
+
+ Limitations:-
+ CpuWriteAddress must be aligned to FLASH_BLOCK_SIZE.
+ DataSize must be a multiple of FLASH_BLOCK_SIZE.
+
+ @param Smst If != NULL then InSmm and use to locate
+ SpiProtocol.
+ @param CpuWriteAddress Address in CPU memory map of flash region.
+ @param Data The buffer containing the data to be written.
+ @param DataSize Amount of data to write.
+ @param DoErase Earse each block.
+ @param DoWrite Write to each block.
+
+ @retval EFI_SUCCESS Operation successful.
+ @retval EFI_NOT_READY Required resources not setup.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFlashEraseWrite (
+ IN VOID *Smst,
+ IN UINTN CpuWriteAddress,
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN BOOLEAN DoErase,
+ IN BOOLEAN DoWrite
+ );
+
+/**
+ Those capsules supported by the firmwares.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+**/
+EFI_STATUS
+EFIAPI
+PlatformSupportCapsuleImage (
+ IN VOID *CapsuleHeader
+ );
+
+/** Check if System booted with recovery Boot Stage1 image.
+
+ @retval TRUE If system booted with recovery Boot Stage1 image.
+ @retval FALSE If system booted with normal stage1 image.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformIsBootWithRecoveryStage1 (
+ VOID
+ );
+
+/**
+ Clear SPI Protect registers.
+
+ @retval EFI_SUCESS SPI protect registers cleared.
+ @retval EFI_ACCESS_DENIED Unable to clear SPI protect registers.
+**/
+
+EFI_STATUS
+EFIAPI
+PlatformClearSpiProtect (
+ VOID
+ );
+
+/**
+ Determine if an SPI address range is protected.
+
+ @param SpiBaseAddress Base of SPI range.
+ @param Length Length of SPI range.
+
+ @retval TRUE Range is protected.
+ @retval FALSE Range is not protected.
+**/
+BOOLEAN
+EFIAPI
+PlatformIsSpiRangeProtected (
+ IN CONST UINT32 SpiBaseAddress,
+ IN CONST UINT32 Length
+ );
+
+/**
+ Set Legacy GPIO Level
+
+ @param LevelRegOffset GPIO level register Offset from GPIO Base Address.
+ @param GpioNum GPIO bit to change.
+ @param HighLevel If TRUE set GPIO High else Set GPIO low.
+
+**/
+VOID
+EFIAPI
+PlatformLegacyGpioSetLevel (
+ IN CONST UINT32 LevelRegOffset,
+ IN CONST UINT32 GpioNum,
+ IN CONST BOOLEAN HighLevel
+ );
+#endif // #ifndef __PLATFORM_HELPER_LIB_H__
diff --git a/QuarkPlatformPkg/Include/Library/PlatformPcieHelperLib.h b/QuarkPlatformPkg/Include/Library/PlatformPcieHelperLib.h
new file mode 100644
index 0000000..6fce546
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/PlatformPcieHelperLib.h
@@ -0,0 +1,87 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformPcieHelperLib.h
+
+Abstract:
+
+ PlatformPcieHelperLib function prototype definitions.
+
+--*/
+
+#ifndef __PLATFORM_PCIE_HELPER_LIB_H__
+#define __PLATFORM_PCIE_HELPER_LIB_H__
+
+#include "Platform.h"
+
+//
+// Function prototypes for routines exported by this library.
+//
+
+/**
+ Platform assert PCI express PERST# signal.
+
+ @param PlatformType See EFI_PLATFORM_TYPE enum definitions.
+
+**/
+VOID
+EFIAPI
+PlatformPERSTAssert (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+/**
+ Platform de assert PCI express PERST# signal.
+
+ @param PlatformType See EFI_PLATFORM_TYPE enum definitions.
+
+**/
+VOID
+EFIAPI
+PlatformPERSTDeAssert (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+/** Early initialisation of the PCIe controller.
+
+ @param PlatformType See EFI_PLATFORM_TYPE enum definitions.
+
+ @retval EFI_SUCCESS Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPciExpressEarlyInit (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+#endif // #ifndef __PLATFORM_PCIE_HELPER_LIB_H__
diff --git a/QuarkPlatformPkg/Include/Library/PlatformSecServicesLib.h b/QuarkPlatformPkg/Include/Library/PlatformSecServicesLib.h
new file mode 100644
index 0000000..5d86912
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/PlatformSecServicesLib.h
@@ -0,0 +1,87 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformSecServicesLib.h
+
+Abstract:
+
+ Provide platform specific services to SEC stage Reset Vector Driver.
+
+--*/
+
+#ifndef __PLATFORM_SEC_SERVICES_LIB_H__
+#define __PLATFORM_SEC_SERVICES_LIB_H__
+
+/** Copy and call fixed recovery image.
+
+**/
+VOID
+EFIAPI
+PlatformCopyFixedRecoveryImageToSramAndCall (
+ VOID
+ );
+
+/** Check if running recovery image in SRAM.
+
+ @retval TRUE If running recovery image from SRAM.
+ @retval FALSE If not recovery image from SRAM.
+**/
+BOOLEAN
+EFIAPI
+PlatformAmIFixedRecoveryRunningFromSram (
+ VOID
+ );
+
+/** Check if force recovery conditions met.
+
+ @return 0 if conditions not met or already running recovery image in SRAM.
+ @return address PlatformCopyFixedRecoveryImageToSramAndCall if conditions met.
+**/
+UINT32
+EFIAPI
+PlatformIsForceRecoveryConditionsMet (
+ VOID
+ );
+
+
+/** Copy boot stage1 image to sram and Call it.
+
+ This routine is called from the QuarkResetVector to copy stage1 image to SRAM
+ the routine should NOT be called from QuarkSecLib.
+
+**/
+VOID
+EFIAPI
+PlatformCopyBootStage1ImageToSramAndCall (
+ VOID
+ );
+#endif
diff --git a/QuarkPlatformPkg/Include/Library/QuarkBootRomLib.h b/QuarkPlatformPkg/Include/Library/QuarkBootRomLib.h
new file mode 100644
index 0000000..696896e
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/QuarkBootRomLib.h
@@ -0,0 +1,221 @@
+/** @file
+ Definition of Pei Core Structures and Services
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _QUARK_BOOT_ROM_LIB_H_
+#define _QUARK_BOOT_ROM_LIB_H_
+
+#define QUARK_DEFAULT_INTEL_KEY_FUSE_BANK 0 // There are 3 fuse banks - we use 0 as a default.
+#define QUARK_KEY_MODULE_MAX_SIZE 0x00008000 // 32K
+#define QUARK_KEY_MODULE_BASE_ADDRESS 0xFFFD8000
+#define QUARK_CRYPTO_HEAP_SIZE_BYTES 0x1900
+#define QUARK_BOOTROM_VALIDATE_FUNCTION_ENTRYPOINT_ADDRESS 0xFFFFFFE0
+#define QUARK_BOOTROM_VALIDATE_KEY_ENTRYPOINT_ADDRESS 0xFFFE1D3A
+#define QUARK_CSH_IDENTIFIER SIGNATURE_32 ('H', 'S', 'C', '_')
+#define QUARK_RSA_2048_MODULUS_SIZE_BYTES 256 // 256 Bytes Modulus size = 2048 bits.
+#define QUARK_RSA_2048_EXPONENT_SIZE_BYTES 4
+
+//
+// Quark ROM error type and error values.
+//
+typedef UINT32 QuarkRomFatalErrorCode;
+#define QUARK_ROM_NO_ERROR 0
+#define QUARK_ROM_FATAL_NO_VALID_MODULES 1
+#define QUARK_ROM_FATAL_RMU_DMA_TIMEOUT 2
+#define QUARK_ROM_FATAL_MEM_TEST_FAIL 3
+#define QUARK_ROM_FATAL_ACPI_TIMER_ERROR 4
+#define QUARK_ROM_FATAL_UNEX_RETURN_FROM_RUNTIME 5
+#define QUARK_ROM_FATAL_ERROR_DMA_TIMEOUT 6
+#define QUARK_ROM_FATAL_OUT_OF_BOUNDS_MODULE_ENTRY 7
+#define QUARK_ROM_FATAL_MODULE_SIZE_EXCEEDS_MEMORY 8
+#define QUARK_ROM_FATAL_KEY_MODULE_FUSE_COMPARE_FAIL 9
+#define QUARK_ROM_FATAL_KEY_MODULE_VALIDATION_FAIL 10
+#define QUARK_ROM_FATAL_STACK_CORRUPT 11
+#define QUARK_ROM_FATAL_INVALID_KEYBANK_NUM 12
+
+//
+// Rom lib has one .inf with MODULE_TYPE=BASE (for inclusion in PEI or DXE)
+// so Mem Alloc Routines passed to its entry points.
+//
+typedef
+VOID *
+(EFIAPI *QUARK_AUTH_ALLOC_POOL) (
+ IN UINTN AllocationSize
+ );
+
+typedef
+VOID
+(EFIAPI *QUARK_AUTH_FREE_POOL) (
+ IN VOID *Buffer
+ );
+
+typedef struct QuarkSecurityHeader_t
+{
+ UINT32 CSH_Identifier; // Unique identifier to sanity check signed module presence
+ UINT32 Version; // Current version of CSH used. Should be one for Quark A0.
+ UINT32 ModuleSizeBytes; // Size of the entire module including the module header and payload
+ UINT32 SecurityVersionNumberIndex; // Index of SVN to use for validation of signed module
+ UINT32 SecurityVersionNumber; // Used to prevent against roll back of modules
+ UINT32 RsvdModuleID; // Currently unused for Clanton. Maintaining for future use
+ UINT32 RsvdModuleVendor; // Vendor Identifier. For Intel products value is 0x00008086
+ UINT32 RsvdDate; // BCD representation of build date as yyyymmdd, where yyyy=4 digit year, mm=1-12, dd=1-31
+ UINT32 ModuleHeaderSizeBytes; // Total length of the header including including any padding optionally added by the signing tool.
+ UINT32 HashAlgorithm; // What Hash is used in the module signing.
+ UINT32 CryptoAlgorithm; // What Crypto is used in the module signing.
+ UINT32 KeySizeBytes; // Total length of the key data including including any padding optionally added by the signing tool.
+ UINT32 SignatureSizeBytes; // Total length of the signature including including any padding optionally added by the signing tool.
+ UINT32 RsvdNextHeaderPointer; // 32-bit pointer to the next Secure Boot Module in the chain, if there is a next header.
+ UINT32 Reserved[8/sizeof(UINT32)]; // Bytes reserved for future use, padding structure to required size.
+} QuarkSecurityHeader_t;
+
+typedef struct RSA2048PublicKey_t
+{
+ UINT32 ModulusSizeBytes; // Size of the RSA public key modulus
+ UINT32 ExponentSizeBytes; // Size of the RSA public key exponent
+ UINT32 Modulus[QUARK_RSA_2048_MODULUS_SIZE_BYTES/sizeof(UINT32)];// Key Modulus, 256 bytes = 2048 bits
+ UINT32 Exponent[QUARK_RSA_2048_EXPONENT_SIZE_BYTES/sizeof(UINT32)]; // Exponent Key, can be up to 4 bytes in our case.
+} RSA2048PublicKey_t;
+
+typedef struct ScratchMemory_t
+{
+ UINT8 *HeapStart; // Address of memory from which we can start to allocate.
+ UINT8 *HeapEnd; // Address of final byte of memory we can allocate up to.
+ UINT8 *NextFreeMem; // Pointer to the next free address in the heap.
+ UINT32 DebugCode; // A progress code, updated as we go along.
+ UINT32 FatalCode; // An indicator of why we failed to boot.
+}ScratchMemory_t;
+
+/** Validate key module routine.
+
+ Checks the SHA256 digest of the Oem Key in a module header against
+ that of the key held in fuse bank and then uses that key to validate
+ key module.
+
+ @param[in] Header A pointer to a header structure of a key
+ module in memory to be validated..
+ @param[in] Data Pointer to the signed data associated with
+ this module.
+ @param[in] ModuleKey The key used to sign the data.
+ @param[in] Signature The signature of the data.
+ @param[in] MemoryBuffer Pointer to crypto heap management structure.
+ @param[in] KeyBankNumber Which fuse bank are we pulling the Intel key from.
+
+ @retval QUARK_ROM_NO_ERROR If Key Module Validates
+ Successfully.
+ @retval QUARK_ROM_FATAL_KEY_MODULE_FUSE_COMPARE_FAIL if the Digest of the Intel Key
+ in the Header does not match
+ that stored in the fuse.
+ @retval QUARK_ROM_FATAL_KEY_MODULE_VALIDATION_FAIL if the RSA signature
+ is not successfully validated.
+ @retval QUARK_ROM_FATAL_INVALID_KEYBANK_NUM If key bank number too large.
+ @return Other Unexpected error.
+
+**/
+typedef
+QuarkRomFatalErrorCode
+(*VALIDATE_KEY_MODULE) (
+ const QuarkSecurityHeader_t * const Header,
+ const UINT8 * const Data,
+ const RSA2048PublicKey_t * const ModuleKey,
+ const UINT8 * const Signature,
+ ScratchMemory_t * const MemoryBuffer,
+ const UINT8 KeyBankNumber
+ );
+
+/**
+ Security library to authenticate a signed image.
+
+ @param[in] ImageBaseAddress Pointer to the current image under
+ consideration
+ @param[in] CallerSignedKeyModule Pointer to signed key module to
+ validate image against. If NULL use
+ default.
+ @param[in] AuthKeyModule If TRUE authenticate key module
+ as well as image.
+ @param[in] KeyBankNumberPtr Pointer to key bank number. If NULL
+ use default bank.
+ @param[in] QAllocPool Pointer allocate pool routine for
+ UEFI emviroment.
+ @param[in] QFreePool Pointer free pool routine for
+ UEFI emviroment.
+
+ @retval EFI_SUCCESS Image is legal
+ @retval EFI_SECURITY_VIOLATION Image is NOT legal.
+ @retval EFI_INVALID_PARAMETER Param options required QAllocPool
+ and QFreePool to be provided.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete
+ operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SecurityAuthenticateImage (
+ IN VOID *ImageBaseAddress,
+ IN QuarkSecurityHeader_t *CallerSignedKeyModule OPTIONAL,
+ IN CONST BOOLEAN AuthKeyModule,
+ IN UINT8 *KeyBankNumberPtr OPTIONAL,
+ IN QUARK_AUTH_ALLOC_POOL QAllocPool OPTIONAL,
+ IN QUARK_AUTH_FREE_POOL QFreePool OPTIONAL
+ );
+
+/**
+ Security library to authenticate a signed key module.
+
+ @param[in] SignedKetModule Pointer to key module to authenticate.
+ @param[in] KeyBankNumber Key bank number to use.
+ @param[in] CallerMemBuf Heap to be used by the BootRom crypto
+ functions. If == NULL alloc a heap.
+ @param[in] QAllocPool Pointer allocate pool routine for
+ UEFI emviroment.
+ @param[in] QFreePool Pointer free pool routine for
+ UEFI emviroment.
+
+ @retval EFI_SUCCESS Key module is legal
+ @retval EFI_SECURITY_VIOLATION Key module is NOT legal.
+ @retval EFI_INVALID_PARAMETER Param options required QAllocPool
+ and QFreePool to be provided.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete
+ operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SecurityAuthenticateKeyModule (
+ IN QuarkSecurityHeader_t *SignedKeyModule,
+ IN CONST UINT8 KeyBankNumber,
+ IN UINT8 *CallerMemBuf OPTIONAL,
+ IN UINTN CallerMemBufSize OPTIONAL,
+ IN QUARK_AUTH_ALLOC_POOL QAllocPool OPTIONAL,
+ IN QUARK_AUTH_FREE_POOL QFreePool OPTIONAL
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Library/RecoveryOemHookLib.h b/QuarkPlatformPkg/Include/Library/RecoveryOemHookLib.h
new file mode 100755
index 0000000..0bb06e4
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/RecoveryOemHookLib.h
@@ -0,0 +1,63 @@
+/** @file
+ This library includes the recovery function that can be customized by OEM,
+ including how to select the recovery capsule if more than one capsule found,
+ and security check.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __RECOVERY_OEM_HOOK_LIB_H__
+#define __RECOVERY_OEM_HOOK_LIB_H__
+
+/**
+ This function allows the user to force a system recovery
+
+**/
+VOID
+EFIAPI
+OemInitiateRecovery (
+ VOID
+ );
+
+/**
+ This function allows the user to force a system recovery and deadloop.
+
+ Deadloop required since system should not execute beyond this point.
+ Deadloop should never happen since OemInitiateRecovery () called within
+ this routine should never return since it executes a Warm Reset.
+
+**/
+VOID
+EFIAPI
+OemInitiateRecoveryAndWait (
+ VOID
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Library/SmmScriptLib.h b/QuarkPlatformPkg/Include/Library/SmmScriptLib.h
new file mode 100644
index 0000000..75184a4
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/SmmScriptLib.h
@@ -0,0 +1,161 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmmScriptLib.h
+
+Abstract:
+
+ This is an implementation of the BootScript at run time.
+
+--*/
+
+#ifndef _SMM_SCRIPT_LIB_H_
+#define _SMM_SCRIPT_LIB_H_
+
+#include <PiDxe.h>
+#include <Tbd/EfiBootScript.h>
+
+typedef EFI_PHYSICAL_ADDRESS EFI_SMM_SCRIPT_TABLE;
+
+EFI_STATUS
+EFIAPI
+InitializeSmmScriptLib (
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINTN SmmScriptTablePages,
+ OUT EFI_PHYSICAL_ADDRESS *SmmScriptTableBase
+ )
+/*++
+
+Routine Description:
+
+ Intialize Boot Script table.
+
+Arguments:
+
+ SystemTable - Pointer to the EFI sytem table
+ SmmScriptTablePages - The expected ScriptTable page number
+ SmmScriptTableBase - The returned ScriptTable base address
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No resource to do the initialization.
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SmmBootScriptCreateTable (
+ IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN UINTN Type
+ )
+/*++
+
+Routine Description:
+
+ Create Boot Script table.
+
+Arguments:
+
+ ScriptTable - Pointer to the boot script table to create.
+ Type - The type of table to creat.
+
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter detected.
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SmmBootScriptWrite (
+ IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN UINTN Type,
+ IN UINT16 OpCode,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Write to boot script table. Format is defined in AcpiScritSave Protocol.
+ Currently it supports MemWrite, IoWrite, PciCfgWrite.
+
+Arguments:
+
+ ScriptTable - Pointer to the script table to write to.
+ Type - Not used.
+ OpCode - Table write's Opcode.
+ ... - Parameter of the OpCode.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter passed in detected.
+ EFI_SUCCESS - Function completed successfully.
+ Other - Error occurred during execution.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SmmBootScriptCloseTable (
+ IN EFI_SMM_SCRIPT_TABLE ScriptTableBase,
+ IN EFI_SMM_SCRIPT_TABLE ScriptTablePtr,
+ IN UINTN Type
+ )
+/*++
+
+Routine Description:
+
+ Close Boot Script table.
+
+Arguments:
+
+ ScriptTableBase - Pointer to the boot script table to create.
+ ScriptTablePtr - Pointer to the script table to write to.
+ Type - The type of table to creat.
+
+
+Returns:
+
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Library/SwBpeLib.h b/QuarkPlatformPkg/Include/Library/SwBpeLib.h
new file mode 100644
index 0000000..8711b04
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/SwBpeLib.h
@@ -0,0 +1,66 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SwBpeLib.h
+
+Abstract:
+
+ This library provides Software Breakpoint Event interface with Debugger.
+
+--*/
+
+#ifndef _SW_BPE_LIB_H_
+#define _SW_BPE_LIB_H_
+
+VOID
+EFIAPI
+BpeDsAllocation (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Allocate NEM buffer for Data Store function and set callback for DRAM allocation in PEI phase
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+#endif // _SW_BPE_LIB_H_
diff --git a/QuarkPlatformPkg/Include/Library/UefiBootManagerLib.h b/QuarkPlatformPkg/Include/Library/UefiBootManagerLib.h
new file mode 100644
index 0000000..5e54548
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Library/UefiBootManagerLib.h
@@ -0,0 +1,740 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+
+#ifndef _UEFI_BOOT_MANAGER_LIB_H_
+#define _UEFI_BOOT_MANAGER_LIB_H_
+
+//
+// Boot Manager load option library functions.
+//
+
+//
+// Load Option Type
+//
+typedef enum {
+ LoadOptionTypeBoot,
+ LoadOptionTypeDriver,
+ LoadOptionTypeMax
+} EFI_BOOT_MANAGER_LOAD_OPTION_TYPE;
+
+typedef enum {
+ LoadOptionNumberMax = 0x10000,
+ LoadOptionNumberUnassigned = LoadOptionNumberMax
+} EFI_BOOT_MANAGER_LOAD_OPTION_NUMBER;
+
+//
+// Common structure definition for DriverOption and BootOption
+//
+typedef struct {
+ //
+ // Data read from UEFI NV variables
+ //
+ UINTN OptionNumber; // #### numerical value, could be LoadOptionNumberUnassigned
+ EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType; // LoadOptionTypeBoot or LoadOptionTypeDriver
+ UINT32 Attributes; // Load Option Attributes
+ CHAR16 *Description; // Load Option Description
+ EFI_DEVICE_PATH_PROTOCOL *FilePath; // Load Option Device Path
+ UINT8 *OptionalData; // Load Option optional data to pass into image
+ UINT32 OptionalDataSize; // Load Option size of OptionalData
+ BOOLEAN BootNext; // TRUE if this was a L"BootNext" Variable
+
+ //
+ // Used at runtime
+ //
+ EFI_STATUS Status; // Status returned from boot attempt gBS->StartImage ()
+ CHAR16 *ExitData; // Exit data returned from gBS->StartImage ()
+ UINTN ExitDataSize; // Size of ExitData
+} EFI_BOOT_MANAGER_LOAD_OPTION;
+
+/**
+ Returns an array of load options based on the EFI variable
+ L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it.
+ #### is the hex value of the UINT16 in each BootOrder/DriverOrder entry.
+
+ @param LoadOptionCount Returns number of entries in the array.
+ @param LoadOptionType The type of the load option.
+
+ @retval NULL No load options exist.
+ @retval !NULL Array of load option entries.
+
+**/
+EFI_BOOT_MANAGER_LOAD_OPTION *
+EFIAPI
+EfiBootManagerGetLoadOptions (
+ OUT UINTN *LoadOptionCount,
+ IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
+ );
+
+/**
+ Free an array of load options which return from
+ EfiBootManagerGetLoadOptions().
+
+ @param LoadOptions Pointer to the array of load options to free.
+ @param LoadOptionCount Number of array entries in LoadOptions.
+
+ @return EFI_SUCCESS LoadOptions was freed.
+ @return EFI_INVALID_PARAMETER LoadOptions is NULL.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeLoadOptions (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions,
+ IN UINTN LoadOptionCount
+ );
+
+/**
+ Initialize a load option.
+
+ @param Option Pointer to the load option to be initialized.
+ @param OptionNumber Option number of the load option.
+ @param OptionType Type of the load option.
+ @param Attributes Attributes of the load option.
+ @param Description Description of the load option.
+ @param FilePath Device path of the load option.
+ @param OptionalData Optional data of the load option.
+ @param OptionalDataSize Size of the optional data of the load option.
+
+ @retval EFI_SUCCESS The load option was initialized successfully.
+ @retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerInitializeLoadOption (
+ IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option,
+ IN UINTN OptionNumber,
+ IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
+ IN UINT32 Attributes,
+ IN CHAR16 *Description,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN UINT8 *OptionalData,
+ IN UINT32 OptionalDataSize
+ );
+
+/**
+ Free a load option that was created by the library.
+
+ @param LoadOption Pointer to the load option to free.
+ CONCERN: Check Boot#### instead of BootOrder, optimize, spec clarify
+ @return EFI_SUCCESS LoadOption was freed.
+ @return EFI_INVALID_PARAMETER LoadOption is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeLoadOption (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
+ );
+
+/**
+ Initialize the load option from the VariableName.
+
+ @param VariableName EFI Variable name which could be Boot#### or
+ Driver####
+ @param LoadOption Pointer to the load option to be initialized
+
+ @retval EFI_SUCCESS The option was created
+ @retval EFI_INVALID_PARAMETER VariableName or LoadOption is NULL.
+ @retval EFI_NOT_FOUND The variable specified by VariableName cannot be found.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerVariableToLoadOption (
+ IN CHAR16 *VariableName,
+ IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
+ );
+
+/**
+ Create the Boot#### or Driver#### variable from the load option.
+
+ @param LoadOption Pointer to the load option.
+
+ @retval EFI_SUCCESS The variable was created.
+ @retval Others Error status returned by RT->SetVariable.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerLoadOptionToVariable (
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
+ );
+
+/**
+ This function will update the Boot####/Driver#### and the BootOrder/DriverOrder
+ to add a new load option.
+
+ @param Option Pointer to load option to add.
+ @param Position Position of the new load option to put in the BootOrder/DriverOrder.
+
+ @retval EFI_SUCCESS The load option has been successfully added.
+ @retval Others Error status returned by RT->SetVariable.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerAddLoadOptionVariable (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
+ IN UINTN Position
+ );
+
+/**
+ Delete the load option according to the OptionNumber and OptionType.
+
+ Only the BootOrder/DriverOrder is updated to remove the reference of the OptionNumber.
+
+ @param OptionNumber Option number of the load option.
+ @param OptionType Type of the load option.
+
+ @retval EFI_NOT_FOUND The load option cannot be found.
+ @retval EFI_SUCCESS The load option was deleted.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerDeleteLoadOptionVariable (
+ IN UINTN OptionNumber,
+ IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
+ );
+
+/**
+ The comparator to be used by EfiBootManagerSortLoadOption.
+
+ @param Left Point to the EFI_BOOT_MANAGER_LOAD_OPTION.
+ @param Right Point to the EFI_BOOT_MANAGER_LOAD_OPTION.
+
+ @retval TRUE Left load option should be in front of the Right load option.
+ @retval FALSE Right load option should be in front of the Left load option.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_BOOT_MANAGER_LOAD_OPTION_COMPARATOR) (
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Left,
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Right
+ );
+
+/**
+ Sort the load options. The DriverOrder/BootOrder variables will be re-created to
+ reflect the new order.
+TODO: Expose or not?
+
+ @param OptionType The type of the load option.
+ @param Comparator The comparator function pointer.
+**/
+VOID
+EFIAPI
+EfiBootManagerSortLoadOptionVariable (
+ EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
+ EFI_BOOT_MANAGER_LOAD_OPTION_COMPARATOR Comparator
+ );
+
+
+/**
+ Return the index of the load option in the load option array.
+
+ The function consider two load options are equal when the
+ OptionType, Attributes, Description, FilePath and OptionalData are equal.
+TODO: Expose or not?
+
+ @param Key Pointer to the load option to be found.
+ @param Array Pointer to the array of load options to be found.
+ @param Count Number of entries in the Array.
+
+ @retval -1 Key wasn't found in the Array.
+ @retval 0 ~ Count-1 The index of the Key in the Array.
+**/
+INTN
+EFIAPI
+EfiBootManagerFindLoadOption (
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
+ IN UINTN Count
+ );
+
+//
+// Boot Manager hot key library functions.
+//
+
+#pragma pack(1)
+///
+/// EFI Key Option.
+///
+typedef struct {
+ ///
+ /// Specifies options about how the key will be processed.
+ ///
+ EFI_BOOT_KEY_DATA KeyData;
+ ///
+ /// The CRC-32 which should match the CRC-32 of the entire EFI_LOAD_OPTION to
+ /// which BootOption refers. If the CRC-32s do not match this value, then this key
+ /// option is ignored.
+ ///
+ UINT32 BootOptionCrc;
+ ///
+ /// The Boot#### option which will be invoked if this key is pressed and the boot option
+ /// is active (LOAD_OPTION_ACTIVE is set).
+ ///
+ UINT16 BootOption;
+ ///
+ /// The key codes to compare against those returned by the
+ /// EFI_SIMPLE_TEXT_INPUT and EFI_SIMPLE_TEXT_INPUT_EX protocols.
+ /// The number of key codes (0-3) is specified by the EFI_KEY_CODE_COUNT field in KeyOptions.
+ ///
+ EFI_INPUT_KEY Keys[3];
+ UINT16 OptionNumber;
+} EFI_BOOT_MANAGER_KEY_OPTION;
+#pragma pack()
+
+/**
+ Start the hot key service so that the key press can trigger the boot option.
+
+ @param HotkeyTriggered Return the waitable event and it will be signaled
+ when a valid hot key is pressed.
+
+ @retval EFI_SUCCESS The hot key service is started.
+**/
+
+EFI_STATUS
+EFIAPI
+EfiBootManagerStartHotkeyService (
+ IN EFI_EVENT *HotkeyTriggered
+ );
+
+//
+// Modifier for EfiBootManagerAddKeyOptionVariable and EfiBootManagerDeleteKeyOptionVariable
+//
+#define EFI_BOOT_MANAGER_SHIFT_PRESSED 0x00000001
+#define EFI_BOOT_MANAGER_CONTROL_PRESSED 0x00000002
+#define EFI_BOOT_MANAGER_ALT_PRESSED 0x00000004
+#define EFI_BOOT_MANAGER_LOGO_PRESSED 0x00000008
+#define EFI_BOOT_MANAGER_MENU_KEY_PRESSED 0x00000010
+#define EFI_BOOT_MANAGER_SYS_REQ_PRESSED 0x00000020
+
+/**
+ Add the key option.
+ It adds the key option variable and the key option takes affect immediately.
+
+ @param AddedOption Return the added key option.
+ @param BootOptionNumber The boot option number for the key option.
+ @param Modifier Key shift state.
+ @param ... Parameter list of pointer of EFI_INPUT_KEY.
+
+ @retval EFI_SUCCESS The key option is added.
+ @retval EFI_ALREADY_STARTED The hot key is already used by certain key option.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerAddKeyOptionVariable (
+ OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption, OPTIONAL
+ IN UINT16 BootOptionNumber,
+ IN UINT32 Modifier,
+ ...
+ );
+
+/**
+ Delete the Key Option variable and unregister the hot key
+
+ @param DeletedOption Return the deleted key options.
+ @param Modifier Key shift state.
+ @param ... Parameter list of pointer of EFI_INPUT_KEY.
+
+ @retval EFI_SUCCESS The key option is deleted.
+ @retval EFI_NOT_FOUND The key option cannot be found.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerDeleteKeyOptionVariable (
+ IN EFI_BOOT_MANAGER_KEY_OPTION *DeletedOption, OPTIONAL
+ IN UINT32 Modifier,
+ ...
+ );
+
+/**
+ Register the key option to exit the waiting of the Boot Manager timeout.
+ Platform should ensure that the continue key option isn't conflict with
+ other boot key options.
+
+ @param Modifier Key shift state.
+ @param ... Parameter list of pointer of EFI_INPUT_KEY.
+
+ @retval EFI_SUCCESS Successfully register the continue key option.
+ @retval EFI_ALREADY_STARTED The continue key option is already registered.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerRegisterContinueKeyOption (
+ IN UINT32 Modifier,
+ ...
+ );
+
+/**
+ Try to boot the boot option triggered by hot key.
+**/
+VOID
+EFIAPI
+EfiBootManagerHotkeyBoot (
+ VOID
+ );
+//
+// Boot Manager boot library functions.
+//
+
+/**
+ For the result returned from EfiBootManagerEnumerateBootOptions, the function adds
+ the missing ones and removes the invalid ones.
+
+ The function won't delete the boot option not added by itself.
+**/
+VOID
+EFIAPI
+EfiBootManagerRefreshAllBootOption (
+ VOID
+ );
+
+/**
+ Attempt to boot the EFI boot option. This routine sets L"BootCurent", clears L"BootNext",
+ and signals the EFI ready to boot event. If the device path for the option
+ starts with a BBS device path a legacy boot is attempted. Short form device paths are
+ also supported via this rountine. A device path starting with
+ MEDIA_HARDDRIVE_DP, MSG_USB_WWID_DP, MSG_USB_CLASS_DP gets expaned out
+ to find the first device that matches. If the BootOption Device Path
+ fails the removable media boot algorithm is attempted (\EFI\BOOTIA32.EFI,
+ \EFI\BOOTX64.EFI,... only one file type is tried per processor type)
+
+ @param BootOption Boot Option to try and boot.
+ On return, BootOption->Status contains the boot status:
+ EFI_SUCCESS BootOption was booted
+ EFI_UNSUPPORTED BootOption isn't supported.
+ EFI_NOT_FOUND The BootOption was not found on the system
+ Others BootOption failed with this error status
+
+**/
+VOID
+EFIAPI
+EfiBootManagerBoot (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ );
+
+/**
+ Emuerate all possible bootable medias in the following order:
+ 1. Removable BlockIo - The boot option only points to the removable media
+ device, like USB key, DVD, Floppy etc.
+ 2. Fixed BlockIo - The boot option only points to a Fixed blockIo device,
+ like HardDisk.
+ 3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting
+ SimpleFileSystem Protocol, but not supporting BlockIo
+ protocol.
+ 4. LoadFile - The boot option points to the media supporting
+ LoadFile protocol.
+ Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior
+**/
+EFI_BOOT_MANAGER_LOAD_OPTION *
+EFIAPI
+EfiBootManagerEnumerateBootOptions (
+ UINTN *BootOptionCount
+ );
+
+/**
+ Return the Boot Manager Menu.
+ TODO: Expose or not? Alternative way is to add new field IsBootManagerMenu in EFI_BOOT_MANAGER_LOAD_OPTION.
+
+ @param BootOption Return the Boot Manager Menu.
+
+ @retval EFI_SUCCESS The Boot Manager Menu is successfully returned.
+ @retval EFI_NOT_FOUND The Boot Manager Menu is not found.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerGetBootManagerMenu (
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ );
+
+/**
+ The function enumerates all the legacy boot options, creates them and registers them in the BootOrder variable.
+**/
+typedef
+VOID
+(EFIAPI *EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION) (
+ VOID
+ );
+
+/**
+ The function boots a legacy boot option.
+**/
+typedef
+VOID
+(EFIAPI *EFI_BOOT_MANAGER_LEGACY_BOOT) (
+ IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ );
+
+/**
+ The function registers the legacy boot support capabilities.
+
+ @param RefreshLegacyBootOption The function pointer to create all the legacy boot options.
+ @param LegacyBoot The function pointer to boot the legacy boot option.
+**/
+VOID
+EFIAPI
+EfiBootManagerRegisterLegacyBootSupport (
+ EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION RefreshLegacyBootOption,
+ EFI_BOOT_MANAGER_LEGACY_BOOT LegacyBoot
+ );
+
+
+//
+// Boot Manager connect and disconnect library functions
+//
+
+/**
+ This function will connect all the system driver to controller
+ first, and then special connect the default console, this make
+ sure all the system controller available and the platform default
+ console connected.
+**/
+VOID
+EFIAPI
+EfiBootManagerConnectAll (
+ VOID
+ );
+
+/**
+ This function will create all handles associate with every device
+ path node. If the handle associate with one device path node can not
+ be created successfully, then still give one chance to do the dispatch,
+ which load the missing drivers if possible.
+
+ @param DevicePathToConnect The device path which will be connected, it CANNOT be
+ a multi-instance device path
+ @param MatchingHandle Return the controller handle closest to the DevicePathToConnect
+
+ @retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.
+ @retval EFI_NOT_FOUND Failed to create all handles associate with every device path node.
+ @retval EFI_SUCCESS Successful to create all handles associate with every device path node.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerConnectDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
+ OUT EFI_HANDLE *MatchingHandle OPTIONAL
+ );
+
+/**
+ This function will disconnect all current system handles.
+
+ gBS->DisconnectController() is invoked for each handle exists in system handle buffer.
+ If handle is a bus type handle, all childrens also are disconnected recursively by
+ gBS->DisconnectController().
+**/
+VOID
+EFIAPI
+EfiBootManagerDisconnectAll (
+ VOID
+ );
+
+
+//
+// Boot Manager console library functions
+//
+
+typedef enum {
+ ConIn,
+ ConOut,
+ ErrOut,
+ ConInDev,
+ ConOutDev,
+ ErrOutDev,
+ ConsoleTypeMax
+} CONSOLE_TYPE;
+
+/**
+ This function will connect all the console devices base on the console
+ device variable ConIn, ConOut and ErrOut.
+**/
+VOID
+EFIAPI
+EfiBootManagerConnectAllDefaultConsoles (
+ VOID
+ );
+
+/**
+ This function updates the console variable based on ConVarName. It can
+ add or remove one specific console device path from the variable
+
+ @param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.
+ @param CustomizedConDevicePath The console device path to be added to
+ the console variable. Cannot be multi-instance.
+ @param ExclusiveDevicePath The console device path to be removed
+ from the console variable. Cannot be multi-instance.
+
+ @retval EFI_UNSUPPORTED The added device path is the same as a removed one.
+ @retval EFI_SUCCESS Successfully added or removed the device path from the
+ console variable.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerUpdateConsoleVariable (
+ IN CONSOLE_TYPE ConsoleType,
+ IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
+ );
+
+/**
+ Connect the console device base on the variable ConVarName, if
+ device path of the ConVarName is multi-instance device path, if
+ anyone of the instances is connected success, then this function
+ will return success.
+
+ @param ConsoleType ConIn, ConOut or ErrOut.
+ @param NeedDispatch Whether need to dispatch.
+
+ @retval EFI_NOT_FOUND There is not any console devices connected
+ success
+ @retval EFI_SUCCESS Success connect any one instance of the console
+ device path base on the variable ConVarName.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerConnectConsoleVariable (
+ IN CONSOLE_TYPE ConsoleType,
+ IN BOOLEAN NeedDispatch
+ );
+
+/**
+ Query all the children of VideoController and return the device paths of all the
+ children that support GraphicsOutput protocol.
+
+ @param VideoController PCI handle of video controller.
+
+ @return Device paths of all the children that support GraphicsOutput protocol.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+EfiBootManagerGetGopDevicePath (
+ IN EFI_HANDLE VideoController
+ );
+
+//
+// Boot Manager device path library functions
+//
+/**
+ Delete the instance in Multi that overlaps with Single.
+TODO: Add to UefiDevicePathLib
+
+ @param Multi A pointer to a multi-instance device path data
+ structure.
+ @param Single A pointer to a single-instance device path data
+ structure.
+
+ @return This function removes the device path instances in Multi that overlap
+ Single, and returns the resulting device path. If there is no
+ remaining device path as a result, this function will return NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+EfiBootManagerDelPartMatchInstance (
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,
+ IN EFI_DEVICE_PATH_PROTOCOL *Single
+ );
+
+/**
+ This function compares a device path data structure to that of all the nodes of a
+ second device path instance.
+TODO: Add to UefiDevicePathLib
+
+ @param Multi A pointer to a multi-instance device path data
+ structure.
+ @param Single A pointer to a single-instance device path data
+ structure.
+
+ @retval TRUE If the Single device path is contained within a
+ Multi device path.
+ @retval FALSE The Single device path is not contained within a
+ Multi device path.
+
+**/
+BOOLEAN
+EFIAPI
+EfiBootManagerMatchDevicePaths (
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,
+ IN EFI_DEVICE_PATH_PROTOCOL *Single
+ );
+
+//
+// Boot Manager misc library functions.
+//
+
+/**
+ This function reads the EFI variable (VendorGuid/Name) and returns a dynamically allocated
+ buffer and the size of the buffer. If it fails, return NULL.
+TODO: Add to UefiLib
+
+ @param Name The string part of the EFI variable name.
+ @param VendorGuid The GUID part of the EFI variable name.
+ @param VariableSize Returns the size of the EFI variable that was read.
+
+ @retval !NULL Dynamically allocated memory that contains a copy
+ of the EFI variable. The caller is responsible to
+ free the buffer.
+ @retval NULL The variable was not found.
+**/
+VOID *
+EFIAPI
+EfiBootManagerGetVariableAndSize (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid,
+ OUT UINTN *VariableSize
+ );
+
+/**
+
+ This routine is called to see if there are any capsules we need to process.
+ If the boot mode is not UPDATE, then we do nothing. Otherwise find the
+ capsule HOBS and produce firmware volumes for them via the DXE service.
+ Then call the dispatcher to dispatch drivers from them. Finally, check
+ the status of the updates.
+
+ This function should be called by BDS in case we need to do some
+ sort of processing even if there is no capsule to process. We
+ need to do this if an earlier update went away and we need to
+ clear the capsule variable so on the next reset PEI does not see it and
+ think there is a capsule available.
+
+ @retval EFI_INVALID_PARAMETER boot mode is not correct for an update
+ @retval EFI_SUCCESS There is no error when processing capsule
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerProcessCapsules (
+ VOID
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Mfh.h b/QuarkPlatformPkg/Include/Mfh.h
new file mode 100644
index 0000000..65e6b13
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Mfh.h
@@ -0,0 +1,122 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Mfh.h
+
+Abstract:
+
+ Defines for Quark Master Flash Header (MFH).
+ Please refer to Quark Secure Boot Programmers Reference Manual.
+
+--*/
+
+#ifndef __MFH_H__
+#define __MFH_H__
+
+//
+// Unique identifier to allow quick sanity checking on our MFH.
+// Corresponds to _MFH in ASCII characters.
+//
+#define MFH_IDENTIFIER 0x5F4D4648
+
+//
+// MFH Max values for sanity checks
+//
+#define MFH_MAX_NUM_BOOT_ITEMS 24
+#define MFH_MAX_NUM_FLASH_ITEMS 240
+
+//
+// Flash Item type definitions.
+//
+
+#define MFH_FLASH_ITEM_TYPE_FW_STAGE1 0x00000000
+#define MFH_FLASH_ITEM_TYPE_FW_STAGE1_SIGNED 0x00000001
+#define MFH_FLASH_ITEM_TYPE_RSVD_02H 0x00000002
+#define MFH_FLASH_ITEM_TYPE_FW_STAGE2 0x00000003
+#define MFH_FLASH_ITEM_TYPE_FW_STAGE2_SIGNED 0x00000004
+#define MFH_FLASH_ITEM_TYPE_FW_STAGE2_CFG 0x00000005
+#define MFH_FLASH_ITEM_TYPE_FW_STAGE2_CFG_SIGNED 0x00000006
+#define MFH_FLASH_ITEM_TYPE_FW_PARAMETERS 0x00000007
+#define MFH_FLASH_ITEM_TYPE_FW_RECOVERY 0x00000008
+#define MFH_FLASH_ITEM_TYPE_FW_RECOVERY_SIGNED 0x00000009
+#define MFH_FLASH_ITEM_TYPE_RSVD_0AH 0x0000000A
+#define MFH_FLASH_ITEM_TYPE_BOOTLOADER 0x0000000B
+#define MFH_FLASH_ITEM_TYPE_BOOTLOADER_SIGNED 0x0000000C
+#define MFH_FLASH_ITEM_TYPE_BOOTLOADER_CFG 0x0000000D
+#define MFH_FLASH_ITEM_TYPE_BOOTLOADER_CFG_SIGNED 0x0000000E
+#define MFH_FLASH_ITEM_TYPE_RSVD_0F 0x0000000F
+#define MFH_FLASH_ITEM_TYPE_KERNEL 0x00000010
+#define MFH_FLASH_ITEM_TYPE_KERNEL_SIGNED 0x00000011
+#define MFH_FLASH_ITEM_TYPE_RAMDISK 0x00000012
+#define MFH_FLASH_ITEM_TYPE_RAMDISK_SIGNED 0x00000013
+#define MFH_FLASH_ITEM_TYPE_RSVD_14H 0x00000014
+#define MFH_FLASH_ITEM_TYPE_PROGRAM 0x00000015
+#define MFH_FLASH_ITEM_TYPE_PROGRAM_SIGNED 0x00000016
+#define MFH_FLASH_ITEM_TYPE_RSVD_17H 0x00000017
+#define MFH_FLASH_ITEM_TYPE_BUILD_INFORMATION 0x00000018
+#define MFH_FLASH_ITEM_TYPE_IMAGE_VERSION 0x00000019
+
+#pragma pack(1)
+
+///
+/// Initial header fields of MFH.
+///
+typedef union {
+ UINT32 ImageVersion; // Definition for MFH_FLASH_ITEM_TYPE_IMAGE_VERSION
+ UINT32 Reserved; // Definition for all other item types
+} MFH_TYPE_SPECIFIC;
+
+///
+/// An entry in the MFH describing some element stored in Flash.
+///
+typedef struct {
+ UINT32 Type; // Type of module that this Flash Item describes.
+ UINT32 FlashAddress; // Starting address of the given element in SPI Flash device.
+ UINT32 LengthBytes; // Length of given module in bytes.
+ MFH_TYPE_SPECIFIC TypeSpecific; // This field is specific to the MFH Item type.
+} MFH_FLASH_ITEM;
+
+///
+/// Initial header fields of MFH.
+///
+typedef struct {
+ UINT32 QuarkMFHIdentifier; // Unique identifier to sanity check MFH presence. This value will always be set to 0xC3F4 C3F4.
+ UINT32 Version; // Current version of MFH used.
+ UINT32 RsvdFlags; // Reserved for use as flags.
+ UINT32 NextHeaderBlock; // Offset from beginning of flash to the next header block.
+ UINT32 FlashItemCount; // Number of flash items within this header block.
+ UINT32 BootPriorityListCount; // Number of boot images within this MFH. All boot images must be within first MFH block.
+} MFH_HEADER;
+
+#pragma pack()
+
+#endif // #ifndef __MFH_H__
diff --git a/QuarkPlatformPkg/Include/Pcal9555.h b/QuarkPlatformPkg/Include/Pcal9555.h
new file mode 100644
index 0000000..cfbd46b
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Pcal9555.h
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ Pcal9555.h
+
+Abstract:
+
+ Definition for Pcal9555 I2c IO Expander.
+
+--*/
+
+#ifndef __PCAL9555_H__
+#define __PCAL9555_H__
+
+#define PCAL9555_REG_OUT_PORT0 0x02
+#define PCAL9555_REG_CFG_PORT0 0x06
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Platform.h b/QuarkPlatformPkg/Include/Platform.h
new file mode 100755
index 0000000..6f34ff5
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Platform.h
@@ -0,0 +1,142 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ Platform.h
+
+Abstract:
+
+ Quark platform specific information.
+
+--*/
+#include "Uefi.h"
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+//
+// Constant definition
+//
+#define MAX_SMRAM_RANGES 4
+#define MAX_NODE 1
+
+#define QUARK_STAGE1_IMAGE_TYPE_MASK 0xF0
+#define QUARK_STAGE1_BOOT_IMAGE_TYPE 0x00 // Stage1 Boot images 0x00 -> 0x0F.
+#define QUARK_STAGE1_RECOVERY_IMAGE_TYPE 0x10 // Stage1 Recovery images 0x10 -> 0x1F.
+
+#define QUARK_BOOTROM_BASE_ADDRESS 0xFFFE0000 // Base address of Quark ROM in memory map.
+#define QUARK_BOOTROM_SIZE_BYTES 0x20000 // Quark ROM is 128KB.
+#define SMM_DEFAULT_SMBASE 0x30000 // Default SMBASE address.
+#define SMM_DEFAULT_SMBASE_SIZE_BYTES 0x10000 // Size in bytes of default SMRAM.
+
+//
+// Gpio to be used to assert / deassert PCI express PERST# signal.
+//
+#define PCIEXP_PERST_RESUMEWELL_GPIO 3
+
+//
+// Minimum time in microseconds for assertion of PERST# signal.
+//
+#define PCIEXP_PERST_MIN_ASSERT_US 100
+
+//
+// Microsecond delay post issueing common lane reset.
+//
+#define PCIEXP_DELAY_US_POST_CMNRESET_RESET 1
+
+//
+// Microsecond delay to wait for PLL to lock.
+//
+#define PCIEXP_DELAY_US_WAIT_PLL_LOCK 80
+
+//
+// Microsecond delay post issueing sideband interface reset.
+//
+#define PCIEXP_DELAY_US_POST_SBI_RESET 20
+
+//
+// Microsecond delay post deasserting PERST#.
+//
+#define PCIEXP_DELAY_US_POST_PERST_DEASSERT 10
+
+//
+// Catastrophic Trip point in degrees Celsius for this platform.
+//
+#define PLATFORM_CATASTROPHIC_TRIP_CELSIUS 105
+
+//
+// This structure stores the base and size of the ACPI reserved memory used when
+// resuming from S3. This region must be allocated by the platform code.
+//
+typedef struct {
+ UINT32 AcpiReservedMemoryBase;
+ UINT32 AcpiReservedMemorySize;
+ UINT32 SystemMemoryLength;
+} RESERVED_ACPI_S3_RANGE;
+
+#define RESERVED_ACPI_S3_RANGE_OFFSET (EFI_PAGE_SIZE - sizeof (RESERVED_ACPI_S3_RANGE))
+
+//
+// Define valid platform types.
+// First add value before TypePlatformMax in EFI_PLATFORM_TYPE definition
+// and then add string description to end of EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION.
+//
+typedef enum {
+ TypeUnknown = 0, // !!! SHOULD BE THE FIRST ENTRY !!!
+ QuarkEmulation,
+ ClantonPeakSVP,
+ KipsBay,
+ CrossHill,
+ ClantonHill,
+ Galileo,
+ GalileoFabE,
+ GalileoGen2,
+ TypePlatformMax // !!! SHOULD BE THE LAST ENTRY !!!
+} EFI_PLATFORM_TYPE;
+
+#define EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION \
+ L"TypeUnknown",\
+ L"QuarkEmulation",\
+ L"ClantonPeakSVP",\
+ L"KipsBay",\
+ L"CrossHill",\
+ L"ClantonHill",\
+ L"Galileo",\
+ L"GalileoGen2", /* FabE should use same name as final Gen2 */\
+ L"GalileoGen2",\
+
+typedef struct {
+ UINT32 EntryOffset;
+ UINT8 ImageIndex;
+} QUARK_EDKII_STAGE1_HEADER;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/PlatformBoards.h b/QuarkPlatformPkg/Include/PlatformBoards.h
new file mode 100755
index 0000000..de942bb
--- /dev/null
+++ b/QuarkPlatformPkg/Include/PlatformBoards.h
@@ -0,0 +1,185 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PlatformBoards.h
+
+Abstract:
+
+ Board config definitions for each of the boards supported by this platform
+ package.
+
+--*/
+#include "Platform.h"
+
+#ifndef __PLATFORM_BOARDS_H__
+#define __PLATFORM_BOARDS_H__
+
+//
+// Constant definition
+//
+
+//
+// Default resume well TPM reset.
+//
+#define PLATFORM_RESUMEWELL_TPM_RST_GPIO 5
+
+//
+// Basic Configs for GPIO table definitions.
+//
+#define NULL_LEGACY_GPIO_INITIALIZER {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+#define ALL_INPUT_LEGACY_GPIO_INITIALIZER {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x3f,0x00}
+#define QUARK_EMULATION_LEGACY_GPIO_INITIALIZER ALL_INPUT_LEGACY_GPIO_INITIALIZER
+#define CLANTON_PEAK_SVP_LEGACY_GPIO_INITIALIZER {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x3f,0x00,0x00,0x3f,0x3f,0x00,0x3f,0x00}
+#define KIPS_BAY_LEGACY_GPIO_INITIALIZER {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x25,0x10,0x00,0x00,0x00,0x00,0x3f,0x00}
+#define CROSS_HILL_LEGACY_GPIO_INITIALIZER {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x03,0x10,0x00,0x03,0x03,0x00,0x3f,0x00}
+#define CLANTON_HILL_LEGACY_GPIO_INITIALIZER {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x06,0x10,0x00,0x04,0x04,0x00,0x3f,0x00}
+#define GALILEO_LEGACY_GPIO_INITIALIZER {0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x21,0x14,0x00,0x00,0x00,0x00,0x3f,0x00}
+#define GALILEO_FABE_LEGACY_GPIO_INITIALIZER {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x1f,0x00,0x00,0x00,0x00,0x00,0x3f,0x00}
+#define GALILEO_GEN2_LEGACY_GPIO_INITIALIZER {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x1c,0x02,0x00,0x00,0x00,0x00,0x3f,0x00}
+
+#define NULL_GPIO_CONTROLLER_INITIALIZER {0,0,0,0,0,0,0,0}
+#define ALL_INPUT_GPIO_CONTROLLER_INITIALIZER NULL_GPIO_CONTROLLER_INITIALIZER
+#define QUARK_EMULATION_GPIO_CONTROLLER_INITIALIZER NULL_GPIO_CONTROLLER_INITIALIZER
+#define CLANTON_PEAK_SVP_GPIO_CONTROLLER_INITIALIZER NULL_GPIO_CONTROLLER_INITIALIZER
+#define KIPS_BAY_GPIO_CONTROLLER_INITIALIZER {0x05,0x05,0,0,0,0,0,0}
+#define CROSS_HILL_GPIO_CONTROLLER_INITIALIZER {0x0D,0x2D,0,0,0,0,0,0}
+#define CLANTON_HILL_GPIO_CONTROLLER_INITIALIZER {0x01,0x39,0,0,0,0,0,0}
+#define GALILEO_GPIO_CONTROLLER_INITIALIZER {0x05,0x15,0,0,0,0,0,0}
+#define GALILEO_GEN2_GPIO_CONTROLLER_INITIALIZER {0x05,0x05,0,0,0,0,0,0}
+#define GALILEO_FABE_GPIO_CONTROLLER_INITIALIZER GALILEO_GEN2_GPIO_CONTROLLER_INITIALIZER
+
+//
+// Legacy Gpio to be used to assert / deassert PCI express PERST# signal
+// on Galileo Gen 2 platform.
+//
+#define GALILEO_GEN2_PCIEXP_PERST_RESUMEWELL_GPIO 0
+
+//
+// Galileo Gen 2 I2C PCAL9555 IO Expander definitions
+//
+#define PCAL9555_GALILEO_GEN2_7BIT_SLAVE_ADDR 0x27
+#define PCAL9555_GALILEO_GEN2_PORT0_CFG 0xff
+#define PCAL9555_GALILEO_GEN2_PORT1_CFG 0x9f
+#define PCAL9555_GALILEO_GEN2_PORT0_DEFAULT_OUT 0xff
+#define PCAL9555_GALILEO_GEN2_PORT1_DEFAULT_OUT 0xbf
+#define PCAL9555_GALILEO_GEN2_PERST_GPIO 13 // 0-7 Port0 8-15 Port1
+
+//
+// Legacy GPIO config struct for each element in PLATFORM_LEGACY_GPIO_TABLE_DEFINITION.
+//
+typedef struct {
+ UINT32 CoreWellEnable; ///< Value for QNC NC Reg R_QNC_GPIO_CGEN_CORE_WELL.
+ UINT32 CoreWellIoSelect; ///< Value for QNC NC Reg R_QNC_GPIO_CGIO_CORE_WELL.
+ UINT32 CoreWellLvlForInputOrOutput; ///< Value for QNC NC Reg R_QNC_GPIO_CGLVL_CORE_WELL.
+ UINT32 CoreWellTriggerPositiveEdge; ///< Value for QNC NC Reg R_QNC_GPIO_CGTPE_CORE_WELL.
+ UINT32 CoreWellTriggerNegativeEdge; ///< Value for QNC NC Reg R_QNC_GPIO_CGTNE_CORE_WELL.
+ UINT32 CoreWellGPEEnable; ///< Value for QNC NC Reg R_QNC_GPIO_CGGPE_CORE_WELL.
+ UINT32 CoreWellSMIEnable; ///< Value for QNC NC Reg R_QNC_GPIO_CGSMI_CORE_WELL.
+ UINT32 CoreWellTriggerStatus; ///< Value for QNC NC Reg R_QNC_GPIO_CGTS_CORE_WELL.
+ UINT32 CoreWellNMIEnable; ///< Value for QNC NC Reg R_QNC_GPIO_CGNMIEN_CORE_WELL.
+ UINT32 ResumeWellEnable; ///< Value for QNC NC Reg R_QNC_GPIO_RGEN_RESUME_WELL.
+ UINT32 ResumeWellIoSelect; ///< Value for QNC NC Reg R_QNC_GPIO_RGIO_RESUME_WELL.
+ UINT32 ResumeWellLvlForInputOrOutput;///< Value for QNC NC Reg R_QNC_GPIO_RGLVL_RESUME_WELL.
+ UINT32 ResumeWellTriggerPositiveEdge;///< Value for QNC NC Reg R_QNC_GPIO_RGTPE_RESUME_WELL.
+ UINT32 ResumeWellTriggerNegativeEdge;///< Value for QNC NC Reg R_QNC_GPIO_RGTNE_RESUME_WELL.
+ UINT32 ResumeWellGPEEnable; ///< Value for QNC NC Reg R_QNC_GPIO_RGGPE_RESUME_WELL.
+ UINT32 ResumeWellSMIEnable; ///< Value for QNC NC Reg R_QNC_GPIO_RGSMI_RESUME_WELL.
+ UINT32 ResumeWellTriggerStatus; ///< Value for QNC NC Reg R_QNC_GPIO_RGTS_RESUME_WELL.
+ UINT32 ResumeWellNMIEnable; ///< Value for QNC NC Reg R_QNC_GPIO_RGNMIEN_RESUME_WELL.
+} BOARD_LEGACY_GPIO_CONFIG;
+
+//
+// GPIO controller config struct for each element in PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION.
+//
+typedef struct {
+ UINT32 PortADR; ///< Value for IOH REG GPIO_SWPORTA_DR.
+ UINT32 PortADir; ///< Value for IOH REG GPIO_SWPORTA_DDR.
+ UINT32 IntEn; ///< Value for IOH REG GPIO_INTEN.
+ UINT32 IntMask; ///< Value for IOH REG GPIO_INTMASK.
+ UINT32 IntType; ///< Value for IOH REG GPIO_INTTYPE_LEVEL.
+ UINT32 IntPolarity; ///< Value for IOH REG GPIO_INT_POLARITY.
+ UINT32 Debounce; ///< Value for IOH REG GPIO_DEBOUNCE.
+ UINT32 LsSync; ///< Value for IOH REG GPIO_LS_SYNC.
+} BOARD_GPIO_CONTROLLER_CONFIG;
+
+///
+/// Table of BOARD_LEGACY_GPIO_CONFIG structures for each board supported
+/// by this platform package.
+/// Table indexed with EFI_PLATFORM_TYPE enum value.
+///
+#define PLATFORM_LEGACY_GPIO_TABLE_DEFINITION \
+ /* EFI_PLATFORM_TYPE - TypeUnknown*/\
+ NULL_LEGACY_GPIO_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - QuarkEmulation*/\
+ QUARK_EMULATION_LEGACY_GPIO_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - ClantonPeakSVP*/\
+ CLANTON_PEAK_SVP_LEGACY_GPIO_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - KipsBay*/\
+ KIPS_BAY_LEGACY_GPIO_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - CrossHill*/\
+ CROSS_HILL_LEGACY_GPIO_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - ClantonHill*/\
+ CLANTON_HILL_LEGACY_GPIO_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - Galileo*/\
+ GALILEO_LEGACY_GPIO_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - GalileoFabE*/\
+ GALILEO_FABE_LEGACY_GPIO_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - GalileoGen2*/\
+ GALILEO_GEN2_LEGACY_GPIO_INITIALIZER,\
+
+///
+/// Table of BOARD_GPIO_CONTROLLER_CONFIG structures for each board
+/// supported by this platform package.
+/// Table indexed with EFI_PLATFORM_TYPE enum value.
+///
+#define PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION \
+ /* EFI_PLATFORM_TYPE - TypeUnknown*/\
+ NULL_GPIO_CONTROLLER_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - QuarkEmulation*/\
+ QUARK_EMULATION_GPIO_CONTROLLER_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - ClantonPeakSVP*/\
+ CLANTON_PEAK_SVP_GPIO_CONTROLLER_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - KipsBay*/\
+ KIPS_BAY_GPIO_CONTROLLER_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - CrossHill*/\
+ CROSS_HILL_GPIO_CONTROLLER_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - ClantonHill*/\
+ CLANTON_HILL_GPIO_CONTROLLER_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - Galileo*/\
+ GALILEO_GPIO_CONTROLLER_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - GalileoFabE */\
+ GALILEO_FABE_GPIO_CONTROLLER_INITIALIZER,\
+ /* EFI_PLATFORM_TYPE - GalileoGen2*/\
+ GALILEO_GEN2_GPIO_CONTROLLER_INITIALIZER,\
+
+#endif
diff --git a/QuarkPlatformPkg/Include/PlatformData.h b/QuarkPlatformPkg/Include/PlatformData.h
new file mode 100755
index 0000000..158b0c4
--- /dev/null
+++ b/QuarkPlatformPkg/Include/PlatformData.h
@@ -0,0 +1,191 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformData.h
+
+Abstract:
+
+ Defines for Quark Platform Data Flash Area.
+
+--*/
+
+#ifndef __PLATFORM_DATA_H__
+#define __PLATFORM_DATA_H__
+
+///
+/// Unique identifier to allow quick sanity checking on our Platform Data Area.
+///
+#define PDAT_IDENTIFIER SIGNATURE_32 ('P', 'D', 'A', 'T')
+
+//
+// Length constants used for sanity checks.
+//
+
+#define PDAT_ITEM_DESC_LENGTH 10
+
+//
+// Platform data Item id definitions.
+//
+
+#define PDAT_ITEM_ID_INVALID 0x0000
+#define PDAT_ITEM_ID_PLATFORM_ID 0x0001
+#define PDAT_ITEM_ID_SERIAL_NUM 0x0002
+#define PDAT_ITEM_ID_MAC0 0x0003
+#define PDAT_ITEM_ID_MAC1 0x0004
+#define PDAT_ITEM_ID_MEM_CFG 0x0005
+#define PDAT_ITEM_ID_MRC_VARS 0x0006
+
+//
+// Public certificate for 'pk' variable.
+//
+#define PDAT_ITEM_ID_PK 0x0007
+
+//
+// SecureBoot records to be provisioned into 'kek', 'db' or 'dbx' variable.
+//
+#define PDAT_ITEM_ID_SB_RECORD 0x0008
+
+#pragma pack(1)
+
+///
+/// Platform Data item.
+///
+typedef struct {
+ UINT16 Identifier; ///< One of PDAT_ITEM_ID_XXXX constants above.
+ UINT16 Length; ///< Length in bytes of data part of item entry.
+ CHAR8 Description[PDAT_ITEM_DESC_LENGTH];
+ UINT16 Version;
+} PDAT_ITEM_HEADER;
+
+///
+/// Platform Data item.
+///
+typedef struct {
+ PDAT_ITEM_HEADER Header;
+ ///
+ /// In reality following field has byte length of
+ /// PDAT_ITEM_HEADER.Length.
+ ///
+ UINT8 Data[1];
+} PDAT_ITEM;
+
+///
+/// Platform Data Flash Area.
+///
+typedef struct {
+ UINT32 Identifier; ///< Should == PDAT_IDENTIFIER above.
+ UINT32 Length; ///< Length of body field.
+ UINT32 Crc; ///< Crc of Body field.
+} PDAT_AREA_HEADER;
+
+///
+/// Platform Data Flash Area.
+///
+typedef struct {
+ PDAT_AREA_HEADER Header;
+ PDAT_ITEM Body[1]; ///< In reality multiple PDAT_ITEM entries.
+} PDAT_AREA;
+
+//
+// Minimun MRC Platform Data version required for this release
+//
+#define PDAT_MRC_MIN_VERSION 0x01
+
+#define PDAT_MRC_FLAG_ECC_EN BIT0
+#define PDAT_MRC_FLAG_SCRAMBLE_EN BIT1
+#define PDAT_MRC_FLAG_MEMTEST_EN BIT2
+#define PDAT_MRC_FLAG_TOP_TREE_EN BIT3 ///< 0b DDR "fly-by" topology else 1b DDR "tree" topology.
+#define PDAT_MRC_FLAG_WR_ODT_EN BIT4 ///< If set ODR signal is asserted to DRAM devices on writes.
+
+///
+/// MRC Params Platform Data.
+///
+
+typedef struct {
+ UINT16 PlatformId; ///< Sanity check should equal data part of PDAT_ITEM_ID_PLATFORM_ID record.
+ UINT32 Flags; ///< Bitmap of PDAT_MRC_FLAG_XXX defs above.
+ UINT8 DramWidth; ///< 0=x8, 1=x16, others=RESERVED.
+ UINT8 DramSpeed; ///< 0=DDRFREQ_800, 1=DDRFREQ_1066, others=RESERVED. Only 533MHz SKU support 1066 memory.
+ UINT8 DramType; ///< 0=DDR3,1=DDR3L, others=RESERVED.
+ UINT8 RankMask; ///< bit[0] RANK0_EN, bit[1] RANK1_EN, others=RESERVED.
+ UINT8 ChanMask; ///< bit[0] CHAN0_EN, others=RESERVED.
+ UINT8 ChanWidth; ///< 1=x16, others=RESERVED.
+ UINT8 AddrMode; ///< 0, 1, 2 (mode 2 forced if ecc enabled), others=RESERVED.
+ UINT8 SrInt; ///< 1=1.95us, 2=3.9us, 3=7.8us, others=RESERVED. REFRESH_RATE.
+ UINT8 SrTemp; ///< 0=normal, 1=extended, others=RESERVED.
+ UINT8 DramRonVal; ///< 0=34ohm, 1=40ohm, others=RESERVED. RON_VALUE Select MRS1.DIC driver impedance control.
+ UINT8 DramRttNomVal; ///< 0=40ohm, 1=60ohm, 2=120ohm, others=RESERVED.
+ UINT8 DramRttWrVal; ///< 0=off others=RESERVED.
+ UINT8 SocRdOdtVal; ///< 0=off, 1=60ohm, 2=120ohm, 3=180ohm, others=RESERVED.
+ UINT8 SocWrRonVal; ///< 0=27ohm, 1=32ohm, 2=40ohm, others=RESERVED.
+ UINT8 SocWrSlewRate; ///< 0=2.5V/ns, 1=4V/ns, others=RESERVED.
+ UINT8 DramDensity; ///< 0=512Mb, 1=1Gb, 2=2Gb, 3=4Gb, others=RESERVED.
+ UINT32 tRAS; ///< ACT to PRE command period in picoseconds.
+ UINT32 tWTR; ///< Delay from start of internal write transaction to internal read command in picoseconds.
+ UINT32 tRRD; ///< ACT to ACT command period (JESD79 specific to page size 1K/2K) in picoseconds.
+ UINT32 tFAW; ///< Four activate window (JESD79 specific to page size 1K/2K) in picoseconds.
+ UINT8 tCL; ///< DRAM CAS Latency in clocks.
+} PDAT_MRC_ITEM;
+
+//
+// Secure boot record defs for PDAT_ITEM_ID_SB_RECORD items.
+// Secure boot record is made up of three sequentional data blobs.
+// 1) PDAT_SB_PAYLOAD_HEADER (required)
+// 2) GUID (optional) to identify record in secure boot data bases, depends on PDAT_SB_FLAG_HAVE_GUID.
+// 3) Certificate (required) data for one of PDAT_SB_CERT_TYPE_XXXX types.
+//
+
+#define PDAT_SB_CERT_TYPE_X509 0x00 // X509 certificate format using ASN.1 DER encoding.
+#define PDAT_SB_CERT_TYPE_SHA256 0x01 // 32byte SHA256 Image digest.
+#define PDAT_SB_CERT_TYPE_RSA2048 0x02 // Rsa2048 storing file (*.pbk).
+
+#define PDAT_SB_FLAG_HAVE_GUID BIT0
+
+typedef struct {
+ //
+ // Payload Secure Boot Store Specifier (UINT8 version of SECUREBOOT_STORE_TYPE)
+ //
+ UINT8 StoreType;
+
+ //
+ // One of PDAT_SB_CERT_TYPE_XXXX defs above.
+ // For KEKStore can be PDAT_SB_CERT_TYPE_X509 or PDAT_SB_CERT_TYPE_RSA2048.
+ // For DBStore/DBXStore can be PDAT_SB_CERT_TYPE_X509 or PDAT_SB_CERT_TYPE_SHA256.
+ //
+ UINT8 CertType;
+
+ UINT16 Flags; ///< Bitmap of PDAT_SB_FLAG_XXX defs above.
+} PDAT_SB_PAYLOAD_HEADER;
+
+#pragma pack()
+
+#endif // #ifndef __PLATFORM_DATA_H__
diff --git a/QuarkPlatformPkg/Include/Ppi/FlashMap.h b/QuarkPlatformPkg/Include/Ppi/FlashMap.h
new file mode 100644
index 0000000..5d71b75
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Ppi/FlashMap.h
@@ -0,0 +1,78 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ FlashMap.h
+
+Abstract:
+
+ FlashMap PPI defined in Tiano
+
+ This code abstracts FlashMap access
+
+--*/
+
+#ifndef _PEI_FLASH_MAP_PPI_H_
+#define _PEI_FLASH_MAP_PPI_H_
+
+#define PEI_FLASH_MAP_PPI_GUID \
+ { \
+ 0xf34c2fa0, 0xde88, 0x4270, {0x84, 0x14, 0x96, 0x12, 0x22, 0xf4, 0x52, 0x1c} \
+ }
+
+#include "EfiFlashMap.h"
+
+typedef struct _PEI_FLASH_MAP_PPI PEI_FLASH_MAP_PPI;
+
+//
+// Functions
+//
+typedef
+EFI_STATUS
+(EFIAPI *PEI_GET_FLASH_AREA_INFO) (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_FLASH_MAP_PPI * This,
+ IN EFI_FLASH_AREA_TYPE AreaType,
+ IN EFI_GUID * AreaTypeGuid,
+ OUT UINT32 *NumEntries,
+ OUT EFI_FLASH_SUBAREA_ENTRY **Entries
+ );
+
+//
+// PEI_FLASH_MAP_PPI
+//
+struct _PEI_FLASH_MAP_PPI {
+ PEI_GET_FLASH_AREA_INFO GetAreaInfo;
+};
+
+extern EFI_GUID gPeiFlashMapPpiGuid;
+
+#endif // _PEI_FLASH_MAP_PPI_H_
diff --git a/QuarkPlatformPkg/Include/Ppi/SStateBootMode.h b/QuarkPlatformPkg/Include/Ppi/SStateBootMode.h
new file mode 100644
index 0000000..5e01955
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Ppi/SStateBootMode.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SStateBootMode.h
+
+Abstract:
+
+ S-State Boot Mode PPI as defined in PEI CIS
+
+--*/
+
+#ifndef _S_STATE_BOOT_MODE_H
+#define _S_STATE_BOOT_MODE_H
+
+#define PEI_S_STATE_BOOT_MODE_PEIM_PPI \
+ { \
+ 0x9c44db3d, 0xf434, 0x4b91, {0x8e, 0xb3, 0x30, 0x38, 0xb1, 0x84, 0xab, 0xfc } \
+ }
+
+typedef struct _PEI_S_STATE_BOOT_MODE_PPI PEI_S_STATE_BOOT_MODE_PPI;
+
+extern EFI_GUID gPeiSStateBootModePpiGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Protocol/FirmwareVolumeBlockSecurity.h b/QuarkPlatformPkg/Include/Protocol/FirmwareVolumeBlockSecurity.h
new file mode 100644
index 0000000..24d6e04
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Protocol/FirmwareVolumeBlockSecurity.h
@@ -0,0 +1,86 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+ FirmwareVolumeBlockSecurity.h
+
+Abstract:
+ Protocol header file for FirmwareVolmeBlockSecurity Protocol.
+
+--*/
+
+#ifndef _FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL_H_
+#define _FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL_H_
+
+//
+// Constant definitions.
+//
+
+//
+// Type definitions.
+//
+
+///
+/// Forward reference for pure ANSI compatability
+///
+typedef struct _FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL;
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gFirmwareVolumeBlockSecurityGuid;
+
+//
+// Service typedefs to follow.
+//
+
+/**
+ Security library to authenticate the Firmware Volume.
+
+ @param ImageBaseAddress Pointer to the current Firmware Volume under consideration
+
+ @retval EFI_SUCCESS Firmware Volume is legal.
+ @retval EFI_SECURITY_VIOLATION Firmware Volume is NOT legal.
+
+ **/
+typedef
+EFI_STATUS
+(EFIAPI *FVB_SECURITY_AUTHENTICATE_IMAGE) (
+ IN VOID *ImageBaseAddress
+ );
+
+///
+/// Fvb security protocol declaration.
+///
+struct _FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL {
+ FVB_SECURITY_AUTHENTICATE_IMAGE SecurityAuthenticateImage; ///< see service typedef.
+};
+
+#endif // _FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL_H_
diff --git a/QuarkPlatformPkg/Include/Protocol/FvbExtension.h b/QuarkPlatformPkg/Include/Protocol/FvbExtension.h
new file mode 100644
index 0000000..fc0fe39
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Protocol/FvbExtension.h
@@ -0,0 +1,70 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ FvbExtension.h
+
+Abstract:
+
+ FVB Extension protocol that extends the FVB Class in a component fashion.
+
+--*/
+
+#ifndef _FVB_EXTENSION_H_
+#define _FVB_EXTENSION_H_
+
+ typedef struct _EFI_FVB_EXTENSION_PROTOCOL EFI_FVB_EXTENSION_PROTOCOL;
+
+// FVB Extension Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI * EFI_FV_ERASE_CUSTOM_BLOCK) (
+ IN EFI_FVB_EXTENSION_PROTOCOL *This,
+ IN EFI_LBA StartLba,
+ IN UINTN OffsetStartLba,
+ IN EFI_LBA LastLba,
+ IN UINTN OffsetLastLba
+);
+
+//
+// IPMI TRANSPORT PROTOCOL
+//
+ struct _EFI_FVB_EXTENSION_PROTOCOL {
+ EFI_FV_ERASE_CUSTOM_BLOCK EraseFvbCustomBlock;
+ };
+
+//
+
+extern EFI_GUID gEfiFvbExtensionProtocolGuid;
+
+#endif
+
diff --git a/QuarkPlatformPkg/Include/Protocol/GlobalNvsArea.h b/QuarkPlatformPkg/Include/Protocol/GlobalNvsArea.h
new file mode 100644
index 0000000..40aff32
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Protocol/GlobalNvsArea.h
@@ -0,0 +1,103 @@
+/** @file
+Definition of the global NVS area protocol. This protocol
+publishes the address and format of a global ACPI NVS buffer
+used as a communications buffer between SMM code and ASL code.
+The format is derived from the ACPI reference code, version 0.95.
+Note: Data structures defined in this protocol are not naturally aligned.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _GLOBAL_NVS_AREA_H_
+#define _GLOBAL_NVS_AREA_H_
+
+//
+// Forward reference for pure ANSI compatability
+//
+
+typedef struct _EFI_GLOBAL_NVS_AREA_PROTOCOL EFI_GLOBAL_NVS_AREA_PROTOCOL;
+
+//
+// Global NVS Area Protocol GUID
+//
+#define EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID \
+{ 0x74e1e48, 0x8132, 0x47a1, {0x8c, 0x2c, 0x3f, 0x14, 0xad, 0x9a, 0x66, 0xdc} }
+
+
+//
+// Global NVS Area definition
+//
+#pragma pack (1)
+typedef struct {
+ //
+ // Miscellaneous Dynamic Values
+ //
+ UINT32 OperatingSystemType; // Os type indicator
+ UINT32 Cfgd; // System configuration description
+ UINT32 HpetEnable;
+
+ UINT32 Pm1blkIoBaseAddress;
+ UINT32 PmbaIoBaseAddress;
+ UINT32 Gpe0blkIoBaseAddress;
+ UINT32 GbaIoBaseAddress;
+
+ UINT32 SmbaIoBaseAddress;
+ UINT32 SpiDmaIoBaseAddress;
+ UINT32 WdtbaIoBaseAddress;
+
+ UINT32 HpetBaseAddress;
+ UINT32 HpetSize;
+ UINT32 PciExpressBaseAddress;
+ UINT32 PciExpressSize;
+
+ UINT32 RcbaMmioBaseAddress;
+ UINT32 RcbaMmioSize;
+ UINT32 IoApicBaseAddress;
+ UINT32 IoApicSize;
+
+ UINT32 TpmPresent;
+
+ UINT8 Reserved[512 - 4 * 19]; // Total 512 Bytes
+} EFI_GLOBAL_NVS_AREA;
+#pragma pack ()
+
+//
+// Global NVS Area Protocol
+//
+struct _EFI_GLOBAL_NVS_AREA_PROTOCOL {
+ EFI_GLOBAL_NVS_AREA *Area;
+};
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gEfiGlobalNvsAreaProtocolGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Protocol/IioUds.h b/QuarkPlatformPkg/Include/Protocol/IioUds.h
new file mode 100755
index 0000000..bd24ed1
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Protocol/IioUds.h
@@ -0,0 +1,62 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ IohUds.h
+
+Abstract:
+
+ This protocol provides access to the Ioh Universal Data Structure
+
+ This protocol is EFI compatible.
+
+
+--*/
+
+#ifndef _IIO_UDS_H_
+#define _IIO_UDS_H_
+
+#include <Iio/IioUniversalData.h>
+
+#define EFI_IIO_UDS_PROTOCOL_GUID \
+ { 0xa7ced760, 0xc71c, 0x4e1a, 0xac, 0xb1, 0x89, 0x60, 0x4d, 0x52, 0x16, 0xcb }
+
+typedef struct _EFI_IIO_UDS_PROTOCOL {
+ IIO_UDS *IioUdsPtr;
+} EFI_IIO_UDS_PROTOCOL;
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gEfiIioUdsProtocolGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Protocol/PlatformSmmSpiReady.h b/QuarkPlatformPkg/Include/Protocol/PlatformSmmSpiReady.h
new file mode 100644
index 0000000..1238b57
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Protocol/PlatformSmmSpiReady.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PlatformSmmSpiReady.h
+
+Abstract:
+
+ This protocol indicates that the platform SPI interface is ready for use.
+
+--*/
+
+#ifndef _PLATFORM_SPI_READY_H_
+#define _PLATFORM_SPI_READY_H_
+
+// {7A5DBC75-5B2B-4e67-BDE1-D48EEE761562}
+#define EFI_SMM_SPI_READY_PROTOCOL_GUID \
+ { 0x7a5dbc75, 0x5b2b, 0x4e67, 0xbd, 0xe1, 0xd4, 0x8e, 0xee, 0x76, 0x15, 0x62 }
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gEfiSmmSpiReadyProtocolGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Protocol/PlatformType.h b/QuarkPlatformPkg/Include/Protocol/PlatformType.h
new file mode 100755
index 0000000..77ea833
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Protocol/PlatformType.h
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+ PlatformType.h
+
+Abstract:
+ This file defines platform policies for Platform Type.
+
+--*/
+
+#ifndef _PLATFORM_TYPE_H_
+#define _PLATFORM_TYPE_H_
+
+#include <Guid/PlatformInfo.h>
+
+typedef struct _EFI_PLATFORM_TYPE_PROTOCOL {
+ UINT8 SystemUuid[16]; // 16 bytes
+ UINT32 Signature; // "$PIT" 0x54495024
+ UINT32 Size; // Size of the table
+ UINT16 Revision; // Revision of the table
+ UINT16 Type; // Platform Type
+ UINT32 TypeRevisionId; // Board Revision ID
+ UINT8 CpuType; // Cpu Type
+ UINT8 CpuStepping; // Cpu Stepping
+ UINT16 IioSku;
+ UINT16 IioRevision;
+ UINT16 QncSku;
+ UINT16 QncRevision;
+ UINT32 FirmwareVersion;
+ BOOLEAN ExtendedInfoValid; // If TRUE then below fields are Valid
+ UINT8 Checksum; // Checksum minus SystemUuid is valid in DXE only.
+ EFI_STRING TypeStringPtr;
+ EFI_GUID BiosPlatformDataFile;
+ EFI_PLATFORM_PCI_DATA PciData;
+ EFI_PLATFORM_CPU_DATA CpuData;
+ EFI_PLATFORM_MEM_DATA MemData;
+ EFI_PLATFORM_SYS_DATA SysData;
+ UINT32 FlashDeviceSize; // Size in bytes of flash device on this platform.
+ UINT64 IioStringPtr;
+ UINT64 QncStringPtr;
+} EFI_PLATFORM_TYPE_PROTOCOL;
+
+extern EFI_GUID gEfiPlatformTypeProtocolGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Include/Protocol/SecureBootHelper.h b/QuarkPlatformPkg/Include/Protocol/SecureBootHelper.h
new file mode 100644
index 0000000..9a6b0cb
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Protocol/SecureBootHelper.h
@@ -0,0 +1,765 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+ SecureBootHelper.h
+
+Abstract:
+ Protocol header file for Secure Boot Helper Protocol.
+
+--*/
+
+#ifndef _SECUREBOOT_HELPER_PROTOCOL_H_
+#define _SECUREBOOT_HELPER_PROTOCOL_H_
+
+#include <IndustryStandard/PeImage.h>
+#include <Guid/ImageAuthentication.h>
+#include <Protocol/DevicePath.h>
+
+//
+// Constant definitions.
+//
+
+#define TWO_BYTE_ENCODE 0x82
+#define WIN_CERT_UEFI_RSA2048_SIZE 256
+
+///
+/// Image type definitions (BIT0 - BIT4 Matchs whats shown in SecurityPkg.dec).
+/// Added BIT31 (IMAGE_FROM_PXE) since GET_IMAGE_FROM_MASK service can
+/// determine this from location. Lower bits left for SecurityPkg additions.
+///
+#define IMAGE_UNKNOWN 0x00000001
+#define IMAGE_FROM_FV 0x00000002
+#define IMAGE_FROM_OPTION_ROM 0x00000004
+#define IMAGE_FROM_REMOVABLE_MEDIA 0x00000008
+#define IMAGE_FROM_FIXED_MEDIA 0x00000010
+#define IMAGE_FROM_PXE 0x80000000
+
+///
+/// Hash types.
+///
+#define HASHALG_SHA1 0x00000000
+#define HASHALG_SHA224 0x00000001
+#define HASHALG_SHA256 0x00000002
+#define HASHALG_SHA384 0x00000003
+#define HASHALG_SHA512 0x00000004
+#define HASHALG_MAX 0x00000005
+
+///
+/// Set max digest size, set 96 to future proof.
+///
+#define MAX_DIGEST_SIZE 96
+
+//
+// Type definitions.
+//
+
+///
+/// We define another format of 5th directory entry: security directory.
+///
+typedef struct {
+ UINT32 Offset; ///< Offset of certificate.
+ UINT32 SizeOfCert; ///< size of certificate appended.
+} EFI_IMAGE_SECURITY_DATA_DIRECTORY;
+
+///
+/// Image type determined when Secure Boot Helper loads a PE Image.
+///
+typedef enum {
+ ImageType_IA32,
+ ImageType_X64
+} SECUREBOOT_PEIMAGE_IMAGE_TYPE;
+
+///
+/// Info on determined when Secure Boot Helper loads a PE Image.
+///
+typedef struct {
+ UINT8 *ImageBase;
+ UINTN ImageSize;
+ SECUREBOOT_PEIMAGE_IMAGE_TYPE ImageType;
+ UINT32 PeCoffHdrOff;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION NtHeader;
+ EFI_IMAGE_SECURITY_DATA_DIRECTORY *SecDataDir;
+ WIN_CERTIFICATE *Certificate;
+ EFI_GUID ImageCertType;
+ UINTN ImageDigestSize;
+ UINT8 ImageDigest [MAX_DIGEST_SIZE];
+} SECUREBOOT_PEIMAGE_LOAD_INFO;
+
+///
+/// SecureBoot statistics for Secure Boot variables.
+///
+typedef struct {
+ BOOLEAN PkEnrolled; ///< Is 'pk' variable enrolled.
+ UINT32 PkAttributes; ///< 'pk' variable attributes.
+ BOOLEAN KekEnrolled; ///< Is 'kek' variable enrolled.
+ UINTN KekAttributes; ///< 'kek' variable attributes.
+ UINTN KekTotalCertCount; ///< Total number of certs in 'kek' database variable.
+ UINTN KekX509CertCount; ///< Number of X509 certs in 'kek' database variable.
+ UINTN KekRsa2048CertCount; ///< Number of Rsa2048 storing file (*.pbk) certs in 'kek' database variable.
+ UINTN KekOtherCertCount; ///< Unspecified cert types stored in kek.
+ BOOLEAN DbEnrolled; ///< Is 'Db' variable enrolled.
+ UINTN DbAttributes; ///< 'Db' variable attributes.
+ UINTN DbTotalCertCount; ///< Total number of certs in 'Db' database variable.
+ UINTN DbX509CertCount; ///< Number of X509 certs in 'Db' database variable.
+ UINTN DbSha256Count; ///< Number of Sha256 digests in 'Db' database variable.
+ UINTN DbSha1Count; ///< Number of Sha1 digests in 'Db' database variable.
+ UINTN DbOtherCertCount; ///< Unspecified cert types stored in Db.
+ BOOLEAN DbxEnrolled; ///< Is 'Dbx' variable enrolled.
+ UINTN DbxAttributes; ///< 'Dbx' variable attributes.
+ UINTN DbxTotalCertCount; ///< Total number of certs in 'Dbx' database variable.
+ UINTN DbxX509CertCount; ///< Number of X509 certs in 'Dbx' database variable.
+ UINTN DbxSha256Count; ///< Number of Sha256 digests in 'Dbx' database variable.
+ UINTN DbxSha1Count; ///< Number of Sha1 digests in 'Dbx' database variable.
+ UINTN DbxOtherCertCount; ///< Unspecified cert types stored in Dbx.
+ UINTN MaxVarSize; ///< Sizeof biggest SecureBoot variable pk,kek,db or dbx.
+} SECUREBOOT_VARIABLE_STATS;
+
+///
+/// Secure Boot Store Type.
+///
+typedef enum {
+ PKStore = 0, ///< Private Key Store.
+ KEKStore = 1, ///< Key Exchange Key Database.
+ DBStore = 2, ///< Authorized Signature Database.
+ DBXStore = 3 ///< Forbidden Signature Database.
+} SECUREBOOT_STORE_TYPE;
+
+///
+/// Filter for finding certificate lists in secure boot databases.
+///
+typedef struct {
+ EFI_GUID *SignatureType; ///< Identifier of certificate list type.
+ EFI_GUID *SignatureOwner; ///< Identifier of Specific cert in list.
+ UINTN SignatureDataPayloadSize; ///< Payload size of cert list.
+} FIND_CERT_FILTER;
+
+///
+/// Optional stats returned from FIND_FIRST_CERT service.
+///
+typedef struct {
+ UINTN VariableSize; ///< Byte size of cert variable.
+ UINT32 VariableAttributes; ///< Attributes of cert variable.
+} FIND_CERT_STATS;
+
+///
+/// Forward reference for pure ANSI compatability
+///
+typedef struct _SECUREBOOT_HELPER_PROTOCOL SECUREBOOT_HELPER_PROTOCOL;
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gSecureBootHelperProtocolGuid;
+
+//
+// Service typedefs to follow.
+//
+
+/** Check if platform is operating by a physically present user.
+
+ This function provides a platform-specific method to detect whether the platform
+ is operating by a physically present user.
+
+ Programmatic changing of platform security policy (such as disable Secure Boot,
+ or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during
+ Boot Services or after exiting EFI Boot Services. Only a physically present user
+ is allowed to perform these operations.
+
+ NOTE THAT: This function cannot depend on any EFI Variable Service since they are
+ not available when this function is called in AuthenticateVariable driver.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval TRUE The platform is operated by a physically present user.
+ @retval FALSE The platform is NOT operated by a physically present user.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *IS_USER_PHYSICAL_PRESENT) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+/**
+ Caculate hash of multiple buffers using the specified Hash algorithm.
+
+ @param[in] This Pointer to located SECUREBOOT_HELPER_PROTOCOL.
+ @param[in] HashAlg Hash algorithm type see HASHALG_"XXX" defs.
+ @param[in, out] DigestSize Size of Digest, on out bytes used in Digest.
+ @param[out] Digest Hash digest written to this buffer.
+ @param ... Pairs of parmas, Buffer Base pointer (A NULL
+ terminates the list) followed by buffer len.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER DigestBuf == NULL or DigestSize == NULL.
+ @retval EFI_BUFFER_TOO_SMALL DigestBuf buffer is too small.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete operation.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+ @retval EFI_UNSUPPORTED The specified algorithm is not supported.
+
+ **/
+typedef
+EFI_STATUS
+(EFIAPI *HASH_MULTIPLE_BUFFERS) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST UINT32 HashAlg,
+ IN OUT UINTN *DigestSize,
+ OUT UINT8 *DigestBuf,
+ ...
+ );
+
+/** Load PE/COFF image information into buffer and check its validity.
+
+ Function returns Pointer to SECUREBOOT_PEIMAGE_LOAD_INFO see
+ Protocol/SecureBootHelper.h.
+
+ Function also calculates HASH of image if CalcHash param == TRUE.
+ If SecurityCert in image then hash algo. is the algo specified by the
+ Cert else a SHA256 digest is calculated.
+
+ Caller must FreePool returned pointer when they are finished.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] FileDevicePath Device Path of PE image file.
+ @param[in] CalcHash Flag to tell loader to calc. hash of image.
+
+ @retval NULL unable to load image.
+ @return Pointer to SECUREBOOT_PEIMAGE_LOAD_INFO struct which contains a
+ memory block with image info and actual image data.
+
+**/
+typedef
+SECUREBOOT_PEIMAGE_LOAD_INFO *
+(EFIAPI *LOAD_PE_IMAGE) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST BOOLEAN CalcHash
+ );
+
+/** Check if secure boot enabled.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval TRUE Secure Boot enabled.
+ @retval FALSE Secure Boot disabled.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *IS_SECURE_BOOT_ENABLED) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+/** Check if secure boot mode is in custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval TRUE Secure Boot mode is in custom mode.
+ @retval FALSE Secure Boot mode is NOT in custom mode.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *IS_SECURE_BOOT_IN_CUSTOM_MODE) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+/** Set Secure Boot Mode to Custom Mode.
+
+ To be called when for SecureBoot in Setup or when the platform
+ is operating by a physically present user..
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval EFI_SUCCESS Set success.
+ @retval EFI_ACCESS_DENIED Can't set mode if Secure Boot enabled.
+ @retval EFI_INVALID_PARAMETER This pointer is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @return Other Unexpected error - unable to verify.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_SET_SECURE_BOOT_CUSTOM_MODE) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+/** Set Secure Boot Mode to default security Mode.
+
+ To be called when for SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval EFI_SUCCESS Set success.
+ @retval EFI_ACCESS_DENIED Can't set mode if Secure Boot enabled.
+ @retval EFI_INVALID_PARAMETER This pointer is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @return Other Unexpected error - unable to verify.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_SET_SECURE_BOOT_DEFAULT_MODE) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+/** Check if Platform Key is enrolled.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[out] Optional return of size of 'pk' variable.
+ @param[out] Optional return of attributes of 'pk' variable.
+
+ @retval TRUE Platform Key is enrolled.
+ @retval FALSE System has no Platform Key or Error with key var.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *IS_PK_ENROLLED) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ OUT UINTN *PkVarSize OPTIONAL,
+ OUT UINT32 *PkVarAttr OPTIONAL
+ );
+
+/**
+ Create time based authenticated variable playload for SecureBoot Setup Mode.
+
+ Also work in SecureBoot Custom Mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in, out] DataSize On input, the size of Data buffer in bytes.
+ On output, the size of data returned in Data
+ buffer in bytes.
+ @param[in, out] Data On input, Pointer to data buffer to be wrapped or
+ pointer to NULL to wrap an empty payload.
+ On output, Pointer to the new payload date buffer allocated from pool,
+ it's caller's responsibility to free the memory when finish using it.
+
+ @retval EFI_SUCCESS Create time based payload successfully.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval Others Unexpected error happens.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_CREATE_TIME_BASED_AUTH_VAR_PAYLOAD) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT8 **Data
+ );
+
+/** Set authenticated variable for SecureBoot in Setup or Custom mode.
+
+ This code sets an authenticated variable in storage blocks
+ (Volatile or Non-Volatile).
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName Name of Variable to set.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] Attr Attribute value of the variable found
+ @param[in] DataSize Size of Data found. If size is less than the
+ data, this value contains the required size.
+ @param[in] Data Data pointer.
+ @param[in] AppendIfExists If TRUE then force append of data if var exists.
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_SUCCESS Set successfully.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_WRITE_PROTECTED Variable is read-only.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_SET_TIME_BASED_AUTH_VARIABLE) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attr,
+ IN UINTN DataSize,
+ IN UINT8 *Data,
+ IN BOOLEAN AppendIfExists
+ );
+
+/** Delete entry from secure boot database for SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName The variable name of the vendor's signature database.
+ @param[in] VendorGuid A unique identifier for the vendor.
+ @param[in] SignatureOwner Signature GUID to delete.
+
+ @retval EFI_SUCCESS Delete cert success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Can't find the cert item.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+
+ **/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_DELETE_CERT) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST EFI_GUID *SignatureOwner
+ );
+
+/** Append cert to KEK, DB or DBX vars for SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName Variable name of signature database.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] CertType Signature hash type.
+ @param[in] SignatureOwner GUID to identify signature.
+ @param[in] SigDataSize Signature data size.
+ @param[in] SigData Signature data.
+
+ @retval EFI_SUCCESS The variable has been appended successfully.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @retval Others Unexpected error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_APPEND_CERT) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST EFI_GUID *CertType,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL,
+ IN CONST UINTN SigDataSize OPTIONAL,
+ IN CONST UINT8 *SigData OPTIONAL
+ );
+
+/** Find first cert. list in security database that matches filter criteria.
+
+ If Filter == NULL then return first cert list in database.
+
+ Caller must call Find Cert Close to free resources allocated by this find.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName Security database variable name.
+ @param[in] VendorGuid Security database variable vendor GUID.
+ @param[in] Filter Filter criteria.
+ @param[out] CertList Pointer to update with address of EFI_SIGNATURE_LIST.
+ @param[out] CertData Pointer to update with address of EFI_SIGNATURE_DATA.
+
+ @retval NULL Nothing found in database.
+ @retval other Pointer to this found context to be passed to Find Next Cert
+ and Find Cert Close.
+ @return Updated CertList with address of EFI_SIGNATURE_LIST structure of the
+ found certificate list.
+ @return Optionally update CertData with address of EFI_SIGNATURE_DATA of the
+ found certificate list.
+
+**/
+typedef
+VOID *
+(EFIAPI *FIND_FIRST_CERT) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN FIND_CERT_FILTER *Filter OPTIONAL,
+ OUT EFI_SIGNATURE_LIST **CertList,
+ OUT EFI_SIGNATURE_DATA **CertData OPTIONAL,
+ OUT FIND_CERT_STATS *Stats OPTIONAL
+ );
+
+/** Find next cert. list in security database that matches filter criteria.
+
+ If Filter == NULL then return next cert list in database.
+
+ @param[in] FindContext Return from previous call to Find First Cert.
+ @param[in] Filter Filter criteria.
+ @param[out] CurrCertList Current position in security database.
+ @param[out] CertData Pointer to update with address of EFI_SIGNATURE_DATA.
+
+ @retval NULL Reached end of database.
+ @retval other Pointer to EFI_SIGNATURE_LIST structure of the
+ next certificate list.
+ @return Optionally update CertData with address of EFI_SIGNATURE_DATA of the
+ next certificate list.
+
+**/
+typedef
+EFI_SIGNATURE_LIST *
+(EFIAPI *FIND_NEXT_CERT) (
+ IN VOID *FindContext,
+ IN FIND_CERT_FILTER *Filter,
+ IN EFI_SIGNATURE_LIST *CurrCertList,
+ OUT EFI_SIGNATURE_DATA **CertData
+ );
+
+/** Free resources allocated by Find First Cert.
+
+ @param[in] FindContext Return from previous call to Find First Cert.
+
+**/
+typedef
+VOID
+(EFIAPI *FIND_CERT_CLOSE) (
+ IN VOID *FindContext
+ );
+
+/** Enroll X509 Cert file into PK, KEK, DB or DBX database.
+
+ For use with SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] StoreType PKStore, KEKStore, DBStore or DBXStore.
+ @param[in] FileDevicePath Device Path of X509 certificate file (.der /.cer / .crt)
+ in format using ASN.1 DER encoding.
+ @param[in] SourceBuffer If not NULL, a pointer to the memory location containing a copy
+ of the certificate, overrides FileDevicePath.
+ @param[in] SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL.
+ @param[in] SignatureOwner Identifier for this enrollment.
+
+ @retval EFI_SUCCESS Enroll success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @retval EFI_WRITE_PROTECTED Resource is read-only.
+ @retval EFI_NOT_FOUND File not found.
+ @retval EFI_SECURITY_VIOLATION System in invalid mode for operation.
+ @retval Others Unexpected error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_ENROLL_X509) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ );
+
+/** Enroll Rsa2048 storing file (*.pbk) into KEK database.
+
+ SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] FileDevicePath Device Path of Rsa2048 storing file (*.pbk).
+ @param[in] SourceBuffer If not NULL, a pointer to the memory location containing a copy
+ of the pbk file, overrides FileDevicePath.
+ @param[in] SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL.
+ @param[in] SignatureOwner Identifier for this enrollment.
+
+ @retval EFI_SUCCESS Enroll success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @retval EFI_WRITE_PROTECTED Resource is read-only.
+ @retval EFI_UNSUPPORTED Unsupported file.
+ @retval EFI_NOT_FOUND File not found.
+ @retval EFI_SECURITY_VIOLATION System in invalid mode for operation.
+ @retval Others Unexpected error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_ENROLL_KEK_RSA2048) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ );
+
+/** Enroll Image Signature into secure boot database.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] StoreType PKStore, KEKStore, DBStore or DBXStore.
+ @param[in] FileDevicePath Device Path of image to enroll.
+ @param[in] SourceBuffer If not NULL, a pointer to the memory location containing SHA256
+ 32 byte image digest. Assumed to match &gEfiCertSha256Guid.
+ @param[in] SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL.
+ @param[in] SignatureOwner Identifier for this enrollment.
+
+ @retval EFI_SUCCESS Enroll success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @retval EFI_WRITE_PROTECTED Resource is read-only.
+ @retval EFI_UNSUPPORTED Unsupported image type.
+ @retval EFI_NOT_FOUND File not found.
+ @retval EFI_SECURITY_VIOLATION System in invalid mode for operation.
+ @retval Others Unexpected error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_ENROLL_IMAGE_SIGNATURE) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ );
+
+/** Delete record in SecureBoot PK, KEK, DB or DBX or delete a complete store.
+
+ SecureBoot in Setup/Custom mode.
+
+ if CompleteStore then reset StoreType with all certs deleted.
+ CompleteStore param ignored if StoreType == PKStore ie complete PK always reset.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] StoreType PKStore, KEKStore, DBStore or DBXStore.
+ @param[in] CompleteStore If true reset complete secure boot store (StoreType).
+ @param[in] SignatureOwner Specific record in store to delete.
+
+ @retval EFI_SUCCESS Delete success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to do operation.
+ @retval EFI_WRITE_PROTECTED Resource is read-only.
+ @retval EFI_SECURITY_VIOLATION System in invalid mode for operation.
+ @retval Others Unexpected error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_DELETE_STORE_RECORD) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST BOOLEAN CompleteStore,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ );
+
+/** Get the file image from mask.
+
+ If This or File pointers are NULL, then ASSERT().
+ If sanity checks on This pointer fail then ASSERT().
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] File This is a pointer to the device path of the file
+ to get IMAGE_FROM_XXX mask for.
+
+ @return UINT32 Mask which is one of IMAGE_FROM_XXX defs in protocol header file.
+
+**/
+
+typedef
+UINT32
+(EFIAPI *GET_IMAGE_FROM_MASK) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File
+ );
+
+/** Get statistics for SecureBoot PK, KEK, DB and DBX variables.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[out] Stats Caller allocated SECUREBOOT_VARIABLE_STATS
+ struct filled out by this routine.
+
+ @retval EFI_SUCCESS Operation success with Stats filled out.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval Others Unexpected error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *GET_SECUREBOOT_VARIABLE_STATS) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ OUT SECUREBOOT_VARIABLE_STATS *Stats
+ );
+
+/** Create Time based authenticated variable for SecureBoot Setup/Custom Mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName Name of Variable to set.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] LeaveIfExists If variable already exists do nothing.
+
+ @retval EFI_SUCCESS The variable has been appended successfully.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @retval EFI_WRITE_PROTECTED Variable is read-only.
+ @retval Others Unexpected error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_CREATE_TIME_BASED_AUTH_VAR) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST BOOLEAN LeaveIfExists
+ );
+
+/** Create Empty DB & DBX if they do not exist.
+
+ SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval EFI_SUCCESS The variable has been appended successfully.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @retval Others Unexpected error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SETUP_CREATE_EMPTY_DB_DBX_IF_NOT_EXIST) (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+///
+/// Secure Boot helper protocol declaration.
+///
+struct _SECUREBOOT_HELPER_PROTOCOL {
+ IS_USER_PHYSICAL_PRESENT IsUserPhysicalPresent; ///< see service typedef.
+ HASH_MULTIPLE_BUFFERS HashMultipleBuffers; ///< see service typedef.
+ LOAD_PE_IMAGE LoadPeImage; ///< see service typedef.
+ IS_SECURE_BOOT_ENABLED IsSecureBootEnabled; ///< see service typedef.
+ IS_SECURE_BOOT_IN_CUSTOM_MODE IsSecureBootInCustomMode; ///< see service typedef.
+ SETUP_SET_SECURE_BOOT_CUSTOM_MODE SetupSetSecureBootCustomMode; ///< see service typedef.
+ SETUP_SET_SECURE_BOOT_DEFAULT_MODE SetupSetSecureBootDefaultMode; ///< see service typedef.
+ SETUP_CREATE_TIME_BASED_AUTH_VAR_PAYLOAD SetupCreateTimeBasedAuthVarPayload; ///< see service typedef.
+ SETUP_SET_TIME_BASED_AUTH_VARIABLE SetupSetTimeBasedAuthVariable; ///< see service typedef.
+ SETUP_DELETE_CERT SetupDeleteCert; ///< see service typedef.
+ SETUP_APPEND_CERT SetupAppendCert; ///< see service typedef.
+ FIND_FIRST_CERT FindFirstCert; ///< see service typedef.
+ FIND_NEXT_CERT FindNextCert; ///< see service typedef.
+ FIND_CERT_CLOSE FindCertClose; ///< see service typedef.
+ IS_PK_ENROLLED IsPkEnrolled; ///< see service typedef.
+ SETUP_ENROLL_X509 SetupEnrollX509; ///< see service typedef.
+ SETUP_ENROLL_KEK_RSA2048 SetupEnrollKekRsa2048; ///< see service typedef.
+ SETUP_ENROLL_IMAGE_SIGNATURE SetupEnrollImageSignature; ///< see service typedef.
+ SETUP_DELETE_STORE_RECORD SetupDeleteStoreRecord; ///< see service typedef.
+ GET_IMAGE_FROM_MASK GetImageFromMask; ///< see service typedef.
+ GET_SECUREBOOT_VARIABLE_STATS GetSecureBootVarStats; ///< see service typedef.
+ SETUP_CREATE_TIME_BASED_AUTH_VAR SetupCreateTimeBasedAuthVar; ///< see service typedef.
+ SETUP_CREATE_EMPTY_DB_DBX_IF_NOT_EXIST SetupCreateEmptyDbDbxIfNotExist; ///< see service typedef.
+};
+
+#endif // _SECUREBOOT_HELPER_PROTOCOL_H_
diff --git a/QuarkPlatformPkg/Include/QuarkPlatformDxe.h b/QuarkPlatformPkg/Include/QuarkPlatformDxe.h
new file mode 100644
index 0000000..698b5ae
--- /dev/null
+++ b/QuarkPlatformPkg/Include/QuarkPlatformDxe.h
@@ -0,0 +1,42 @@
+/**@file
+ The common DXE header file for QuarkPlatformPkg.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __QUARK_PLATFORM_DXE_H__
+#define __QUARK_PLATFORM_DXE_H__
+
+#define EFI_EVENT_NOTIFY_SIGNAL_ALL 0x00000400
+
+#define EFI_EVENT_SIGNAL_READY_TO_BOOT 0x00000203
+#define EFI_EVENT_SIGNAL_LEGACY_BOOT 0x00000204
+
+#endif
diff --git a/QuarkPlatformPkg/Include/QuarkPlatformPeim.h b/QuarkPlatformPkg/Include/QuarkPlatformPeim.h
new file mode 100644
index 0000000..8a8db66
--- /dev/null
+++ b/QuarkPlatformPkg/Include/QuarkPlatformPeim.h
@@ -0,0 +1,41 @@
+/**@file
+ The common PEIM header file for QuarkNcSocId package
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef __QUARK_PLATFORM_PEIM_H__
+#define __QUARK_PLATFORM_PEIM_H__
+
+//#include <SetupVariable.h>
+#include <Guid/PlatformMemoryLayout.h>
+#include <Ppi/SStateBootMode.h>
+
+#endif
+
diff --git a/QuarkPlatformPkg/Include/Tbd/EfiBootScript.h b/QuarkPlatformPkg/Include/Tbd/EfiBootScript.h
new file mode 100644
index 0000000..b80c72c
--- /dev/null
+++ b/QuarkPlatformPkg/Include/Tbd/EfiBootScript.h
@@ -0,0 +1,244 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ EfiBootScript.h
+
+Abstract:
+
+
+
+--*/
+
+#ifndef _EFI_BOOT_SCRIPT_H_
+#define _EFI_BOOT_SCRIPT_H_
+
+#define EFI_ACPI_S3_RESUME_SCRIPT_TABLE 0x00
+
+//
+// Boot Script Opcode Definitions
+//
+typedef const UINT16 EFI_BOOT_SCRIPT_OPCODE;
+
+#define EFI_BOOT_SCRIPT_IO_WRITE_OPCODE 0x00
+#define EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE 0x01
+#define EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE 0x02
+#define EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE 0x03
+#define EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE 0x04
+#define EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE 0x05
+#define EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE 0x06
+#define EFI_BOOT_SCRIPT_STALL_OPCODE 0x07
+#define EFI_BOOT_SCRIPT_DISPATCH_OPCODE 0x08
+
+//
+// Extensions to boot script definitions
+//
+//#define EFI_BOOT_SCRIPT_MEM_POLL_OPCODE 0x09
+#define EFI_BOOT_SCRIPT_INFORMATION_OPCODE 0x0A
+#define EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE 0x0B
+#define EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE 0x0C
+
+#define EFI_BOOT_SCRIPT_TABLE_OPCODE 0xAA
+#define EFI_BOOT_SCRIPT_TERMINATE_OPCODE 0xFF
+
+#pragma pack(1)
+
+//
+// EFI Boot Script Width
+//
+/*typedef enum {
+ EfiBootScriptWidthUint8,
+ EfiBootScriptWidthUint16,
+ EfiBootScriptWidthUint32,
+ EfiBootScriptWidthUint64,
+ EfiBootScriptWidthFifoUint8,
+ EfiBootScriptWidthFifoUint16,
+ EfiBootScriptWidthFifoUint32,
+ EfiBootScriptWidthFifoUint64,
+ EfiBootScriptWidthFillUint8,
+ EfiBootScriptWidthFillUint16,
+ EfiBootScriptWidthFillUint32,
+ EfiBootScriptWidthFillUint64,
+ EfiBootScriptWidthMaximum
+} EFI_BOOT_SCRIPT_WIDTH;
+*/
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+} EFI_BOOT_SCRIPT_GENERIC_HEADER;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT16 Version;
+ UINT32 TableLength;
+ UINT16 Reserved[2];
+} EFI_BOOT_SCRIPT_TABLE_HEADER;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+} EFI_BOOT_SCRIPT_COMMON_HEADER;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT32 Count;
+ UINT64 Address;
+} EFI_BOOT_SCRIPT_IO_WRITE;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT64 Address;
+} EFI_BOOT_SCRIPT_IO_READ_WRITE;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT32 Count;
+ UINT64 Address;
+} EFI_BOOT_SCRIPT_MEM_WRITE;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT64 Address;
+} EFI_BOOT_SCRIPT_MEM_READ_WRITE;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT32 Count;
+ UINT64 Address;
+} EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT32 Count;
+ UINT64 Address;
+ UINT16 Segment;
+} EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT64 Address;
+} EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT64 Address;
+ UINT16 Segment;
+} EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE;
+
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT64 SlaveAddress;
+ UINT64 Command;
+ UINT32 Operation;
+ BOOLEAN PecCheck;
+ UINT32 DataSize;
+} EFI_BOOT_SCRIPT_SMBUS_EXECUTE;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT64 Duration;
+} EFI_BOOT_SCRIPT_STALL;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ EFI_PHYSICAL_ADDRESS EntryPoint;
+} EFI_BOOT_SCRIPT_DISPATCH;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 Width;
+ UINT64 Address;
+ UINT64 BitMask;
+ UINT64 BitValue;
+ UINT64 Duration;
+ UINT64 LoopTimes;
+} EFI_BOOT_SCRIPT_MEM_POLL;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+ UINT32 InformationLength;
+ EFI_PHYSICAL_ADDRESS Information;
+} EFI_BOOT_SCRIPT_INFORMATION;
+
+typedef struct {
+ UINT16 OpCode;
+ UINT8 Length;
+} EFI_BOOT_SCRIPT_TERMINATE;
+
+typedef union {
+ EFI_BOOT_SCRIPT_GENERIC_HEADER *Header;
+ EFI_BOOT_SCRIPT_TABLE_HEADER *TableInfo;
+ EFI_BOOT_SCRIPT_IO_WRITE *IoWrite;
+ EFI_BOOT_SCRIPT_IO_READ_WRITE *IoReadWrite;
+ EFI_BOOT_SCRIPT_MEM_WRITE *MemWrite;
+ EFI_BOOT_SCRIPT_MEM_READ_WRITE *MemReadWrite;
+ EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE *PciWrite;
+ EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE *PciReadWrite;
+ EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE *PciWrite2;
+ EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE *PciReadWrite2;
+ EFI_BOOT_SCRIPT_SMBUS_EXECUTE *SmbusExecute;
+ EFI_BOOT_SCRIPT_STALL *Stall;
+ EFI_BOOT_SCRIPT_DISPATCH *Dispatch;
+ EFI_BOOT_SCRIPT_MEM_POLL *MemPoll;
+ EFI_BOOT_SCRIPT_INFORMATION *Information;
+ EFI_BOOT_SCRIPT_TERMINATE *Terminate;
+ EFI_BOOT_SCRIPT_COMMON_HEADER *CommonHeader;
+ UINT8 *Raw;
+} BOOT_SCRIPT_POINTERS;
+
+#pragma pack()
+
+#endif
diff --git a/QuarkPlatformPkg/Library/LogoLib/Logo.c b/QuarkPlatformPkg/Library/LogoLib/Logo.c
new file mode 100644
index 0000000..fa5c4fc
--- /dev/null
+++ b/QuarkPlatformPkg/Library/LogoLib/Logo.c
@@ -0,0 +1,866 @@
+/** @file
+ BDS Lib functions which contain all the code to connect console device
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--*/
+
+#include <PiDxe.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/OEMBadging.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/UgaDraw.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+
+#include <IndustryStandard/Bmp.h>
+#include <Protocol/BootLogo.h>
+
+/**
+ Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
+ is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
+ buffer is passed in it will be used if it is big enough.
+
+ @param BmpImage Pointer to BMP file
+ @param BmpImageSize Number of bytes in BmpImage
+ @param GopBlt Buffer containing GOP version of BmpImage.
+ @param GopBltSize Size of GopBlt in bytes.
+ @param PixelHeight Height of GopBlt/BmpImage in pixels
+ @param PixelWidth Width of GopBlt/BmpImage in pixels
+
+ @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
+ @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
+ @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
+ GopBltSize will contain the required size.
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
+
+**/
+EFI_STATUS
+ConvertBmpToGopBlt (
+ IN VOID *BmpImage,
+ IN UINTN BmpImageSize,
+ IN OUT VOID **GopBlt,
+ IN OUT UINTN *GopBltSize,
+ OUT UINTN *PixelHeight,
+ OUT UINTN *PixelWidth
+ )
+{
+ UINT8 *Image;
+ UINT8 *ImageHeader;
+ BMP_IMAGE_HEADER *BmpHeader;
+ BMP_COLOR_MAP *BmpColorMap;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINT64 BltBufferSize;
+ UINTN Index;
+ UINTN Height;
+ UINTN Width;
+ UINTN ImageIndex;
+ UINT32 DataSizePerLine;
+ BOOLEAN IsAllocated;
+ UINT32 ColorMapNum;
+
+ if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
+
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Doesn't support compress.
+ //
+ if (BmpHeader->CompressionType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Only support BITMAPINFOHEADER format.
+ // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
+ //
+ if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // The data size in each line must be 4 byte alignment.
+ //
+ DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
+ BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
+ if (BltBufferSize > (UINT32) ~0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BmpHeader->Size != BmpImageSize) ||
+ (BmpHeader->Size < BmpHeader->ImageOffset) ||
+ (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Calculate Color Map offset in the image.
+ //
+ Image = BmpImage;
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
+ if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ ColorMapNum = 2;
+ break;
+ case 4:
+ ColorMapNum = 16;
+ break;
+ case 8:
+ ColorMapNum = 256;
+ break;
+ default:
+ ColorMapNum = 0;
+ break;
+ }
+ if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) != sizeof (BMP_COLOR_MAP) * ColorMapNum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Calculate graphics image data address in the image
+ //
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
+ ImageHeader = Image;
+
+ //
+ // Calculate the BltBuffer needed size.
+ //
+ BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
+ //
+ // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+ //
+ if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ return EFI_UNSUPPORTED;
+ }
+ BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ IsAllocated = FALSE;
+ if (*GopBlt == NULL) {
+ //
+ // GopBlt is not allocated by caller.
+ //
+ *GopBltSize = (UINTN) BltBufferSize;
+ *GopBlt = AllocatePool (*GopBltSize);
+ IsAllocated = TRUE;
+ if (*GopBlt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ //
+ // GopBlt has been allocated by caller.
+ //
+ if (*GopBltSize < (UINTN) BltBufferSize) {
+ *GopBltSize = (UINTN) BltBufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ *PixelWidth = BmpHeader->PixelWidth;
+ *PixelHeight = BmpHeader->PixelHeight;
+
+ //
+ // Convert image from BMP to Blt buffer format
+ //
+ BltBuffer = *GopBlt;
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ //
+ // Convert 1-bit (2 colors) BMP to 24-bit color
+ //
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+ Blt++;
+ Width++;
+ }
+
+ Blt--;
+ Width--;
+ break;
+
+ case 4:
+ //
+ // Convert 4-bit (16 colors) BMP Palette to 24-bit color
+ //
+ Index = (*Image) >> 4;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ if (Width < (BmpHeader->PixelWidth - 1)) {
+ Blt++;
+ Width++;
+ Index = (*Image) & 0x0f;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ }
+ break;
+
+ case 8:
+ //
+ // Convert 8-bit (256 colors) BMP Palette to 24-bit color
+ //
+ Blt->Red = BmpColorMap[*Image].Red;
+ Blt->Green = BmpColorMap[*Image].Green;
+ Blt->Blue = BmpColorMap[*Image].Blue;
+ break;
+
+ case 24:
+ //
+ // It is 24-bit BMP.
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image;
+ break;
+
+ default:
+ //
+ // Other bit format BMP is not supported.
+ //
+ if (IsAllocated) {
+ FreePool (*GopBlt);
+ *GopBlt = NULL;
+ }
+ return EFI_UNSUPPORTED;
+ break;
+ };
+
+ }
+
+ ImageIndex = (UINTN) (Image - ImageHeader);
+ if ((ImageIndex % 4) != 0) {
+ //
+ // Bmp Image starts each row on a 32-bit boundary!
+ //
+ Image = Image + (4 - (ImageIndex % 4));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Use SystemTable Conout to stop video based Simple Text Out consoles from going
+ to the video device. Put up LogoFile on every video device that is a console.
+
+ @param[in] LogoFile File name of logo to display on the center of the screen.
+
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
+ @retval EFI_UNSUPPORTED Logo not found
+
+**/
+EFI_STATUS
+EFIAPI
+EnableQuietBoot (
+ IN EFI_GUID *LogoFile
+ )
+{
+ EFI_STATUS Status;
+ EFI_OEM_BADGING_PROTOCOL *Badging;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ INTN DestX;
+ INTN DestY;
+ UINT8 *ImageData;
+ UINTN ImageSize;
+ UINTN BltSize;
+ UINT32 Instance;
+ EFI_BADGING_FORMAT Format;
+ EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
+ UINTN CoordinateX;
+ UINTN CoordinateY;
+ UINTN Height;
+ UINTN Width;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_BOOT_LOGO_PROTOCOL *BootLogo;
+ UINTN NumberOfLogos;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;
+ UINTN LogoDestX;
+ UINTN LogoDestY;
+ UINTN LogoHeight;
+ UINTN LogoWidth;
+ UINTN NewDestX;
+ UINTN NewDestY;
+ UINTN NewHeight;
+ UINTN NewWidth;
+ UINT64 BufferSize;
+
+
+ UgaDraw = NULL;
+ //
+ // Try to open GOP first
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
+ if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ GraphicsOutput = NULL;
+ //
+ // Open GOP failed, try to open UGA
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Try to open Boot Logo Protocol.
+ //
+ BootLogo = NULL;
+ gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
+
+ //
+ // Erase Cursor from screen
+ //
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ Badging = NULL;
+ Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
+
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+
+ } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ Blt = NULL;
+ NumberOfLogos = 0;
+ LogoDestX = 0;
+ LogoDestY = 0;
+ LogoHeight = 0;
+ LogoWidth = 0;
+ NewDestX = 0;
+ NewDestY = 0;
+ NewHeight = 0;
+ NewWidth = 0;
+ Instance = 0;
+ while (1) {
+ ImageData = NULL;
+ ImageSize = 0;
+
+ if (Badging != NULL) {
+ //
+ // Get image from OEMBadging protocol.
+ //
+ Status = Badging->GetImage (
+ Badging,
+ &Instance,
+ &Format,
+ &ImageData,
+ &ImageSize,
+ &Attribute,
+ &CoordinateX,
+ &CoordinateY
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ } else {
+ //
+ // Get the specified image from FV.
+ //
+ Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ CoordinateX = 0;
+ CoordinateY = 0;
+ Attribute = EfiBadgingDisplayAttributeCenter;
+ }
+
+ if (Blt != NULL) {
+ FreePool (Blt);
+ }
+
+ //
+ // Try BMP decoder
+ //
+ Blt = NULL;
+ Status = ConvertBmpToGopBlt (
+ ImageData,
+ ImageSize,
+ (VOID **) &Blt,
+ &BltSize,
+ &Height,
+ &Width
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (ImageData);
+
+ if (Badging == NULL) {
+ return Status;
+ } else {
+ continue;
+ }
+ }
+
+ //
+ // Calculate the display position according to Attribute.
+ //
+ switch (Attribute) {
+ case EfiBadgingDisplayAttributeLeftTop:
+ DestX = CoordinateX;
+ DestY = CoordinateY;
+ break;
+
+ case EfiBadgingDisplayAttributeCenterTop:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = CoordinateY;
+ break;
+
+ case EfiBadgingDisplayAttributeRightTop:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = CoordinateY;;
+ break;
+
+ case EfiBadgingDisplayAttributeCenterRight:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ case EfiBadgingDisplayAttributeRightBottom:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeCenterBottom:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeLeftBottom:
+ DestX = CoordinateX;
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeCenterLeft:
+ DestX = CoordinateX;
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ case EfiBadgingDisplayAttributeCenter:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ default:
+ DestX = CoordinateX;
+ DestY = CoordinateY;
+ break;
+ }
+
+ if ((DestX >= 0) && (DestY >= 0)) {
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ Blt,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) DestX,
+ (UINTN) DestY,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) Blt,
+ EfiUgaBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) DestX,
+ (UINTN) DestY,
+ Width,
+ Height,
+ Width * sizeof (EFI_UGA_PIXEL)
+ );
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ //
+ // Report displayed Logo information.
+ //
+ if (!EFI_ERROR (Status)) {
+ NumberOfLogos++;
+
+ if (LogoWidth == 0) {
+ //
+ // The first Logo.
+ //
+ LogoDestX = (UINTN) DestX;
+ LogoDestY = (UINTN) DestY;
+ LogoWidth = Width;
+ LogoHeight = Height;
+ } else {
+ //
+ // Merge new logo with old one.
+ //
+ NewDestX = MIN ((UINTN) DestX, LogoDestX);
+ NewDestY = MIN ((UINTN) DestY, LogoDestY);
+ NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;
+ NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;
+
+ LogoDestX = NewDestX;
+ LogoDestY = NewDestY;
+ LogoWidth = NewWidth;
+ LogoHeight = NewHeight;
+ }
+ }
+ }
+
+ FreePool (ImageData);
+
+ if (Badging == NULL) {
+ break;
+ }
+ }
+
+Done:
+ if (BootLogo == NULL || NumberOfLogos == 0) {
+ //
+ // No logo displayed.
+ //
+ if (Blt != NULL) {
+ FreePool (Blt);
+ }
+
+ return Status;
+ }
+
+ //
+ // Advertise displayed Logo information.
+ //
+ if (NumberOfLogos == 1) {
+ //
+ // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
+ //
+ LogoBlt = Blt;
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
+ //
+ if (Blt != NULL) {
+ FreePool (Blt);
+ }
+
+ //
+ // Ensure the LogoHeight * LogoWidth doesn't overflow
+ //
+ if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+ BufferSize = MultU64x64 (LogoWidth, LogoHeight);
+
+ //
+ // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+ //
+ if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (LogoBlt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ LogoBlt,
+ EfiBltVideoToBltBuffer,
+ LogoDestX,
+ LogoDestY,
+ 0,
+ 0,
+ LogoWidth,
+ LogoHeight,
+ LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) LogoBlt,
+ EfiUgaVideoToBltBuffer,
+ LogoDestX,
+ LogoDestY,
+ 0,
+ 0,
+ LogoWidth,
+ LogoHeight,
+ LogoWidth * sizeof (EFI_UGA_PIXEL)
+ );
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);
+ }
+ FreePool (LogoBlt);
+
+ return Status;
+}
+
+/**
+ Use SystemTable Conout to turn on video based Simple Text Out consoles. The
+ Simple Text Out screens will now be synced up with all non video output devices
+
+ @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableQuietBoot (
+ VOID
+ )
+{
+
+ //
+ // Enable Cursor on Screen
+ //
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Show progress bar with title above it. It only works in Graphics mode.
+
+
+ @param TitleForeground Foreground color for Title.
+ @param TitleBackground Background color for Title.
+ @param Title Title above progress bar.
+ @param ProgressColor Progress bar color.
+ @param Progress Progress (0-100)
+ @param PreviousValue The previous value of the progress.
+
+ @retval EFI_STATUS Success update the progress bar
+
+**/
+EFI_STATUS
+EFIAPI
+ShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINTN BlockHeight;
+ UINTN BlockWidth;
+ UINTN BlockNum;
+ UINTN PosX;
+ UINTN PosY;
+ UINTN Index;
+
+ if (Progress > 100) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UgaDraw = NULL;
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput
+ );
+ if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ GraphicsOutput = NULL;
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiUgaDrawProtocolGuid,
+ (VOID **) &UgaDraw
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SizeOfX = 0;
+ SizeOfY = 0;
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ } else if (UgaDraw != NULL) {
+ Status = UgaDraw->GetMode (
+ UgaDraw,
+ &SizeOfX,
+ &SizeOfY,
+ &ColorDepth,
+ &RefreshRate
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ BlockWidth = SizeOfX / 100;
+ BlockHeight = SizeOfY / 50;
+
+ BlockNum = Progress;
+
+ PosX = 0;
+ PosY = SizeOfY * 48 / 50;
+
+ if (BlockNum == 0) {
+ //
+ // Clear progress area
+ //
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &Color,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &Color,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_UGA_PIXEL)
+ );
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ //
+ // Show progress by drawing blocks
+ //
+ for (Index = PreviousValue; Index < BlockNum; Index++) {
+ PosX = Index * BlockWidth;
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &ProgressColor,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &ProgressColor,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)
+ );
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ PrintXY (
+ (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ &TitleForeground,
+ &TitleBackground,
+ Title
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Library/LogoLib/LogoLib.inf b/QuarkPlatformPkg/Library/LogoLib/LogoLib.inf
new file mode 100644
index 0000000..2b31e61
--- /dev/null
+++ b/QuarkPlatformPkg/Library/LogoLib/LogoLib.inf
@@ -0,0 +1,86 @@
+## @file
+#
+# General BDS defines and produce general interfaces for platform BDS driver including:
+# 1) BDS boot policy interface;
+# 2) BDS boot device connect interface;
+# 3) BDS Misc interfaces for mainting boot variable, ouput string, etc.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = LogoLib
+ FILE_GUID = F5AE5B5C-42E8-4A9B-829D-5B631CD5367A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LogoLib|DXE_DRIVER UEFI_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ Logo.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ PcdLib
+ DxeServicesLib
+
+[Guids]
+
+[Protocols]
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL SOMETIMES_CONSUMES
+ gEfiUgaDrawProtocolGuid |PcdUgaConsumeSupport # PROTOCOL SOMETIMES_CONSUMES
+ gEfiBootLogoProtocolGuid # PROTOCOL SOMETIMES_CONSUMES
+ gEfiUserManagerProtocolGuid # PROTOCOL CONSUMES
+
+####IntelFrameworkModulePkg
+ gEfiOEMBadgingProtocolGuid # PROTOCOL CONSUMES
+
+
+[FeaturePcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport
+
+[Pcd]
diff --git a/QuarkPlatformPkg/Library/MfhLib/MfhLib.c b/QuarkPlatformPkg/Library/MfhLib/MfhLib.c
new file mode 100644
index 0000000..b9ab18a
--- /dev/null
+++ b/QuarkPlatformPkg/Library/MfhLib/MfhLib.c
@@ -0,0 +1,491 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ MfhLib.c
+
+Abstract:
+
+ Library producing routines for Master Flash Header (MFH) functionality.
+
+--*/
+
+#include <Base.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+
+#include <Mfh.h>
+#include <Library/MfhLib.h>
+
+//
+// Routines local to this source module.
+//
+
+STATIC
+MFH_FLASH_ITEM *
+FindNext (
+ IN CONST UINT64 ItemTypeFilter,
+ IN CONST BOOLEAN IncrementBeforeMatchCheck,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ )
+{
+ UINT32 *IdxPtr;
+ UINT32 FlashItemCount;
+ UINT32 BootPriorityListCount;
+ MFH_FLASH_ITEM *FlashItem;
+
+ if (IncrementBeforeMatchCheck) {
+ if (FindContext->OnlyBootFlashItems) {
+ FindContext->CurrBootPriorityListIndex++;
+ } else {
+ FindContext->CurrFlashItemIndex++;
+ }
+ }
+
+ IdxPtr = &FindContext->CurrFlashItemIndex;
+ FlashItemCount = FindContext->MfhHeader->FlashItemCount;
+ BootPriorityListCount = FindContext->MfhHeader->BootPriorityListCount;
+
+ do {
+ if (FindContext->OnlyBootFlashItems) {
+
+ //
+ // Search for items referenced by BootPriorityList
+ //
+ if (FindContext->CurrBootPriorityListIndex >= BootPriorityListCount) {
+ return NULL; // End of list no more boot items.
+ }
+
+ *IdxPtr = FindContext->BootPriorityList[FindContext->CurrBootPriorityListIndex];
+ FlashItem = &FindContext->FlashItemList[*IdxPtr];
+ if (*IdxPtr >= FlashItemCount || FlashItem->Type > 63) {
+ //
+ // Index must < FlashItemCount
+ // and since filter is UINT64 the max type is 63 for BIT63.
+ //
+ ASSERT (FALSE);
+ } else {
+ if (MFH_IS_FILTER_MATCH (ItemTypeFilter, FlashItem->Type)) {
+ break;
+ }
+ }
+ FindContext->CurrBootPriorityListIndex++;
+ continue;
+ }
+
+ //
+ // Search through all flash items.
+ //
+ if (*IdxPtr >= FlashItemCount) {
+ return NULL; // End of list no more items.
+ }
+
+ FlashItem = &FindContext->FlashItemList[*IdxPtr];
+ if (FlashItem->Type > 63) {
+ //
+ // Since Filter is UINT64 the max type is 63 for BIT63.
+ //
+ ASSERT (FALSE);
+ } else {
+ if (MFH_IS_FILTER_MATCH (ItemTypeFilter, FlashItem->Type)) {
+ break;
+ }
+ }
+ (*IdxPtr)++;
+ } while (TRUE);
+ return FlashItem;
+}
+
+//
+// Routines exported by this source module.
+//
+
+/** Find First flash Item using item type filter.
+
+ The bit position for a particular type is (1 << MFH_FLASH_ITEM_TYPE_XXX)
+
+ @param[in] ItemTypeFilter Filter of item types to search for.
+ @param[in] OnlyBootFlashItems Only find flash items referenced in boot
+ priority list.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if MFH not found, corrupt or no items match filter.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindFirstWithFilter (
+ IN CONST UINT64 ItemTypeFilter,
+ IN CONST BOOLEAN OnlyBootFlashItems,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ )
+{
+ BOOLEAN IsValidMfh;
+
+ IsValidMfh = MfhLibValidateMfhBaseAddress (
+ PcdGet32 (PcdFlashNvMfh),
+ &FindContext->MfhHeader,
+ &FindContext->BootPriorityList,
+ &FindContext->FlashItemList
+ );
+
+ if (!IsValidMfh) {
+ return NULL;
+ }
+
+ FindContext->CurrFlashItemIndex = 0;
+ FindContext->CurrBootPriorityListIndex = 0;
+ FindContext->OnlyBootFlashItems = OnlyBootFlashItems;
+ return FindNext (ItemTypeFilter, FALSE, FindContext);
+}
+
+/** Find next flash Item using item type filter.
+
+ @param[in] ItemTypeFilter Filter of item types to search for.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if no more items found for specified type.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindNextWithFilter (
+ IN CONST UINT64 ItemTypeFilter,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ )
+{
+ return FindNext (ItemTypeFilter, TRUE, FindContext);
+}
+
+/** Find First flash Item of a specific type.
+
+ @param[in] FlashItemType One of MFH_FLASH_ITEM defs in Mfh.h.
+ @param[in] OnlyBootFlashItems Only find flash items referenced in boot
+ priority list.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if MFH not found, corrupt or no items found for specified type.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindFirstOfType (
+ IN CONST UINT32 FlashItemType,
+ IN CONST BOOLEAN OnlyBootFlashItems,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ )
+{
+ return MfhLibFindFirstWithFilter (
+ MFH_FIT_BM (FlashItemType),
+ OnlyBootFlashItems,
+ FindContext
+ );
+}
+
+/** Find next flash Item of a specific type.
+
+ @param[in] FlashItemType One of MFH_FLASH_ITEM defs in Mfh.h.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if no more items found for specified type.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindNextOfType (
+ IN CONST UINT32 FlashItemType,
+ IN OUT MFH_LIB_FINDCONTEXT *FindContext
+ )
+{
+ return MfhLibFindNextWithFilter (
+ MFH_FIT_BM (FlashItemType),
+ FindContext
+ );
+}
+
+/** Validate if MFH at specified base address is valid.
+
+ Optional return of pointers to resources within MFH.
+
+ @param[in] MfhBaseAddress Check memory at this location
+ points to a valid MFH.
+ @param[out] MfhHeaderPtr Optional return header part of MFH.
+ @param[out] BootPriorityListPtr Optional return of boot priority list.
+ points to a valid MFH.
+ @param[out] FlashItemListPtr Optional return of flash item list.
+
+ @retval TRUE if MfhBaseAddress points to a valid MFH.
+ @retval FALSE if MfhBaseAddress points to an invalid MFH.
+**/
+BOOLEAN
+EFIAPI
+MfhLibValidateMfhBaseAddress (
+ IN CONST UINT32 MfhBaseAddress,
+ OUT MFH_HEADER **MfhHeaderPtr OPTIONAL,
+ OUT UINT32 **BootPriorityListPtr OPTIONAL,
+ OUT MFH_FLASH_ITEM **FlashItemListPtr OPTIONAL
+ )
+{
+ UINT8 *MemPtr;
+ UINT32 BootPriorityListCount;
+ MFH_HEADER *MfhHeader;
+
+ MfhHeader = (MFH_HEADER *) MfhBaseAddress;
+
+ //
+ // Do some basic sanity checks.
+ //
+ if (MfhHeader->QuarkMFHIdentifier != MFH_IDENTIFIER) {
+ return FALSE;
+ }
+ if (MfhHeader->BootPriorityListCount > MFH_MAX_NUM_BOOT_ITEMS) {
+ return FALSE;
+ }
+ if (MfhHeader->FlashItemCount > MFH_MAX_NUM_FLASH_ITEMS) {
+ return FALSE;
+ }
+
+ MemPtr = (UINT8 *) MfhHeader;
+
+ if (MfhHeaderPtr != NULL) {
+ *MfhHeaderPtr = (MFH_HEADER *) MemPtr;
+ }
+ MemPtr += sizeof (MFH_HEADER);
+
+ if (BootPriorityListPtr != NULL) {
+ *BootPriorityListPtr = (UINT32 *) MemPtr;
+ }
+
+ if (FlashItemListPtr != NULL) {
+ BootPriorityListCount = MfhHeader->BootPriorityListCount;
+ MemPtr += (sizeof (UINT32) * BootPriorityListCount);
+ *FlashItemListPtr = (MFH_FLASH_ITEM *) MemPtr;
+ }
+
+ return TRUE;
+}
+
+/** Find First stage1 flash module info or fixed recovery module info.
+
+ @param[out] FlashItemBuffer Caller storage to receive flash item
+ fields.
+ @param[out] GotFixedRecovery TRUE if buffer filled with fixed
+ recovery module info.
+
+ @retval TRUE if found flash module.
+ @retval FALSE if no flash module found.
+**/
+BOOLEAN
+EFIAPI
+MfhLibFindFirstStage1OrFixedRecovery (
+ OUT MFH_FLASH_ITEM *FlashItemBuffer,
+ OUT BOOLEAN *GotFixedRecovery OPTIONAL
+ )
+{
+ MFH_LIB_FINDCONTEXT FindContext;
+ MFH_FLASH_ITEM *Item;
+
+ Item = MfhLibFindFirstWithFilter (
+ MFH_FIND_ALL_STAGE1_FILTER,
+ TRUE,
+ &FindContext
+ );
+ if (Item == NULL) {
+ if (GotFixedRecovery != NULL) {
+ *GotFixedRecovery = TRUE;
+ }
+ FlashItemBuffer->Type = MFH_FLASH_ITEM_TYPE_FW_RECOVERY;
+ FlashItemBuffer->FlashAddress = PcdGet32 (PcdFlashFvFixedStage1AreaBase);
+ FlashItemBuffer->LengthBytes = PcdGet32 (PcdFlashFvFixedStage1AreaSize);
+ FlashItemBuffer->TypeSpecific.Reserved = 0;
+ } else {
+ if (GotFixedRecovery != NULL) {
+ *GotFixedRecovery = FALSE;
+ }
+ FlashItemBuffer->Type = Item->Type;
+ FlashItemBuffer->FlashAddress = Item->FlashAddress;
+ FlashItemBuffer->LengthBytes = Item->LengthBytes;
+ FlashItemBuffer->TypeSpecific.Reserved = Item->TypeSpecific.Reserved;
+ }
+
+ return TRUE;
+}
+
+/** Return string for printing flash item type.
+
+ @param[in] FlashItemType One of MFH_FLASH_ITEM defs in Mfh.h.
+
+ @return string for printing flash item type.
+**/
+CHAR16 *
+EFIAPI
+MfhLibFlashItemTypePrintString (
+ IN CONST UINT32 FlashItemType
+ )
+{
+ CHAR16 *Str;
+
+ if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_STAGE1) {
+ Str = L"Firmware stage1";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_STAGE1_SIGNED) {
+ Str = L"Firmware stage1 signed";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_RSVD_02H) {
+ Str = L"Reserved 02Hex";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_STAGE2) {
+ Str = L"Firmware stage2";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_STAGE2_SIGNED) {
+ Str = L"Firmware stage2 signed";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_STAGE2_CFG) {
+ Str = L"Firmware stage2 config";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_STAGE2_CFG_SIGNED) {
+ Str = L"Firmware stage2 config signed";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_PARAMETERS) {
+ Str = L"Firmware parameters";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_RECOVERY) {
+ Str = L"Firmware recoverey";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_FW_RECOVERY_SIGNED) {
+ Str = L"Firmware recoverey signed";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_RSVD_0AH) {
+ Str = L"Reserved 0AHex item";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_BOOTLOADER) {
+ Str = L"Bootloader";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_BOOTLOADER_SIGNED) {
+ Str = L"Bootloader signed";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_BOOTLOADER_CFG) {
+ Str = L"Bootloader config";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_BOOTLOADER_CFG_SIGNED) {
+ Str = L"Bootloader config signed";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_RSVD_0F) {
+ Str = L"Boot defender internal error";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_KERNEL) {
+ Str = L"Kernel";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_KERNEL_SIGNED) {
+ Str = L"Kernel signed";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_RAMDISK) {
+ Str = L"Boot defender internal error";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_RAMDISK_SIGNED) {
+ Str = L"RAMDISK";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_RSVD_14H) {
+ Str = L"Reserved 14Hex item";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_PROGRAM) {
+ Str = L"Program";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_PROGRAM_SIGNED) {
+ Str = L"Program signed";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_RSVD_17H) {
+ Str = L"Reserved 17Hex item";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_BUILD_INFORMATION) {
+ Str = L"Build information";
+ } else if (FlashItemType == MFH_FLASH_ITEM_TYPE_IMAGE_VERSION) {
+ Str = L"Firmware image version";
+ } else {
+ Str = L"Flash Item Unknown";
+ }
+ return Str;
+}
+
+/** Check if Address within firmware flash item.
+
+ @param[in] CheckAddress Address to check.
+
+ @retval TRUE if check address with FW flash item.
+ @retval FALSE if check address outside FW flash item.
+**/
+BOOLEAN
+EFIAPI
+MfhLibIsAddressWithinFwFlashItem (
+ IN CONST UINT32 CheckAddress
+ )
+{
+ MFH_LIB_FINDCONTEXT FindContext;
+ MFH_FLASH_ITEM *FlashItem;
+ UINT32 LastItemAddress;
+ UINT64 Filter;
+
+ Filter = MFH_FIND_ANY_FW_FIT_FILTER;
+
+ FlashItem = MfhLibFindFirstWithFilter (
+ Filter,
+ FALSE,
+ &FindContext
+ );
+ while (FlashItem != NULL) {
+ if (CheckAddress > FlashItem->FlashAddress) {
+ LastItemAddress = FlashItem->FlashAddress + (FlashItem->LengthBytes -1);
+ if (CheckAddress <= LastItemAddress) {
+ return TRUE;
+ }
+ }
+
+ FlashItem = MfhLibFindNextWithFilter (
+ Filter,
+ &FindContext
+ );
+ }
+ return FALSE;
+}
+
+/** Find flash Item for boot priority index.
+
+ @param[in] BootPriorityIndex Boot priority index of flash item
+ we are looking for.
+
+ @return pointer to MFH_FLASH_ITEM struct for found item.
+ @retval NULL if MFH not found, corrupt or BootPriorityIndex >= ListCount.
+**/
+MFH_FLASH_ITEM *
+EFIAPI
+MfhLibFindFlashItemForBootPriorityIndex (
+ IN CONST UINT32 BootPriorityIndex
+ )
+{
+ BOOLEAN IsValidMfh;
+ MFH_LIB_FINDCONTEXT FindContext;
+ UINT32 ItemIndex;
+
+ IsValidMfh = MfhLibValidateMfhBaseAddress (
+ PcdGet32 (PcdFlashNvMfh),
+ &FindContext.MfhHeader,
+ &FindContext.BootPriorityList,
+ &FindContext.FlashItemList
+ );
+
+ if ((IsValidMfh) && (BootPriorityIndex < FindContext.MfhHeader->BootPriorityListCount)) {
+ ItemIndex = FindContext.BootPriorityList[BootPriorityIndex];
+ return &FindContext.FlashItemList[ItemIndex];
+ }
+ return NULL;
+}
+
diff --git a/QuarkPlatformPkg/Library/MfhLib/MfhLib.inf b/QuarkPlatformPkg/Library/MfhLib/MfhLib.inf
new file mode 100644
index 0000000..ba0156b
--- /dev/null
+++ b/QuarkPlatformPkg/Library/MfhLib/MfhLib.inf
@@ -0,0 +1,74 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# Mfhib.inf
+#
+# Abstract:
+#
+# Library producing routines for Master Flash Header (MFH) functionality.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MfhLib
+ FILE_GUID = DBA56126-FE4F-439e-B87C-A20EB7600C1E
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MfhLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ MfhLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+
+[FeaturePcd]
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvMfh
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/QuarkPlatformPkg/Library/PlatformBootManagerLib/BdsPlatform.c
new file mode 100755
index 0000000..2e6d6e4
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -0,0 +1,1383 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ BdsPlatform.c
+
+Abstract:
+
+ This file include all platform action which can be customized
+ by IBV/OEM.
+
+--*/
+
+#include "BdsPlatform.h"
+
+extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath;
+EFI_USER_PROFILE_HANDLE mCurrentUser = NULL;
+UINT16 mPayloadBootOptionNumber = 0xffff;
+SECUREBOOT_HELPER_PROTOCOL *gSecureBootHelperProtocol = NULL;
+
+/**
+ Identify a user and, if authenticated, returns the current user profile handle.
+
+ @param[out] User Point to user profile handle.
+
+ @retval EFI_SUCCESS User is successfully identified, or user identification
+ is not supported.
+ @retval EFI_ACCESS_DENIED User is not successfully identified
+
+**/
+EFI_STATUS
+UserIdentify (
+ OUT EFI_USER_PROFILE_HANDLE *User
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_MANAGER_PROTOCOL *Manager;
+
+ Status = gBS->LocateProtocol (
+ &gEfiUserManagerProtocolGuid,
+ NULL,
+ (VOID **) &Manager
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ return Manager->Identify (Manager, User);
+}
+
+/**
+ Search out the video controller.
+
+ @return PCI device path of the video controller.
+**/
+EFI_HANDLE
+PlatformGetVideoController (
+ EFI_HANDLE *OnboardVideoController,
+ EFI_HANDLE *AddinVideoController
+ )
+{
+ EFI_STATUS Status;
+ UINTN RootBridgeHandleCount;
+ EFI_HANDLE *RootBridgeHandleBuffer;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN RootBridgeIndex;
+ UINTN Index;
+ EFI_HANDLE VideoController = NULL;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ EFI_PCI_PLATFORM_PROTOCOL *PciPlatformProtocol;
+
+ //
+ // Make all the PCI_IO protocols show up
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &RootBridgeHandleCount,
+ &RootBridgeHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (RootBridgeHandleCount == 0)) {
+ return NULL;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiPciPlatformProtocolGuid,
+ NULL,
+ (VOID **) &PciPlatformProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
+ gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);
+
+ //
+ // Start to check all the pci io to find the first video controller
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Check for all video controller
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (!EFI_ERROR (Status) && IS_PCI_VGA (&Pci)) {
+ // Set VideoController to default to first video controller.
+ // This will be the device used if Video Select is set to Auto.
+ if(VideoController == NULL) {
+ VideoController = HandleBuffer[Index];
+ *AddinVideoController = HandleBuffer[Index];
+ }
+ }
+ }
+ }
+ FreePool (HandleBuffer);
+
+ if (VideoController != NULL) {
+ break;
+ }
+ }
+ FreePool (RootBridgeHandleBuffer);
+
+ return VideoController;
+}
+
+
+VOID
+UpdateConOut (
+ VOID
+ )
+{
+ EFI_HANDLE VideoController;
+ EFI_DEVICE_PATH_PROTOCOL *Gop;
+ EFI_HANDLE OnboardVideoController = NULL;
+ EFI_HANDLE AddinVideoController = NULL;
+ UINTN VideoSelect;
+
+ //
+ // Get the platform vga device
+ //
+ VideoController = PlatformGetVideoController (&OnboardVideoController, &AddinVideoController);
+
+ if (VideoController == NULL) {
+ return ;
+ }
+
+
+ // Force to Auto
+ VideoSelect = 0;
+
+ // If device selected by SystemConfig is not present, force to Auto
+ if (VideoSelect == 1 && OnboardVideoController == NULL) {
+ VideoSelect = 0;
+ }
+ if (VideoSelect == 2 && AddinVideoController == NULL) {
+ VideoSelect = 0;
+ }
+
+ switch(VideoSelect) {
+ case 1:
+ // Onboard selected
+ VideoController = OnboardVideoController;
+ DEBUG((EFI_D_INFO, "Video select: Onboard\n"));
+ break;
+ case 2:
+ // Add-in selected
+ VideoController = AddinVideoController;
+ DEBUG((EFI_D_INFO, "Video select: Add-in\n"));
+ break;
+ case 0:
+ default:
+ // Use first VideoController found, which is what GetVideoController returns as VideoController
+ DEBUG((EFI_D_INFO, "Video select: Auto\n"));
+ break;
+ }
+
+ //
+ // Try to connect the PCI device path, so that GOP dirver could start on this
+ // device and create child handles with GraphicsOutput Protocol installed
+ // on them, then we get device paths of these child handles and select
+ // them as possible console device.
+ //
+ gBS->ConnectController (VideoController, NULL, NULL, FALSE);
+
+ Gop = EfiBootManagerGetGopDevicePath (VideoController);
+ if (Gop == NULL) {
+ return ;
+ }
+
+ //
+ // Update ConOut variable to remove device path of on-board/add-in video controller
+ // and add the device path of the specified video controller
+ //
+ EfiBootManagerUpdateConsoleVariable (ConOut, NULL, DevicePathFromHandle (OnboardVideoController));
+ EfiBootManagerUpdateConsoleVariable (ConOut, Gop, DevicePathFromHandle (AddinVideoController));
+ FreePool (Gop);
+
+}
+
+
+/**
+ Initialize the platform default console variables when the console variable is empty.
+
+ @param PlatformConsole Predfined platform default console device array.
+**/
+VOID
+InitializeConsoleVariables (
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ )
+{
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *VarConOut;
+ EFI_DEVICE_PATH_PROTOCOL *VarConIn;
+ EFI_BOOT_MODE BootMode;
+
+ BootMode = GetBootModeHob ();
+
+ VarConOut = GetEfiGlobalVariable (L"ConOut"); if (VarConOut != NULL) { FreePool (VarConOut); }
+ VarConIn = GetEfiGlobalVariable (L"ConIn"); if (VarConIn != NULL) { FreePool (VarConIn); }
+ if (VarConOut == NULL || VarConIn == NULL) {
+ //
+ // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may drop to Full Configuration boot mode in non-first boot
+ //
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; Index++) {
+ //
+ // Update the console variable with the connect type
+ //
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+ EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ }
+ }
+}
+
+//
+// BDS Platform Functions
+//
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
+ BOOLEAN SecureBootSupportEnabled;
+ BOOLEAN SecureBootEnabled;
+
+ SecureBootSupportEnabled = FALSE;
+ SecureBootEnabled = FALSE;
+
+ if (FeaturePcdGet (PcdSupportSecureBoot)) {
+
+ //
+ // Auto provision UEFI Secure boot.
+ //
+ SecureBootSupportEnabled = TRUE;
+ SecureBootEnabled = PlatformAutoProvisionSecureBoot ();
+
+ //
+ // UEFI Secure boot not supported / validated for this firmware release.
+ //
+ ASSERT (FALSE);
+
+ }
+
+ if (FeaturePcdGet (PcdEnableSecureLock)) {
+ if (!SecureBootEnabled) {
+ PcdSetBool (PcdConInConnectOnDemand, TRUE);
+ }
+
+ DEBUG (
+ (EFI_D_INFO, "Secure Lock ENABLED Secure Boot Support %s Secure Boot %s\n",
+ SecureBootSupportEnabled ? L"ENABLED" : L"DISABLED",
+ SecureBootEnabled ? L"ENABLED" : L"DISABLED"
+ ));
+ } else {
+ DEBUG (
+ (EFI_D_INFO, "Secure Lock DISABLED Secure Boot Support %s Secure Boot %s\n",
+ SecureBootSupportEnabled ? L"ENABLED" : L"DISABLED",
+ SecureBootEnabled ? L"ENABLED" : L"DISABLED"
+ ));
+ }
+
+ //
+ // Add platform string package
+ //
+ InitializeStringSupport ();
+
+ InitializeConsoleVariables (gPlatformConsole);
+ UpdateConOut ();
+
+ RegisterLoadOptions ();
+
+
+ Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **)&AcpiS3Save);
+ if (!EFI_ERROR (Status)) {
+ AcpiS3Save->S3Save (AcpiS3Save, NULL);
+ }
+
+ //
+ // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gExitPmAuthProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Append Usb Keyboard short form DevicePath into "ConInDev"
+ //
+ EfiBootManagerUpdateConsoleVariable (
+ ConInDev,
+ (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath,
+ NULL
+ );
+
+ //
+ // Before user authentication, the user identification devices need be connected
+ // from the platform customized device paths
+ //
+ ConnectAuthDevice ();
+
+ //
+ // As console is not ready, the auto logon user will be identified.
+ //
+ UserIdentify (&mCurrentUser);
+}
+
+VOID
+ConnectSequence (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Connect with predeined platform connect sequence,
+ the OEM/IBV can customize with their own connect sequence.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ None.
+
+--*/
+{
+ UINTN Index;
+
+ //
+ // Here we can get the customized platform connect sequence
+ // Notes: we can connect with new variable which record the
+ // last time boots connect device path sequence
+ //
+ for (Index = 0; gPlatformConnectSequence[Index] != NULL; Index++) {
+ //
+ // Build the platform boot option
+ //
+ EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
+ }
+ //
+ // For the debug tip, just use the simple policy to connect all devices
+ //
+ EfiBootManagerConnectAll ();
+
+}
+
+
+EFI_DEVICE_PATH *
+FvFilePath (
+ UINTN FvBaseAddress,
+ UINTN FvSize,
+ EFI_GUID *FileGuid
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+ EFI_HANDLE FvProtocolHandle;
+ EFI_HANDLE *FvHandleBuffer;
+ UINTN FvHandleCount;
+ EFI_FV_FILETYPE Type;
+ UINTN Size;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINT32 AuthenticationStatus;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ UINTN Index;
+
+ EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+
+ if (FvBaseAddress == 0) {
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+ return AppendDevicePathNode (
+ DevicePathFromHandle (LoadedImage->DeviceHandle),
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ }
+ else {
+ //
+ // Expose Payload file in FV
+ //
+ gDS->ProcessFirmwareVolume (
+ (VOID *)FvBaseAddress,
+ (UINT32)FvSize,
+ &FvProtocolHandle
+ );
+
+ //
+ // Find out the handle of FV containing the playload file
+ //
+ FvHandleBuffer = NULL;
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &FvHandleCount,
+ &FvHandleBuffer
+ );
+ for (Index = 0; Index < FvHandleCount; Index++) {
+ gBS->HandleProtocol (
+ FvHandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &Fv
+ );
+ Status = Fv->ReadFile (
+ Fv,
+ FileGuid,
+ NULL,
+ &Size,
+ &Type,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ if (Index < FvHandleCount) {
+ return AppendDevicePathNode (
+ DevicePathFromHandle (FvHandleBuffer[Index]),
+ ( EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ }
+ }
+ return NULL;
+}
+
+EFI_GUID mBootMenuFile = {
+ 0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D }
+};
+
+EFI_STATUS
+RegisterFvBootOption (
+ IN UINTN FvBaseAddress,
+ IN UINTN FvSize,
+ IN EFI_GUID *FileGuid,
+ IN CHAR16 *Description,
+ IN UINTN Position,
+ IN BOOLEAN IsBootCategory,
+ OUT UINT16 *OptionNumberPtr OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN OptionIndex;
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ if (OptionNumberPtr != NULL) {
+ *OptionNumberPtr = (UINT16) -1;
+ }
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+ DevicePath = FvFilePath (FvBaseAddress, FvSize, FileGuid);
+ if (DevicePath != NULL) {
+ Status = EfiBootManagerInitializeLoadOption (
+ &NewOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ IsBootCategory ? LOAD_OPTION_ACTIVE : LOAD_OPTION_CATEGORY_APP,
+ Description,
+ DevicePath,
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (DevicePath);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OptionIndex = EfiBootManagerFindLoadOption (&NewOption, BootOptions, BootOptionCount);
+
+ if (OptionIndex == -1) {
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, Position);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ NewOption.OptionNumber = BootOptions[OptionIndex].OptionNumber;
+ Status = EFI_SUCCESS;
+ }
+ EfiBootManagerFreeLoadOption (&NewOption);
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+ if (OptionNumberPtr != NULL) {
+ *OptionNumberPtr = (UINT16) NewOption.OptionNumber;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RegisterPayloadBootOption (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ExpectedBaseAddress;
+ UINT32 TryBaseAddress;
+ BOOLEAN SecureBootEnabled;
+
+ SecureBootEnabled = FALSE;
+
+ ExpectedBaseAddress = (UINTN) PcdGet32(PcdFlashFvPayloadBase);
+ Status = RegisterFvBootOption (
+ (UINTN) ExpectedBaseAddress,
+ (UINTN) PcdGet32(PcdFlashFvPayloadSize),
+ PcdGetPtr (PcdPayloadFile),
+ L"UEFI Payload",
+ (UINTN) 1,
+ TRUE,
+ &mPayloadBootOptionNumber
+ );
+ if (!EFI_ERROR(Status)) {
+ return Status;
+ }
+ DEBUG ((EFI_D_ERROR, "Payload Not found\n"));
+ if (FeaturePcdGet (PcdEnableSecureLock)) {
+ if (gSecureBootHelperProtocol != NULL) {
+ SecureBootEnabled = gSecureBootHelperProtocol->IsSecureBootEnabled (
+ gSecureBootHelperProtocol
+ );
+ }
+ //
+ // In secure lockdown builds payload must be found if UEFI SecureBoot disabled.
+ //
+ ASSERT (SecureBootEnabled);
+ }
+
+ //
+ // Try 4G - 4M.
+ //
+ TryBaseAddress = 0xFFFFFFFF - (4 *1024 * 1024) + 1;
+ TryBaseAddress += PcdGet32 (PcdFvSecurityHeaderSize);
+ DEBUG ((EFI_D_WARN, "[PlatformBds] Try if payload at 4G-4M base = 0x%08x\n", (UINTN) TryBaseAddress));
+ if (TryBaseAddress != ExpectedBaseAddress) {
+ Status = RegisterFvBootOption (
+ (UINTN) TryBaseAddress,
+ (UINTN) PcdGet32(PcdFlashFvPayloadSize),
+ PcdGetPtr (PcdPayloadFile),
+ L"UEFI Payload",
+ (UINTN) 1,
+ TRUE,
+ &mPayloadBootOptionNumber
+ );
+ if (!EFI_ERROR(Status)) {
+ // Use EFI_D_ERROR so user on release builds knows payload found.
+ DEBUG ((EFI_D_ERROR, "[PlatformBds] Payload found in 4M flash default address\n"));
+ return Status;
+ }
+ }
+ //
+ // Try 4G - 8M.
+ //
+ TryBaseAddress = 0xFFFFFFFF - (8 *1024 * 1024) + 1;
+ TryBaseAddress += PcdGet32 (PcdFvSecurityHeaderSize);
+ DEBUG ((EFI_D_WARN, "[PlatformBds] Try if payload at 4G-8M base = 0x%08x\n", (UINTN) TryBaseAddress));
+ if (TryBaseAddress != ExpectedBaseAddress) {
+ Status = RegisterFvBootOption (
+ (UINTN) TryBaseAddress,
+ (UINTN) PcdGet32(PcdFlashFvPayloadSize),
+ PcdGetPtr (PcdPayloadFile),
+ L"UEFI Payload",
+ (UINTN) 1,
+ TRUE,
+ &mPayloadBootOptionNumber
+ );
+ if (!EFI_ERROR(Status)) {
+ // Use EFI_D_ERROR so user on release builds knows payload found.
+ DEBUG ((EFI_D_ERROR, "[PlatformBds] Payload found in 8M flash default address\n"));
+ return Status;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+VOID
+RegisterLoadOptions (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Load the predefined driver option, OEM/IBV can customize this
+ to load their own drivers.
+
+Arguments:
+
+ BdsDriverLists - The header of the driver option link list.
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_BOOT_MANAGER_LOAD_OPTION DriverOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *DriverOptions;
+ UINTN DriverOptionCount;
+ UINT16 OptionNumber;
+ EFI_INPUT_KEY F7;
+ EFI_INPUT_KEY Enter;
+ EFI_BOOT_MODE BootMode;
+
+ BootMode = GetBootModeHob ();
+
+ //
+ // 0. Continue key
+ //
+ Enter.ScanCode = SCAN_NULL;
+ Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+ EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+
+ //
+ // 1. Add Payload if not flash update and not recovery.
+ //
+ if (BootMode != BOOT_ON_FLASH_UPDATE && BootMode != BOOT_IN_RECOVERY_MODE) {
+ RegisterPayloadBootOption ();
+ }
+
+ //
+ // 2. Internal Shell if Secure Lock Disabled.
+ //
+ if(!FeaturePcdGet (PcdEnableSecureLock)) {
+ //
+ // Internal shell not allowed in Secure Lock down builds.
+ //
+ RegisterFvBootOption (0, 0, PcdGetPtr (PcdShellFile), L"UEFI Internal Shell", (UINTN) -1, TRUE, NULL);
+ }
+
+ //
+ // 3. Boot Device List menu
+ //
+ F7.UnicodeChar = CHAR_NULL;
+ F7.ScanCode = SCAN_F7;
+ Status = RegisterFvBootOption (0, 0, &mBootMenuFile, L"Boot Device List", (UINTN) -1, FALSE, &OptionNumber);
+ ASSERT_EFI_ERROR (Status);
+ Status = EfiBootManagerAddKeyOptionVariable (NULL, OptionNumber, 0, &F7, NULL);
+ DEBUG ((EFI_D_WARN, "[PlatformBds] Add Key Boot Device List Status = %r, Option %d\n", (UINTN) Status, OptionNumber));
+ ASSERT (Status == EFI_ALREADY_STARTED || Status == EFI_SUCCESS);
+
+ //
+ // 4. Create platform specified Driver####
+ //
+ DriverOptions = EfiBootManagerGetLoadOptions (&DriverOptionCount, LoadOptionTypeDriver);
+
+ for (Index = 0; gPlatformDriverOption[Index] != NULL; Index++) {
+ Status = EfiBootManagerInitializeLoadOption (
+ &DriverOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeDriver,
+ LOAD_OPTION_ACTIVE,
+ L"",
+ gPlatformDriverOption[Index],
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (EfiBootManagerFindLoadOption (&DriverOption, DriverOptions, DriverOptionCount) == -1) {
+ Status = EfiBootManagerAddLoadOptionVariable (&DriverOption, (UINTN) -1);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ EfiBootManagerFreeLoadOption (&DriverOption);
+ }
+
+ EfiBootManagerFreeLoadOptions (DriverOptions, DriverOptionCount);
+}
+
+VOID
+Diagnostics (
+ IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
+ IN BOOLEAN QuietBoot
+ )
+/*++
+
+Routine Description:
+
+ Perform the platform diagnostic, such like test memory. OEM/IBV also
+ can customize this fuction to support specific platform diagnostic.
+
+Arguments:
+
+ MemoryTestLevel - The memory test intensive level
+
+ QuietBoot - Indicate if need to enable the quiet boot
+
+ BaseMemoryTest - A pointer to BdsMemoryTest()
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Here we can decide if we need to show
+ // the diagnostics screen
+ // Notes: this quiet boot code should be remove
+ // from the graphic lib
+ //
+
+ if (QuietBoot) {
+ EnableQuietBoot (PcdGetPtr(PcdLogoFile));
+
+ //
+ // Perform system diagnostic
+ //
+ Status = MemoryTest (MemoryTestLevel);
+ if (EFI_ERROR (Status)) {
+ DisableQuietBoot ();
+ }
+ return ;
+ }
+ //
+ // Perform system diagnostic
+ //
+ Status = MemoryTest (MemoryTestLevel);
+
+}
+
+/**
+ Returns the priority number.
+
+ @param BootOption
+**/
+UINTN
+BootOptionPriority (
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+ )
+{
+ //
+ // Make sure Shell is in the last
+ //
+ if (StrCmp (BootOption->Description, L"UEFI Internal Shell") == 0) {
+ return 100;
+ }
+ return 0;
+}
+
+BOOLEAN
+EFIAPI
+CompareBootOption (
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Left,
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Right
+ )
+{
+ return (BOOLEAN) (BootOptionPriority (Left) < BootOptionPriority (Right));
+}
+
+extern EFI_GUID gSignalBeforeEnterSetupGuid;
+
+/**
+ This function Installs a guid before entering the Setup.
+
+**/
+VOID
+SignalProtocolEvent(IN EFI_GUID *ProtocolGuid)
+{
+ EFI_HANDLE Handle = NULL;
+
+ gBS->InstallProtocolInterface (
+ &Handle, ProtocolGuid, EFI_NATIVE_INTERFACE,NULL
+ );
+
+ gBS->UninstallProtocolInterface (
+ Handle, ProtocolGuid, NULL
+ );
+}
+
+/**
+ Boot handling when secure lock down enabled.
+
+ Boot payload forever ie if payload returns then boot it again.
+
+ WARNING: Status variable in function needs to be volatile to handle
+ unreachable code error with some compilers.
+
+**/
+VOID
+EFIAPI
+SecureLockBoot (
+ VOID
+ )
+{
+ volatile EFI_STATUS Status;
+ CHAR16 OptionName[sizeof ("Boot####")];
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+ BOOLEAN SecureBootEnabled;
+
+ SecureBootEnabled = FALSE;
+
+ for (Status = EFI_SUCCESS; Status == EFI_SUCCESS; Status = EFI_SUCCESS) {
+ if(gSecureBootHelperProtocol != NULL) {
+ //
+ // re-determine in every loop iteration in case payload enables UEFI SecureBoot.
+ //
+ SecureBootEnabled = gSecureBootHelperProtocol->IsSecureBootEnabled (
+ gSecureBootHelperProtocol
+ );
+ }
+
+ if (FeaturePcdGet (PcdEnableSecureLock) && SecureBootEnabled == FALSE) {
+ //
+ // Force boot of payload in secure lock down builds if UEFI SecureBoot disabled.
+ //
+ DEBUG ((EFI_D_INFO, "SecureLockBoot ENABLED and SecureBoot Disabled: Only Allow Payload boot.\n"));
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", mPayloadBootOptionNumber);
+ Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption);
+ ASSERT_EFI_ERROR (Status);
+ EfiBootManagerBoot (&BootOption);
+ EfiBootManagerFreeLoadOption (&BootOption);
+ } else {
+ DEBUG ((EFI_D_INFO, "SecureLockBoot Do Nothing: Continue to BootOption Boot\n"));
+ break;
+ }
+ }
+}
+
+UINT32
+EFIAPI
+PlatformBootManagerAfterConsole (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ The function will excute with as the platform policy, current policy
+ is driven by boot mode. IBV/OEM can customize this code for their specific
+ policy action.
+
+Arguments:
+
+ DriverOptionList - The header of the driver option link list
+
+ BootOptionList - The header of the boot option link list
+
+ ProcessCapsules - A pointer to ProcessCapsules()
+
+ BaseMemoryTest - A pointer to BaseMemoryTest()
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ BOOLEAN DeferredImageExist;
+ UINTN Index;
+ CHAR16 CapsuleVarName[30];
+ CHAR16 *TempVarName;
+ VOID *BootState;
+ EFI_GUID EfiBootStateGuid = {
+ 0x60b5e939, 0xfcf, 0x4227, { 0xba, 0x83, 0x6b, 0xbe, 0xd4, 0x5b, 0xc0, 0xe3 }
+ };
+ BOOLEAN SecureBootEnabled;
+
+ SecureBootEnabled = FALSE;
+
+ if(gSecureBootHelperProtocol != NULL) {
+ SecureBootEnabled = gSecureBootHelperProtocol->IsSecureBootEnabled (
+ gSecureBootHelperProtocol
+ );
+ }
+
+ //
+ // Check BootState variable, NULL means it's the first boot after reflashing
+ //
+ BootState = GetVariable (L"BootState", &EfiBootStateGuid);
+ if (BootState != NULL) {
+ FreePool (BootState);
+ }
+
+ BootMode = GetBootModeHob ();
+ DEBUG ((EFI_D_INFO, "[PlatformBds]BootMode = %d\n", (UINTN) BootMode));
+
+ //
+ // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
+ // as early as possible which will avoid the next time boot after the capsule update
+ // will still into the capsule loop
+ //
+ StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+ Index = 0;
+ while (TRUE) {
+ if (Index > 0) {
+ UnicodeValueToString (TempVarName, 0, Index, 0);
+ }
+ Status = gRT->SetVariable (
+ CapsuleVarName,
+ &gEfiCapsuleVendorGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ (VOID *)NULL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // There is no capsule variables, quit
+ //
+ break;
+ }
+ Index++;
+ }
+
+ //
+ // No deferred image exists by default
+ //
+ DeferredImageExist = FALSE;
+
+ //
+ // Go the different platform policy with different boot mode
+ // Notes: this part code can be change with the table policy
+ //
+ switch (BootMode) {
+
+ case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+ case BOOT_WITH_MINIMAL_CONFIGURATION:
+ //
+ // Memory test and Logo show
+ //
+ Diagnostics (IGNORE, TRUE);
+
+ //
+ // Perform some platform specific connect sequence
+ //
+ ConnectSequence ();
+
+ //
+ // As console is ready, perform user identification again.
+ //
+ if (mCurrentUser == NULL) {
+ CheckDeferredImage (&mCurrentUser, &DeferredImageExist);
+ if (DeferredImageExist) {
+ //
+ // After user authentication, the deferred drivers was loaded again.
+ // Here, need to ensure the deferred images are connected.
+ //
+ EfiBootManagerConnectAllDefaultConsoles ();
+ ConnectSequence ();
+ }
+ }
+ break;
+
+ case BOOT_ON_FLASH_UPDATE:
+ //
+ // Clear protected ranges before updating flash.
+ //
+ Status = PlatformClearSpiProtect ();
+ ASSERT_EFI_ERROR (Status);
+ if (FeaturePcdGet (PcdSupportUpdateCapsuleReset)) {
+ EfiBootManagerProcessCapsules ();
+ } else {
+ ASSERT (FeaturePcdGet (PcdSupportUpdateCapsuleReset));
+ }
+
+ //
+ // Cold reset the system as any flash update are now complete
+ //
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+
+ break;
+
+ case BOOT_IN_RECOVERY_MODE:
+ //
+ // In recovery mode, just connect platform console
+ // and show up the front page
+ //
+ Diagnostics (EXTENSIVE, FALSE);
+ EfiBootManagerConnectAll ();
+
+ //
+ // Perform user identification
+ //
+ if (mCurrentUser == NULL) {
+ CheckDeferredImage (&mCurrentUser, &DeferredImageExist);
+ if (DeferredImageExist) {
+ //
+ // After user authentication, the deferred drivers was loaded again.
+ // Here, need to ensure the deferred drivers are connected.
+ //
+ EfiBootManagerConnectAll ();
+ }
+ }
+
+ break;
+
+ case BOOT_WITH_FULL_CONFIGURATION:
+ case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
+ case BOOT_WITH_DEFAULT_SETTINGS:
+ default:
+ //
+ // Memory test and Logo show
+ //
+ Diagnostics (IGNORE, TRUE);
+
+ //
+ // Perform some platform specific connect sequence
+ //
+ ConnectSequence ();
+
+ //
+ // Perform user identification
+ //
+ if (mCurrentUser == NULL) {
+ CheckDeferredImage (&mCurrentUser, &DeferredImageExist);
+ if (DeferredImageExist) {
+ //
+ // After user authentication, the deferred drivers was loaded again.
+ // Here, need to ensure the deferred drivers are connected.
+ //
+ EfiBootManagerConnectAllDefaultConsoles ();
+ ConnectSequence ();
+ }
+ }
+
+ //
+ // Here we have enough time to do the enumeration of boot device
+ //
+ EfiBootManagerRefreshAllBootOption ();
+ if (BootState == NULL) {
+ EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
+ }
+ break;
+ }
+
+ //
+ // Lock regions and config of SPI flash.
+ //
+ PlatformFlashLockPolicy (TRUE);
+
+ //
+ // NOTE: We need install DxeSmmReadyToLock directly here because many boot script is added via ExitPmAuth callback.
+ // If we install them at same callback, these boot script will be rejected because BootScript Driver runs first to lock them done.
+ // So we seperate them to be 2 different events, ExitPmAuth is last chance to let platform add boot script. DxeSmmReadyToLock will
+ // make boot script save driver lock down the interface.
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiDxeSmmReadyToLockProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if(!FeaturePcdGet (PcdEnableSecureLock) || (SecureBootEnabled)) {
+ //
+ // Print menu in unsecure builds or when UEFI SecureBoot enabled.
+ //
+ PrintBootPrompt ();
+ }
+
+ //
+ // Signal a event before entering Setup.
+ //
+ DEBUG ((EFI_D_INFO, "Before Entering Setup...\n"));
+ SignalProtocolEvent(&gSignalBeforeEnterSetupGuid);
+
+ SecureLockBoot ();
+
+ //
+ // If SecureBoot then validate its vars for this platform.
+ //
+ PlatformValidateSecureBootVars ();
+
+ return PLATFORM_BOOT_MANAGER_ENABLE_ALL;
+}
+
+/**
+ Connect the predefined platform default authentication devices.
+
+ This function connects the predefined device path for authentication device,
+ and if the predefined device path has child device path, the child handle will
+ be connected too. But the child handle of the child will not be connected.
+
+**/
+VOID
+EFIAPI
+ConnectAuthDevice (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN HandleIndex;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath;
+ EFI_USER_MANAGER_PROTOCOL *Manager;
+
+ Status = gBS->LocateProtocol (
+ &gEfiUserManagerProtocolGuid,
+ NULL,
+ (VOID **) &Manager
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // As user manager protocol is not installed, the authentication devices
+ // should not be connected.
+ //
+ return ;
+ }
+
+ Index = 0;
+ while (gUserAuthenticationDevice[Index] != NULL) {
+ //
+ // Connect the platform customized device paths
+ //
+ EfiBootManagerConnectDevicePath (gUserAuthenticationDevice[Index], NULL);
+ Index++;
+ }
+
+ //
+ // Find and connect the child device paths of the platform customized device paths
+ //
+ HandleBuffer = NULL;
+ for (Index = 0; gUserAuthenticationDevice[Index] != NULL; Index++) {
+ HandleCount = 0;
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find and connect the child device paths of gUserIdentificationDevice[Index]
+ //
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ ChildDevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ChildDevicePath
+ );
+ if (EFI_ERROR (Status) || ChildDevicePath == NULL) {
+ continue;
+ }
+
+ if (CompareMem (
+ ChildDevicePath,
+ gUserAuthenticationDevice[Index],
+ (GetDevicePathSize (gUserAuthenticationDevice[Index]) - sizeof (EFI_DEVICE_PATH_PROTOCOL))
+ ) != 0) {
+ continue;
+ }
+ gBS->ConnectController (HandleBuffer[HandleIndex], NULL, NULL, TRUE);
+ }
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+}
+
+/**
+ This function is to identify a user, and return whether deferred images exist.
+
+ @param[out] User Point to user profile handle.
+ @param[out] DeferredImageExist On return, points to TRUE if the deferred image
+ exist or FALSE if it did not exist.
+
+**/
+VOID
+CheckDeferredImage (
+ OUT EFI_USER_PROFILE_HANDLE *User,
+ OUT BOOLEAN *DeferredImageExist
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *DeferredImage;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuf;
+ UINTN Index;
+ UINTN DriverIndex;
+ EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
+ VOID *DriverImage;
+ UINTN ImageSize;
+ BOOLEAN BootOption;
+
+ //
+ // Perform user identification
+ //
+ do {
+ Status = UserIdentify (User);
+ } while (EFI_ERROR (Status));
+
+ //
+ // After user authentication now, try to find whether deferred images exists
+ //
+ HandleCount = 0;
+ HandleBuf = NULL;
+ *DeferredImageExist = FALSE;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiDeferredImageLoadProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuf
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuf[Index],
+ &gEfiDeferredImageLoadProtocolGuid,
+ (VOID **) &DeferredImage
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Find whether deferred image exists in this instance.
+ //
+ DriverIndex = 0;
+ Status = DeferredImage->GetImageInfo(
+ DeferredImage,
+ DriverIndex,
+ &ImageDevicePath,
+ (VOID **) &DriverImage,
+ &ImageSize,
+ &BootOption
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // The deferred image is found.
+ //
+ FreePool (HandleBuf);
+ *DeferredImageExist = TRUE;
+ return ;
+ }
+ }
+ }
+
+ FreePool (HandleBuf);
+}
+
+/** Constructor for this lib.
+
+ Tasks:
+ Fixup globals with PCD values.
+
+ @param ImageHandle ImageHandle of the loaded driver.
+ @param SystemTable Pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS Register successfully.
+**/
+EFI_STATUS
+EFIAPI
+PlatformBootManagerLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG((EFI_D_INFO, "PlatformBootManagerLibConstructor:>>\n"));
+ gSerialDevicePath.SerialDevice.Function = PcdGet8 (PcdIohUartFunctionNumber);
+ gSerialDevicePath.SerialDevice.Device = PcdGet8 (PcdIohUartDevNumber);
+ gSerialDevicePath.Uart.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
+ gSerialDevicePath.Uart.DataBits = PcdGet8 (PcdUartDefaultDataBits);
+ gSerialDevicePath.Uart.Parity = PcdGet8 (PcdUartDefaultParity);
+ gSerialDevicePath.Uart.StopBits = PcdGet8 (PcdUartDefaultStopBits);
+
+ Status = gBS->LocateProtocol(
+ &gSecureBootHelperProtocolGuid,
+ NULL,
+ (VOID**) &gSecureBootHelperProtocol
+ );
+
+ if (EFI_ERROR(Status)) {
+ //
+ // Helper needed for Secure lockdown builds.
+ //
+ gSecureBootHelperProtocol = NULL;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/BdsPlatform.h b/QuarkPlatformPkg/Library/PlatformBootManagerLib/BdsPlatform.h
new file mode 100644
index 0000000..51a729e
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/BdsPlatform.h
@@ -0,0 +1,268 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ BdsPlatform.h
+
+Abstract:
+
+ Head file for BDS Platform specific code
+
+--*/
+
+#ifndef _BDS_PLATFORM_H
+#define _BDS_PLATFORM_H
+
+#include <PiDxe.h>
+#include <Ioh.h>
+
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/UserManager.h>
+#include <Protocol/DeferredImageLoad.h>
+#include <Protocol/GenericMemoryTest.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/ExitPmAuth.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/PciPlatform.h>
+#include <Protocol/AcpiS3Save.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/SecureBootHelper.h>
+
+#include <Guid/CapsuleVendor.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/GlobalVariable.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/PlatformBootManagerLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HobLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/LogoLib.h>
+#include <Library/HiiLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/PlatformHelperLib.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Atapi.h>
+
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN ConnectType;
+} BDS_CONSOLE_CONNECT_ENTRY;
+
+#define CONSOLE_OUT 0x00000001
+#define STD_ERROR 0x00000002
+#define CONSOLE_IN 0x00000004
+#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+
+//
+//
+//
+#define VIDEO_DEV_NUM 0x00
+#define VIDEO_FUNC_NUM 0x00
+
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges [];
+extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole [];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformAllPossibleAgpConsole [];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence [];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption [];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformBootOption [];
+extern EFI_DEVICE_PATH_PROTOCOL *gUserAuthenticationDevice[];
+#define gPciRootBridge \
+ { \
+ ACPI_DEVICE_PATH, ACPI_DP, (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), (UINT8) \
+ ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8), EISA_PNP_ID (0x0A03), 0 \
+ }
+
+#define gEndEntire \
+ { \
+ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, END_DEVICE_PATH_LENGTH, 0 \
+ }
+
+//
+// Platform Root Bridge
+//
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
+
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH PcieBridge;
+ PCI_DEVICE_PATH PcieDevice;
+ ACPI_ADR_DEVICE_PATH DisplayDevice;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_PCIE_DEVICE_PATH;
+
+//
+// Below is the platform USB controller device path for
+// USB disk as user authentication device.
+//
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH PciDevice;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_USB_DEVICE_PATH;
+
+typedef struct {
+ USB_CLASS_DEVICE_PATH UsbClass;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH SerialDevice;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEVICE_PATH TerminalType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_PCI_SERIAL_DEVICE_PATH;
+
+#define CLASS_HID 3
+#define SUBCLASS_BOOT 1
+#define PROTOCOL_KEYBOARD 1
+
+//
+// Platform BDS global variables.
+//
+
+extern PLATFORM_PCI_SERIAL_DEVICE_PATH gSerialDevicePath;
+extern SECUREBOOT_HELPER_PROTOCOL *gSecureBootHelperProtocol;
+
+//
+// Platform BDS Functions
+//
+
+/**
+ Perform the memory test base on the memory test intensive level,
+ and update the memory resource.
+
+ @param Level The memory test intensive level.
+
+ @retval EFI_STATUS Success test all the system memory and update
+ the memory resource
+
+**/
+EFI_STATUS
+MemoryTest (
+ IN EXTENDMEM_COVERAGE_LEVEL Level
+ );
+
+VOID
+RegisterLoadOptions (
+ VOID
+ );
+
+VOID
+ConnectSequence (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Connect with predeined platform connect sequence,
+ the OEM/IBV can customize with their own connect sequence.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ None.
+
+--*/
+;
+
+/**
+ Connect the predefined platform default authentication devices.
+
+ This function connects the predefined device path for authentication device,
+ and if the predefined device path has child device path, the child handle will
+ be connected too. But the child handle of the child will not be connected.
+
+**/
+VOID
+ConnectAuthDevice (
+ VOID
+ );
+
+/**
+ This function is to identify a user, and return whether deferred images exist.
+
+ @param[out] User Point to user profile handle.
+ @param[out] DeferredImageExist On return, points to TRUE if the deferred image
+ exist or FALSE if it did not exist.
+
+**/
+VOID
+CheckDeferredImage (
+ OUT EFI_USER_PROFILE_HANDLE *User,
+ OUT BOOLEAN *DeferredImage
+ );
+
+VOID
+InitializeStringSupport (
+ VOID
+ );
+VOID
+PrintBootPrompt (
+ VOID
+ );
+VOID
+PrintMfgModePrompt (
+ VOID
+ );
+VOID
+LockNonUpdatableFlash (
+ VOID
+ );
+#endif
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/MemoryTest.c b/QuarkPlatformPkg/Library/PlatformBootManagerLib/MemoryTest.c
new file mode 100644
index 0000000..0d381c0
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/MemoryTest.c
@@ -0,0 +1,326 @@
+/** @file
+ Perform the platform memory test
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "BdsPlatform.h"
+
+//
+// BDS Platform Functions
+//
+
+EFI_HII_HANDLE mHiiHandle = NULL;
+
+VOID
+InitializeStringSupport (
+ VOID
+ )
+{
+ mHiiHandle = HiiAddPackages (
+ &gEfiCallerIdGuid,
+ gImageHandle,
+ PlatformBootManagerLibStrings,
+ NULL
+ );
+ ASSERT (mHiiHandle != NULL);
+}
+
+VOID
+PrintBootPrompt (
+ VOID
+ )
+{
+ CHAR16 *BootPrompt;
+
+ BootPrompt = HiiGetString (mHiiHandle, STRING_TOKEN (STR_BOOT_PROMPT), NULL);
+ if (BootPrompt != NULL) {
+ Print (BootPrompt);
+ FreePool (BootPrompt);
+ }
+}
+
+VOID
+PrintMfgModePrompt (
+ VOID
+ )
+{
+ CHAR16 *MfgPrompt;
+
+ MfgPrompt = HiiGetString (mHiiHandle, STRING_TOKEN (STR_MFG_MODE_PROMPT), NULL);
+ if (MfgPrompt != NULL) {
+ Print (MfgPrompt);
+ FreePool (MfgPrompt);
+ }
+}
+
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+ UINT16 TimeoutRemain
+ )
+{
+ CHAR16 *TmpStr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINT16 Timeout;
+
+ Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+ //
+ // Show progress
+ //
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+
+ TmpStr = HiiGetString (mHiiHandle, STRING_TOKEN (STR_START_BOOT_OPTION), NULL);
+ if (TmpStr != NULL) {
+ ShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ (Timeout - TimeoutRemain) * 100 / Timeout,
+ 0
+ );
+ FreePool (TmpStr);
+ }
+}
+
+/**
+ Perform the memory test base on the memory test intensive level,
+ and update the memory resource.
+
+ @param Level The memory test intensive level.
+
+ @retval EFI_STATUS Success test all the system memory and update
+ the memory resource
+
+**/
+EFI_STATUS
+MemoryTest (
+ IN EXTENDMEM_COVERAGE_LEVEL Level
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS KeyStatus;
+ EFI_STATUS InitStatus;
+ EFI_STATUS ReturnStatus;
+ BOOLEAN RequireSoftECCInit;
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;
+ UINT64 TestedMemorySize;
+ UINT64 TotalMemorySize;
+ UINTN TestPercent;
+ UINT64 PreviousValue;
+ BOOLEAN ErrorOut;
+ BOOLEAN TestAbort;
+ EFI_INPUT_KEY Key;
+ CHAR16 StrPercent[80];
+ CHAR16 *StrTotalMemory;
+ CHAR16 *Pos;
+ CHAR16 *TmpStr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ BOOLEAN IsFirstBoot;
+ UINT32 TempData;
+
+ //
+ // Use a DynamicHii type pcd to save the boot status, which is used to
+ // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration.
+ //
+ IsFirstBoot = PcdGetBool(PcdBootState);
+ if (IsFirstBoot) {
+ PcdSetBool(PcdBootState, FALSE);
+ }
+
+ ReturnStatus = EFI_SUCCESS;
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
+
+ Pos = AllocatePool (128);
+
+ if (Pos == NULL) {
+ return ReturnStatus;
+ }
+
+ StrTotalMemory = Pos;
+
+ TestedMemorySize = 0;
+ TotalMemorySize = 0;
+ PreviousValue = 0;
+ ErrorOut = FALSE;
+ TestAbort = FALSE;
+ TestPercent = 0;
+
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+
+ RequireSoftECCInit = FALSE;
+
+ Status = gBS->LocateProtocol (
+ &gEfiGenericMemTestProtocolGuid,
+ NULL,
+ (VOID **) &GenMemoryTest
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Pos);
+ return EFI_SUCCESS;
+ }
+
+ InitStatus = GenMemoryTest->MemoryTestInit (
+ GenMemoryTest,
+ Level,
+ &RequireSoftECCInit
+ );
+ if (InitStatus == EFI_NO_MEDIA) {
+ //
+ // The PEI codes also have the relevant memory test code to check the memory,
+ // it can select to test some range of the memory or all of them. If PEI code
+ // checks all the memory, this BDS memory test will has no not-test memory to
+ // do the test, and then the status of EFI_NO_MEDIA will be returned by
+ // "MemoryTestInit". So it does not need to test memory again, just return.
+ //
+ FreePool (Pos);
+ return EFI_SUCCESS;
+ }
+
+ TmpStr = HiiGetString (mHiiHandle, STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST), NULL);
+
+ if (TmpStr != NULL) {
+ PrintXY (10, 10, NULL, NULL, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ do {
+ Status = GenMemoryTest->PerformMemoryTest (
+ GenMemoryTest,
+ &TestedMemorySize,
+ &TotalMemorySize,
+ &ErrorOut,
+ TestAbort
+ );
+ if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {
+ TmpStr = HiiGetString (mHiiHandle, STRING_TOKEN (STR_SYSTEM_MEM_ERROR), NULL);
+ if (TmpStr != NULL) {
+ PrintXY (10, 10, NULL, NULL, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ ASSERT (0);
+ }
+
+ TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);
+ TestPercent = (UINTN) DivU64x32 (
+ DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),
+ TempData
+ );
+ if (TestPercent != PreviousValue) {
+ UnicodeValueToString (StrPercent, 0, TestPercent, 0);
+ TmpStr = HiiGetString (mHiiHandle, STRING_TOKEN (STR_MEMORY_TEST_PERCENT), NULL);
+ if (TmpStr != NULL) {
+ //
+ // TmpStr size is 64, StrPercent is reserved to 16.
+ //
+ StrCat (StrPercent, TmpStr);
+ PrintXY (10, 10, NULL, NULL, StrPercent);
+ FreePool (TmpStr);
+ }
+
+ TmpStr = HiiGetString (mHiiHandle, STRING_TOKEN (STR_PERFORM_MEM_TEST), NULL);
+ if (TmpStr != NULL) {
+ ShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ TestPercent,
+ (UINTN) PreviousValue
+ );
+ FreePool (TmpStr);
+ }
+ }
+
+ PreviousValue = TestPercent;
+
+ KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {
+ if (!RequireSoftECCInit) {
+ TmpStr = HiiGetString (mHiiHandle, STRING_TOKEN (STR_PERFORM_MEM_TEST), NULL);
+ if (TmpStr != NULL) {
+ ShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ 100,
+ (UINTN) PreviousValue
+ );
+ FreePool (TmpStr);
+ }
+
+ PrintXY (10, 10, NULL, NULL, L"100");
+ Status = GenMemoryTest->Finished (GenMemoryTest);
+ goto Done;
+ }
+
+ TestAbort = TRUE;
+ }
+ } while (Status != EFI_NOT_FOUND);
+
+ Status = GenMemoryTest->Finished (GenMemoryTest);
+
+Done:
+ UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);
+ if (StrTotalMemory[0] == L',') {
+ StrTotalMemory++;
+ }
+
+ TmpStr = HiiGetString (mHiiHandle, STRING_TOKEN (STR_MEM_TEST_COMPLETED), NULL);
+ if (TmpStr != NULL) {
+ StrCat (StrTotalMemory, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ PrintXY (10, 10, NULL, NULL, StrTotalMemory);
+ ShowProgress (
+ Foreground,
+ Background,
+ StrTotalMemory,
+ Color,
+ 100,
+ (UINTN) PreviousValue
+ );
+ FreePool (Pos);
+
+
+ return ReturnStatus;
+}
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
new file mode 100755
index 0000000..b20ed0c
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -0,0 +1,132 @@
+#/** @file
+# Component name for module PlatformBootManagerLib
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformBootManagerLib
+ FILE_GUID = 7B83D5FB-E943-4323-A08D-B941A290189A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER UEFI_APPLICATION
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+ CONSTRUCTOR = PlatformBootManagerLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ MemoryTest.c
+ BdsPlatform.c
+ PlatformData.c
+ BdsPlatform.h
+ Strings.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ PrintLib
+ DevicePathLib
+ UefiLib
+ HobLib
+ DxeServicesLib
+ HiiLib
+ UefiBootManagerLib
+ LogoLib
+ IntelQNCLib
+ PlatformHelperLib
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiLegacyBiosProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiCpuIoProtocolGuid
+ gExitPmAuthProtocolGuid
+ gEfiGenericMemTestProtocolGuid
+ gEfiPciPlatformProtocolGuid
+ gEfiUserManagerProtocolGuid
+ gEfiDeferredImageLoadProtocolGuid
+ gEfiLoadedImageProtocolGuid
+ gEfiAcpiS3SaveProtocolGuid
+ gEfiDxeSmmReadyToLockProtocolGuid
+ gSecureBootHelperProtocolGuid
+
+[Guids]
+ gEfiCapsuleVendorGuid
+ gEfiGlobalVariableGuid
+ gSignalBeforeEnterSetupGuid
+ gEfiSetupVariableGuid
+
+[FeaturePcd]
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset
+ gQuarkPlatformTokenSpaceGuid.PcdSupportSecureBoot
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdPayloadFile
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartBusNumber
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartDevNumber
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartFunctionNumber
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+
+[Pcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoveryBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadSize
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformData.c b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformData.c
new file mode 100755
index 0000000..15a4eeb
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformData.c
@@ -0,0 +1,197 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformData.c
+
+Abstract:
+
+ Defined the platform specific device path which will be used by
+ platform Bbd to perform the platform policy connect.
+
+--*/
+
+#include "BdsPlatform.h"
+
+//
+// Predefined platform default time out value
+//
+UINT16 gPlatformBootTimeOutDefault = 10;
+
+//
+// Predefined platform root bridge
+//
+PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {
+ gPciRootBridge,
+ gEndEntire
+};
+
+EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = {
+ (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,
+ NULL
+};
+
+//
+// Platform specific serial device path
+//
+PLATFORM_PCI_SERIAL_DEVICE_PATH gSerialDevicePath = {
+ gPciRootBridge,
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ (UINT8) (sizeof (PCI_DEVICE_PATH)),
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8),
+ 0xff,
+ 0xff
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ (UINT8) (sizeof (UART_DEVICE_PATH)),
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8),
+ 0,
+ 0xffffffffffffffff,
+ 0xff,
+ 0xff,
+ 0xff
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8),
+ DEVICE_PATH_MESSAGING_PC_ANSI
+ },
+ gEndEntire
+};
+
+USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_CLASS_DP,
+ (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
+ (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
+ },
+ 0xffff, // VendorId
+ 0xffff, // ProductId
+ CLASS_HID, // DeviceClass
+ SUBCLASS_BOOT, // DeviceSubClass
+ PROTOCOL_KEYBOARD // DeviceProtocol
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+};
+
+//
+// Predefined platform default console device path
+//
+BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *) &gSerialDevicePath,
+ (CONSOLE_OUT | CONSOLE_IN)
+ },
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath,
+ CONSOLE_IN
+ },
+ {
+ NULL,
+ 0
+ }
+};
+
+//
+// Predefined platform specific perdict boot option
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformBootOption[] = {
+ NULL
+};
+
+//
+// Predefined platform specific driver option
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL };
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };
+
+//
+// Platform specific USB controller device path
+//
+PLATFORM_USB_DEVICE_PATH gUsbDevicePath0 = {
+ gPciRootBridge,
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ (UINT8)(sizeof(PCI_DEVICE_PATH)),
+ (UINT8)((sizeof(PCI_DEVICE_PATH)) >> 8),
+ IOH_EHCI_FUNCTION_NUMBER,
+ IOH_USB_EHCI_DEVICE_NUMBER
+ },
+ gEndEntire
+};
+
+//
+// Platform specific USB controller device path
+//
+PLATFORM_USB_DEVICE_PATH gUsbDevicePath1 = {
+ gPciRootBridge,
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ (UINT8)(sizeof(PCI_DEVICE_PATH)),
+ (UINT8)((sizeof(PCI_DEVICE_PATH)) >> 8),
+ IOH_OHCI_FUNCTION_NUMBER,
+ IOH_USB_OHCI_DEVICE_NUMBER
+ },
+ gEndEntire
+};
+
+//
+// Predefined platform device path for user authtication
+//
+EFI_DEVICE_PATH_PROTOCOL* gUserAuthenticationDevice[] = {
+ //
+ // Predefined device path for secure card (USB disk).
+ //
+ (EFI_DEVICE_PATH_PROTOCOL*)&gUsbDevicePath0,
+ (EFI_DEVICE_PATH_PROTOCOL*)&gUsbDevicePath1,
+ NULL
+};
+
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/Strings.uni b/QuarkPlatformPkg/Library/PlatformBootManagerLib/Strings.uni
new file mode 100644
index 0000000..af987cd
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/Strings.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Library/PlatformCapsuleLib/IA32/TrigSmi.S b/QuarkPlatformPkg/Library/PlatformCapsuleLib/IA32/TrigSmi.S
new file mode 100644
index 0000000..bda4dc5
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformCapsuleLib/IA32/TrigSmi.S
@@ -0,0 +1,90 @@
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# TrigSmi.S
+#
+# Abstract:
+#
+# TrigSmi for capsule update. SMI number is 0x27 and 0x28.
+#
+# Notes:
+#
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# VOID
+# SendCapsuleSmi (
+# UINTN Addr
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(SendCapsuleSmi)
+ASM_PFX(SendCapsuleSmi):
+ pushl %ecx
+ movl 8(%esp), %ecx
+ pushl %ebp
+ movl %esp, %ebp
+ subl $8, %esp
+ pushl %eax
+ pushl %ebx
+ movl %ecx, %ebx
+ movl $0xEF27, %eax
+ outb %al, $0xB2
+ popl %ebx
+ popl %eax
+ movl %ebp, %esp
+ popl %ebp
+ popl %ecx
+ ret $0
+
+
+#------------------------------------------------------------------------------
+# VOID
+# GetUpdateStatusSmi (
+# UINTN Addr
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(GetUpdateStatusSmi)
+ASM_PFX(GetUpdateStatusSmi):
+ pushl %ecx
+ movl 8(%esp), %ecx
+ pushl %ebp
+ movl %esp, %ebp
+ subl $8, %esp
+ pushl %eax
+ pushl %ebx
+ movl %ecx, %ebx
+ movl $0xEF28, %eax
+ outb %al, $0xB2
+ popl %ebx
+ popl %eax
+ movl %ebp, %esp
+ popl %ebp
+ popl %ecx
+ ret $0
diff --git a/QuarkPlatformPkg/Library/PlatformCapsuleLib/IA32/TrigSmi.asm b/QuarkPlatformPkg/Library/PlatformCapsuleLib/IA32/TrigSmi.asm
new file mode 100644
index 0000000..5f6d051
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformCapsuleLib/IA32/TrigSmi.asm
@@ -0,0 +1,93 @@
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; TrigSmi.asm
+;
+; Abstract:
+;
+; TrigSmi for capsule update. SMI number is 0x27 and 0x28.
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+ .386P
+ .MODEL FLAT,C
+ .CODE
+;------------------------------------------------------------------------------
+; VOID
+; SendCapsuleSmi (
+; UINTN Addr
+; )
+;------------------------------------------------------------------------------
+SendCapsuleSmi PROC PUBLIC
+ push ecx
+ mov ecx, dword ptr [esp + 8]
+ push ebp
+ mov ebp, esp
+ sub esp, 8
+ push eax
+ push ebx
+ mov ebx, ecx
+ mov eax, 0EF27h
+ out 0B2h, AL
+ pop ebx
+ pop eax
+ mov esp, ebp
+ pop ebp
+ pop ecx
+ ret 0
+SendCapsuleSmi ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; GetUpdateStatusSmi (
+; UINTN Addr
+; )
+;------------------------------------------------------------------------------
+GetUpdateStatusSmi PROC PUBLIC
+ push ecx
+ mov ecx, dword ptr [esp + 8]
+ push ebp
+ mov ebp, esp
+ sub esp, 8
+ push eax
+ push ebx
+ mov ebx, ecx
+ mov eax, 0EF28h
+ out 0B2h, AL
+ pop ebx
+ pop eax
+ mov esp, ebp
+ pop ebp
+ pop ecx
+ ret 0
+GetUpdateStatusSmi ENDP
+
+END
diff --git a/QuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.c b/QuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.c
new file mode 100755
index 0000000..85e14be
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.c
@@ -0,0 +1,246 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Abstract:
+ Capsule Library instance to update capsule image to flash.
+
+**/
+#include <PiDxe.h>
+
+#include <Guid/QuarkCapsuleGuid.h>
+#include <Protocol/FirmwareVolumeBlockSecurity.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HobLib.h>
+#include <Library/QNCAccessLib.h>
+
+extern VOID SendCapsuleSmi(UINTN Addr);
+extern VOID GetUpdateStatusSmi(UINTN Addr);
+
+/**
+ Those capsules supported by the firmwares.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+**/
+EFI_STATUS
+EFIAPI
+SupportCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ if (CompareGuid (&gEfiQuarkCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The firmware implements to process the capsule image.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ CAPSULE_INFO_PACKET *CapsuleInfoPacketPtr;
+ CAPSULE_FRAGMENT *CapsuleFragmentPtr;
+ UPDATE_STATUS_PACKET *UpdateStatusPacketPtr;
+ EFI_STATUS Status;
+ UINT16 WdtBaseAddress;
+ STATIC UINT8 WdtConfigRegister;
+ UINT8 WdtResetEnabled;
+ UINT8 WdtLockEnabled;
+ FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL *FvbSecurityProtocol;
+ EFI_HOB_GUID_TYPE *SecurityHeaderHob;
+ VOID *SecurityHeader;
+ UINTN TempSize;
+ UINT8 *AuthImage;
+
+ TempSize = 0;
+
+ if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Locate Fvb Security Protocol for Capsule File Verification.
+ //
+ Status = gBS->LocateProtocol(
+ &gFirmwareVolumeBlockSecurityGuid,
+ NULL,
+ (VOID**) &FvbSecurityProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (FvbSecurityProtocol != NULL);
+ ASSERT (FvbSecurityProtocol->SecurityAuthenticateImage != NULL);
+
+ if (FvbSecurityProtocol != NULL) {
+ //
+ // If NoReset Capsule we should have a security header prefix to CapHdr.
+ //
+ Status = FvbSecurityProtocol->SecurityAuthenticateImage ((VOID *) CapsuleHeader);
+ if (EFI_ERROR(Status)) {
+ //
+ // If Reset Capsule get SecHdr from HOB created at PEI stage.
+ //
+ SecurityHeaderHob = GetFirstGuidHob (&gEfiQuarkCapsuleSecurityHeaderGuid);
+ if (SecurityHeaderHob != NULL) {
+ SecurityHeader = GET_GUID_HOB_DATA (SecurityHeaderHob);
+ if (SecurityHeader != NULL) {
+ DEBUG ((EFI_D_INFO, "ProcessCapsuleImage: SecHdrPtr:SigId 0x%8X:0x%8X \n",
+ (UINTN) SecurityHeader,
+ (UINTN) *((UINT32 *) SecurityHeader)
+ ));
+
+ TempSize =
+ PcdGet32 (PcdFvSecurityHeaderSize) +
+ CapsuleHeader->HeaderSize +
+ CapsuleHeader->CapsuleImageSize;
+
+ AuthImage = AllocatePool (TempSize);
+ ASSERT (AuthImage != NULL);
+
+ CopyMem (
+ (VOID *) AuthImage,
+ SecurityHeader,
+ PcdGet32 (PcdFvSecurityHeaderSize)
+ );
+
+ TempSize -= PcdGet32 (PcdFvSecurityHeaderSize);
+ CopyMem (
+ (VOID *) &AuthImage[PcdGet32 (PcdFvSecurityHeaderSize)],
+ (VOID *) CapsuleHeader,
+ TempSize);
+
+ Status = FvbSecurityProtocol->SecurityAuthenticateImage (
+ (VOID *) &AuthImage[PcdGet32 (PcdFvSecurityHeaderSize)]
+ );
+
+ FreePool (AuthImage);
+ }
+ }
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ CapsuleFragmentPtr = (CAPSULE_FRAGMENT *) AllocateZeroPool (sizeof (CAPSULE_FRAGMENT));
+ CapsuleInfoPacketPtr = (CAPSULE_INFO_PACKET *) AllocateZeroPool (sizeof (CAPSULE_INFO_PACKET));
+ UpdateStatusPacketPtr = (UPDATE_STATUS_PACKET *) AllocateZeroPool (sizeof (UPDATE_STATUS_PACKET));
+ DEBUG ((EFI_D_INFO, "CapsuleImage Address is %10p, CapsuleImage Size is %8x\n", CapsuleHeader, CapsuleHeader->CapsuleImageSize));
+ DEBUG ((EFI_D_INFO, "CapsuleFragment Address is %10p, CapsuleInfo Address is %10p\n", CapsuleFragmentPtr, CapsuleInfoPacketPtr));
+
+ //
+ // Prepare structures to store capsule image.
+ //
+
+ CapsuleFragmentPtr->Address = (UINTN) CapsuleHeader;
+ CapsuleFragmentPtr->BufferOffset = 0;
+ CapsuleFragmentPtr->Size = CapsuleHeader->CapsuleImageSize;
+ CapsuleFragmentPtr->Flags = BIT0;
+
+ CapsuleInfoPacketPtr->CapsuleLocation = (UINTN) CapsuleFragmentPtr;
+ CapsuleInfoPacketPtr->CapsuleSize = CapsuleHeader->CapsuleImageSize;
+ CapsuleInfoPacketPtr->Status = EFI_SUCCESS;
+
+ Print (L"Start to update capsule image!\n");
+
+ //
+ // Check if WDT reset and lock are enabled
+ //
+ WdtBaseAddress = (LpcPciCfg16(R_QNC_LPC_WDTBA));
+ WdtConfigRegister = IoRead8((WdtBaseAddress + R_QNC_LPC_WDT_WDTCR));
+ WdtResetEnabled = WdtConfigRegister & BIT4;
+ WdtLockEnabled = IoRead8((WdtBaseAddress + R_QNC_LPC_WDT_WDTLR)) & BIT0;
+ ASSERT ((WdtLockEnabled == 0 && WdtResetEnabled == 0));
+
+ //
+ // Explicitly clear WDT Reset Enable
+ //
+ IoWrite8((WdtBaseAddress + R_QNC_LPC_WDT_WDTCR), (WdtConfigRegister & ~BIT4));
+
+ //
+ // Trig SMI to update Capsule image.
+ //
+ SendCapsuleSmi((UINTN)CapsuleInfoPacketPtr);
+
+ UpdateStatusPacketPtr->BlocksCompleted = 0;
+ UpdateStatusPacketPtr->TotalBlocks = (UINTN) -1;
+ UpdateStatusPacketPtr->Status = EFI_SUCCESS;
+
+ do {
+ //
+ // Trig SMI to get the status to updating capsule image.
+ //
+ gBS->Stall (200000);
+ GetUpdateStatusSmi((UINTN)UpdateStatusPacketPtr);
+
+ if (UpdateStatusPacketPtr->TotalBlocks != (UINTN) -1) {
+ Print (L"Updated Blocks completed: %d of %d\n", UpdateStatusPacketPtr->BlocksCompleted, UpdateStatusPacketPtr->TotalBlocks);
+ }
+ } while ((UpdateStatusPacketPtr->Status == EFI_SUCCESS) && (UpdateStatusPacketPtr->BlocksCompleted < UpdateStatusPacketPtr->TotalBlocks));
+
+ //
+ // Restore Previous WDT Reset Enable setting
+ //
+ IoWrite8((WdtBaseAddress + R_QNC_LPC_WDT_WDTCR), (WdtConfigRegister));
+
+
+ Status = UpdateStatusPacketPtr->Status;
+ if (EFI_ERROR (Status)) {
+ Print (L"Invalid capsule format. Please furnish a valid capsule. Return status is %r!\n", UpdateStatusPacketPtr->Status);
+ } else {
+ Print (L"Capsule image is updated done!\n");
+ }
+
+ FreePool (CapsuleFragmentPtr);
+ FreePool (CapsuleInfoPacketPtr);
+ FreePool (UpdateStatusPacketPtr);
+
+ return Status;
+}
+
diff --git a/QuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.inf b/QuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.inf
new file mode 100644
index 0000000..8e3e7ab
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.inf
@@ -0,0 +1,80 @@
+# Abstract:
+# Capsule library instance for Server capsule update.
+# It trigs SMI to update capsule image.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformCapsuleLib
+ FILE_GUID = 425AFDC9-4B2B-4ef6-BD4E-7B9977AA0FE9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CapsuleLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ PlatformCapsuleLib.c
+
+[Sources.IA32]
+ IA32/TrigSmi.asm
+ IA32/TrigSmi.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ IoLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ PcdLib
+ UefiLib
+ HobLib
+
+[Guids]
+ gEfiQuarkCapsuleGuid # CONSUMES
+ gEfiQuarkCapsuleSecurityHeaderGuid # CONSUMES
+
+[Protocols]
+ gFirmwareVolumeBlockSecurityGuid # CONSUMES
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
diff --git a/QuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.c b/QuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.c
new file mode 100755
index 0000000..c27f84a
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.c
@@ -0,0 +1,409 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformDataLib.c
+
+Abstract:
+
+ Library producing routines for platform data functionality.
+
+--*/
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+
+#include <PlatformData.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformDataLib.h>
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this source module.
+//
+
+STATIC
+PDAT_ITEM *
+FindNext (
+ IN CONST UINT64 ItemIdFilter,
+ IN CONST BOOLEAN IncrementBeforeMatchCheck,
+ IN OUT PDAT_LIB_FINDCONTEXT *FindContext,
+ OUT VOID *ItemData OPTIONAL
+ )
+{
+ PDAT_ITEM *CurrItem;
+
+ if (IncrementBeforeMatchCheck) {
+ FindContext->CurrMemLocation += sizeof(PDAT_ITEM_HEADER) + ((PDAT_ITEM *) FindContext->CurrMemLocation)->Header.Length;
+ }
+
+ do {
+
+ //
+ // Search through all platform data items.
+ //
+ if (FindContext->CurrMemLocation >= FindContext->Limit) {
+ return NULL; // End of list no more items.
+ }
+ CurrItem = (PDAT_ITEM *) FindContext->CurrMemLocation;
+
+ ///
+ /// Return Current item if user wants all items.
+ ///
+ if (ItemIdFilter == PDAT_FIND_ANY_ITEM_FILTER) {
+ break;
+ }
+
+ if (CurrItem->Header.Identifier < 64) {
+ ///
+ /// Only ids < 64 can be found with filter routines.
+ ///
+ if (PDAT_IS_FILTER_MATCH (ItemIdFilter, CurrItem->Header.Identifier)) {
+ break;
+ }
+ }
+ FindContext->CurrMemLocation += (sizeof(PDAT_ITEM_HEADER) + CurrItem->Header.Length);
+ } while (TRUE);
+
+ //
+ // Found Item, update optional outputs and return pointer to item.
+ //
+ if (ItemData != NULL) {
+ CopyMem (
+ ItemData,
+ (VOID *) &CurrItem->Data[0],
+ CurrItem->Header.Length
+ );
+ }
+ return CurrItem;
+}
+
+//
+// Routines exported by this source module.
+//
+
+/** Validate Platform Data Area.
+
+ @param[in] Area Area to Validate.
+ @param[in] DoCrcCheck Do CRC Check on area.
+
+ @retval EFI_SUCCESS Area validated.
+ @retval EFI_NOT_FOUND Signature not found in area.
+ @retval EFI_BAD_BUFFER_SIZE Area has invalid length.
+ @retval EFI_CRC_ERROR Area CRC Fail.
+ @retval EFI_INVALID_PARAMETER Area parameter invalid.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+PDatLibValidateArea (
+ IN CONST PDAT_AREA *Area,
+ IN CONST BOOLEAN DoCrcCheck
+ )
+{
+ UINT32 CalcCrc;
+ EFI_STATUS Status;
+
+ if (Area == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Area->Header.Identifier != PDAT_IDENTIFIER) {
+ return EFI_NOT_FOUND;
+ }
+ if (Area->Header.Length > PcdGet32(PcdPlatformDataMaxLen)) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ Status = EFI_SUCCESS;
+ if (DoCrcCheck) {
+ Status = PlatformCalculateCrc32 (
+ (UINT8 *) &Area->Body[0],
+ (UINTN) Area->Header.Length,
+ &CalcCrc
+ );
+ if (CalcCrc != Area->Header.Crc) {
+ return EFI_CRC_ERROR;
+ }
+ }
+ return Status;
+}
+
+/** Get pointer to system Platform Data Area.
+
+ @param[in] DoCrcCheck Do CRC Check on area.
+ @param[out] AreaPtr Pointer to pointer to receive address of
+ platform data area.
+
+ @retval EFI_SUCCESS Area validated.
+ @retval EFI_NOT_FOUND Signature not found in area.
+ @retval EFI_BAD_BUFFER_SIZE Area has invalid length.
+ @retval EFI_CRC_ERROR Area CRC Fail.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+PDatLibGetSystemAreaPointer (
+ IN CONST BOOLEAN DoCrcCheck,
+ OUT PDAT_AREA **AreaPtr
+ )
+{
+ PDAT_AREA *Area;
+ EFI_STATUS Status;
+
+ Area = (PDAT_AREA *) PcdGet32(PcdPlatformDataBaseAddress);
+
+ *AreaPtr = NULL;
+ Status = PDatLibValidateArea (Area, DoCrcCheck);
+ if (!EFI_ERROR(Status)) {
+ *AreaPtr = Area;
+ }
+ return Status;
+}
+
+/** Find platform data item.
+
+ @param[in] UserArea Platform Data Area to search
+ if == NULL then use system area.
+ @param[in] ItemId One of PDAT_ITEM_ID_XXXX constants
+ indicating item to find.
+ @param[in] DoCrcCheck Do CRC Check on area.
+ @param[out] ItemData Optional pointer to buffer to receive
+ Item Data, caller reponsible that buffer
+ is large enough.
+
+ @return pointer to PDAT_ITEM struct for found item.
+ @retval NULL if item not found or validate fails.
+**/
+PDAT_ITEM *
+EFIAPI
+PDatLibFindItem (
+ IN PDAT_AREA *UserArea, OPTIONAL
+ IN CONST UINT16 ItemId,
+ IN CONST BOOLEAN DoCrcCheck,
+ OUT VOID *ItemData OPTIONAL
+ )
+{
+ PDAT_ITEM *CurrItem;
+ PDAT_AREA *Area;
+ UINT8 *CurrMemLocation;
+ UINT8 *Limit;
+ EFI_STATUS Status;
+
+ if (UserArea == NULL) {
+ Status = PDatLibGetSystemAreaPointer (
+ DoCrcCheck,
+ &Area
+ );
+ ASSERT (Area != NULL);
+ } else {
+ Area = UserArea;
+ Status = PDatLibValidateArea (Area, DoCrcCheck);
+ }
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ CurrMemLocation = ((UINT8 *) Area) + sizeof (PDAT_AREA_HEADER);
+ Limit = ((UINT8 *) Area) + sizeof (PDAT_AREA_HEADER) + Area->Header.Length;
+ while (CurrMemLocation < Limit) {
+ CurrItem = (PDAT_ITEM *) CurrMemLocation;
+
+ if (CurrItem->Header.Identifier == ItemId) {
+
+ //
+ // Found Item, update optional outputs and return pointer to item.
+ //
+ if (ItemData != NULL) {
+ CopyMem (
+ ItemData,
+ (VOID *) &CurrItem->Data[0],
+ CurrItem->Header.Length
+ );
+ }
+ return CurrItem;
+ }
+ CurrMemLocation += (sizeof(PDAT_ITEM_HEADER) + CurrItem->Header.Length);
+ }
+
+ return NULL;
+}
+
+/** Find First Item using item id filter.
+
+ This routine will alway validate the platform data area (including CRC).
+
+ WARNING:
+ FindFirst / FindNext limited to item ids 0x0000 - 0x0003f.
+
+ @param[in] UserArea Platform Data Area to search
+ if == NULL then use system area.
+ @param[in] ItemIdFilter Filter of item types to search for.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+ @param[out] ItemData Optional pointer to buffer to receive
+ Item Data, caller reponsible that buffer
+ is large enough.
+
+ @return pointer to PDAT_ITEM struct for found item.
+ @retval NULL if item not found, area corrupt or reached end of platform data area.
+**/
+PDAT_ITEM *
+EFIAPI
+PDatLibFindFirstWithFilter (
+ IN PDAT_AREA *UserArea, OPTIONAL
+ IN CONST UINT64 ItemIdFilter,
+ IN OUT PDAT_LIB_FINDCONTEXT *FindContext,
+ OUT VOID *ItemData OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ if (UserArea == NULL) {
+ Status = PDatLibGetSystemAreaPointer (
+ TRUE,
+ &FindContext->Area
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ ASSERT (FindContext->Area != NULL);
+ } else {
+ FindContext->Area = UserArea;
+ }
+ FindContext->CurrMemLocation =
+ ((UINT8 *) FindContext->Area) + sizeof (PDAT_AREA_HEADER);
+
+ FindContext->Limit = FindContext->CurrMemLocation + FindContext->Area->Header.Length;
+
+ return FindNext (ItemIdFilter, FALSE, FindContext, ItemData);
+}
+
+/** Find next Item using item id filter.
+
+ WARNING:
+ FindFirst / FindNext limited to item ids 0x0000 - 0x0003f.
+
+ @param[in] ItemIdFilter Filter of item types to search for.
+ @param[in out] FindContext Pointer to caller allocated storage for
+ find context.
+ @param[out] ItemData Optional pointer to buffer to receive
+ Item Data, caller reponsible that buffer
+ is large enough.
+
+ @return pointer to PDAT_ITEM struct for found item.
+ @retval NULL if reached end of platform data area.
+**/
+PDAT_ITEM *
+EFIAPI
+PDatLibFindNextWithFilter (
+ IN CONST UINT64 ItemIdFilter,
+ IN OUT PDAT_LIB_FINDCONTEXT *FindContext,
+ OUT VOID *ItemData OPTIONAL
+ )
+{
+ return FindNext (ItemIdFilter, TRUE, FindContext, ItemData);
+}
+
+/** Copy platform data area and filter out specified items.
+
+ Only able to filter out item ids 0x0000 - 0x0003f.
+
+ @param[out] DestArea User allocated buffer to receive
+ SrcArea with ItemIdFilter items
+ removed.
+ @param[in] SrcArea Area to copy.
+ @param[in] ItemIdFilter Filter of items not to copy into DestArea.
+
+ @retval EFI_SUCCESS Operation success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval Others Unexpected error happened.
+**/
+EFI_STATUS
+EFIAPI
+PDatLibCopyAreaWithFilterOut (
+ OUT PDAT_AREA *DestArea,
+ IN PDAT_AREA *SrcArea,
+ IN CONST UINT64 ItemIdFilter
+ )
+{
+ EFI_STATUS Status;
+ PDAT_ITEM *Item;
+ PDAT_LIB_FINDCONTEXT PDatFindContext;
+ UINTN FilteredCount;
+ UINTN ItemTotalLen;
+ UINT8 *CurrMemLocation;
+
+ if (DestArea == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = PDatLibValidateArea (SrcArea, TRUE);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ Item = PDatLibFindFirstWithFilter (SrcArea, PDAT_FIND_ANY_ITEM_FILTER, &PDatFindContext, NULL);
+ FilteredCount = 0;
+ CopyMem (((UINT8 *) DestArea), ((UINT8 *) SrcArea), sizeof (PDAT_AREA_HEADER));
+ CurrMemLocation = ((UINT8 *) DestArea) + sizeof (PDAT_AREA_HEADER);
+ if (Item != NULL) {
+ do {
+ ItemTotalLen = sizeof(PDAT_ITEM_HEADER) + Item->Header.Length;
+ if (Item->Header.Identifier < 64) {
+ ///
+ /// Only ids < 64 can be filtered out.
+ ///
+ if (PDAT_IS_FILTER_MATCH (ItemIdFilter, Item->Header.Identifier)) {
+ DestArea->Header.Length -= ItemTotalLen;
+ FilteredCount++;
+ ItemTotalLen = 0;
+ }
+ }
+ if (ItemTotalLen > 0) {
+ CopyMem (CurrMemLocation, (UINT8 *) Item, ItemTotalLen);
+ CurrMemLocation += ItemTotalLen;
+ }
+ Item = PDatLibFindNextWithFilter(PDAT_FIND_ANY_ITEM_FILTER, &PDatFindContext, NULL);
+ } while (Item != NULL);
+ }
+ if (FilteredCount > 0) {
+ Status = PlatformCalculateCrc32 (
+ (UINT8 *) &DestArea->Body[0],
+ (UINTN) DestArea->Header.Length,
+ &DestArea->Header.Crc
+ );
+ }
+ return PDatLibValidateArea (DestArea, FALSE);
+}
diff --git a/QuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.inf b/QuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.inf
new file mode 100644
index 0000000..08d7976
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.inf
@@ -0,0 +1,73 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# PlatformDataLib.inf
+#
+# Abstract:
+#
+# Library producing routines to access items in Platform Data flash area.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformDataLib
+ FILE_GUID = 1C0A42C1-51A9-46c4-95BF-3E59E6DA6869
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformDataLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PlatformDataLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ PlatformHelperLib
+
+
+[FeaturePcd]
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformDataBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformDataMaxLen
diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/CommonHeader.h b/QuarkPlatformPkg/Library/PlatformHelperLib/CommonHeader.h
new file mode 100644
index 0000000..7363119
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformHelperLib/CommonHeader.h
@@ -0,0 +1,69 @@
+/**@file
+ Common header file shared by all source files in this component.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+#include <Uefi.h>
+#include <Guid/QuarkCapsuleGuid.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/PlatformDataLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Platform.h>
+#include "FlashLayout.h"
+#include <CommonIncludes.h>
+#include <QNCAccess.h>
+#include <QNCAccessLib.h>
+#include <IohAccess.h>
+
+#include <Library/PlatformHelperLib.h>
+
+//
+// Routines shared between souce modules in this component.
+//
+
+EFI_STATUS
+WriteFirstFreeSpiProtect (
+ IN CONST UINT32 PchRootComplexBar,
+ IN CONST UINT32 DirectValue,
+ IN CONST UINT32 BaseAddress,
+ IN CONST UINT32 Length,
+ OUT UINT32 *OffsetPtr
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/Crc32.c b/QuarkPlatformPkg/Library/PlatformHelperLib/Crc32.c
new file mode 100644
index 0000000..6c519ba
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformHelperLib/Crc32.c
@@ -0,0 +1,339 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Crc32.c
+
+Abstract:
+
+ CalcuateCrc32 routine.
+
+**/
+
+#include <Uefi.h>
+
+static UINT32 mCrcTable[256] = {
+ 0x00000000,
+ 0x77073096,
+ 0xEE0E612C,
+ 0x990951BA,
+ 0x076DC419,
+ 0x706AF48F,
+ 0xE963A535,
+ 0x9E6495A3,
+ 0x0EDB8832,
+ 0x79DCB8A4,
+ 0xE0D5E91E,
+ 0x97D2D988,
+ 0x09B64C2B,
+ 0x7EB17CBD,
+ 0xE7B82D07,
+ 0x90BF1D91,
+ 0x1DB71064,
+ 0x6AB020F2,
+ 0xF3B97148,
+ 0x84BE41DE,
+ 0x1ADAD47D,
+ 0x6DDDE4EB,
+ 0xF4D4B551,
+ 0x83D385C7,
+ 0x136C9856,
+ 0x646BA8C0,
+ 0xFD62F97A,
+ 0x8A65C9EC,
+ 0x14015C4F,
+ 0x63066CD9,
+ 0xFA0F3D63,
+ 0x8D080DF5,
+ 0x3B6E20C8,
+ 0x4C69105E,
+ 0xD56041E4,
+ 0xA2677172,
+ 0x3C03E4D1,
+ 0x4B04D447,
+ 0xD20D85FD,
+ 0xA50AB56B,
+ 0x35B5A8FA,
+ 0x42B2986C,
+ 0xDBBBC9D6,
+ 0xACBCF940,
+ 0x32D86CE3,
+ 0x45DF5C75,
+ 0xDCD60DCF,
+ 0xABD13D59,
+ 0x26D930AC,
+ 0x51DE003A,
+ 0xC8D75180,
+ 0xBFD06116,
+ 0x21B4F4B5,
+ 0x56B3C423,
+ 0xCFBA9599,
+ 0xB8BDA50F,
+ 0x2802B89E,
+ 0x5F058808,
+ 0xC60CD9B2,
+ 0xB10BE924,
+ 0x2F6F7C87,
+ 0x58684C11,
+ 0xC1611DAB,
+ 0xB6662D3D,
+ 0x76DC4190,
+ 0x01DB7106,
+ 0x98D220BC,
+ 0xEFD5102A,
+ 0x71B18589,
+ 0x06B6B51F,
+ 0x9FBFE4A5,
+ 0xE8B8D433,
+ 0x7807C9A2,
+ 0x0F00F934,
+ 0x9609A88E,
+ 0xE10E9818,
+ 0x7F6A0DBB,
+ 0x086D3D2D,
+ 0x91646C97,
+ 0xE6635C01,
+ 0x6B6B51F4,
+ 0x1C6C6162,
+ 0x856530D8,
+ 0xF262004E,
+ 0x6C0695ED,
+ 0x1B01A57B,
+ 0x8208F4C1,
+ 0xF50FC457,
+ 0x65B0D9C6,
+ 0x12B7E950,
+ 0x8BBEB8EA,
+ 0xFCB9887C,
+ 0x62DD1DDF,
+ 0x15DA2D49,
+ 0x8CD37CF3,
+ 0xFBD44C65,
+ 0x4DB26158,
+ 0x3AB551CE,
+ 0xA3BC0074,
+ 0xD4BB30E2,
+ 0x4ADFA541,
+ 0x3DD895D7,
+ 0xA4D1C46D,
+ 0xD3D6F4FB,
+ 0x4369E96A,
+ 0x346ED9FC,
+ 0xAD678846,
+ 0xDA60B8D0,
+ 0x44042D73,
+ 0x33031DE5,
+ 0xAA0A4C5F,
+ 0xDD0D7CC9,
+ 0x5005713C,
+ 0x270241AA,
+ 0xBE0B1010,
+ 0xC90C2086,
+ 0x5768B525,
+ 0x206F85B3,
+ 0xB966D409,
+ 0xCE61E49F,
+ 0x5EDEF90E,
+ 0x29D9C998,
+ 0xB0D09822,
+ 0xC7D7A8B4,
+ 0x59B33D17,
+ 0x2EB40D81,
+ 0xB7BD5C3B,
+ 0xC0BA6CAD,
+ 0xEDB88320,
+ 0x9ABFB3B6,
+ 0x03B6E20C,
+ 0x74B1D29A,
+ 0xEAD54739,
+ 0x9DD277AF,
+ 0x04DB2615,
+ 0x73DC1683,
+ 0xE3630B12,
+ 0x94643B84,
+ 0x0D6D6A3E,
+ 0x7A6A5AA8,
+ 0xE40ECF0B,
+ 0x9309FF9D,
+ 0x0A00AE27,
+ 0x7D079EB1,
+ 0xF00F9344,
+ 0x8708A3D2,
+ 0x1E01F268,
+ 0x6906C2FE,
+ 0xF762575D,
+ 0x806567CB,
+ 0x196C3671,
+ 0x6E6B06E7,
+ 0xFED41B76,
+ 0x89D32BE0,
+ 0x10DA7A5A,
+ 0x67DD4ACC,
+ 0xF9B9DF6F,
+ 0x8EBEEFF9,
+ 0x17B7BE43,
+ 0x60B08ED5,
+ 0xD6D6A3E8,
+ 0xA1D1937E,
+ 0x38D8C2C4,
+ 0x4FDFF252,
+ 0xD1BB67F1,
+ 0xA6BC5767,
+ 0x3FB506DD,
+ 0x48B2364B,
+ 0xD80D2BDA,
+ 0xAF0A1B4C,
+ 0x36034AF6,
+ 0x41047A60,
+ 0xDF60EFC3,
+ 0xA867DF55,
+ 0x316E8EEF,
+ 0x4669BE79,
+ 0xCB61B38C,
+ 0xBC66831A,
+ 0x256FD2A0,
+ 0x5268E236,
+ 0xCC0C7795,
+ 0xBB0B4703,
+ 0x220216B9,
+ 0x5505262F,
+ 0xC5BA3BBE,
+ 0xB2BD0B28,
+ 0x2BB45A92,
+ 0x5CB36A04,
+ 0xC2D7FFA7,
+ 0xB5D0CF31,
+ 0x2CD99E8B,
+ 0x5BDEAE1D,
+ 0x9B64C2B0,
+ 0xEC63F226,
+ 0x756AA39C,
+ 0x026D930A,
+ 0x9C0906A9,
+ 0xEB0E363F,
+ 0x72076785,
+ 0x05005713,
+ 0x95BF4A82,
+ 0xE2B87A14,
+ 0x7BB12BAE,
+ 0x0CB61B38,
+ 0x92D28E9B,
+ 0xE5D5BE0D,
+ 0x7CDCEFB7,
+ 0x0BDBDF21,
+ 0x86D3D2D4,
+ 0xF1D4E242,
+ 0x68DDB3F8,
+ 0x1FDA836E,
+ 0x81BE16CD,
+ 0xF6B9265B,
+ 0x6FB077E1,
+ 0x18B74777,
+ 0x88085AE6,
+ 0xFF0F6A70,
+ 0x66063BCA,
+ 0x11010B5C,
+ 0x8F659EFF,
+ 0xF862AE69,
+ 0x616BFFD3,
+ 0x166CCF45,
+ 0xA00AE278,
+ 0xD70DD2EE,
+ 0x4E048354,
+ 0x3903B3C2,
+ 0xA7672661,
+ 0xD06016F7,
+ 0x4969474D,
+ 0x3E6E77DB,
+ 0xAED16A4A,
+ 0xD9D65ADC,
+ 0x40DF0B66,
+ 0x37D83BF0,
+ 0xA9BCAE53,
+ 0xDEBB9EC5,
+ 0x47B2CF7F,
+ 0x30B5FFE9,
+ 0xBDBDF21C,
+ 0xCABAC28A,
+ 0x53B39330,
+ 0x24B4A3A6,
+ 0xBAD03605,
+ 0xCDD70693,
+ 0x54DE5729,
+ 0x23D967BF,
+ 0xB3667A2E,
+ 0xC4614AB8,
+ 0x5D681B02,
+ 0x2A6F2B94,
+ 0xB40BBE37,
+ 0xC30C8EA1,
+ 0x5A05DF1B,
+ 0x2D02EF8D
+};
+
+/**
+ The PlatformCalculateCrc32 routine.
+
+ @param Data The buffer contaning the data to be processed.
+ @param DataSize The size of data to be processed.
+ @param CrcOut A pointer to the caller allocated UINT32 that
+ on return contains the CRC32 checksum of Data.
+
+ @retval EFI_SUCCESS Calculation is successful.
+ @retval EFI_INVALID_PARAMETER Data / CrcOut = NULL, or DataSize = 0.
+ @retval EFI_NOT_FOUND Firmware volume file not found.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformCalculateCrc32 (
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN OUT UINT32 *CrcOut
+ )
+{
+ UINT32 Crc;
+ UINTN Index;
+ UINT8 *Ptr;
+
+ if ((DataSize == 0) || (Data == NULL) || (CrcOut == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Crc = 0xffffffff;
+ for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {
+ Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr];
+ }
+
+ *CrcOut = Crc ^ 0xffffffff;
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf b/QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf
new file mode 100644
index 0000000..bb82271
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf
@@ -0,0 +1,110 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# DxePlatformHelperLib.inf
+#
+# Abstract:
+#
+# Library producing helper routines for this platform.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxePlatformHelperLib
+ FILE_GUID = 02805010-2591-4ed3-827B-A218F34AE0D7
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformHelperLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ PlatformHelperLib.c
+ PlatformHelperDxe.c
+ Crc32.c
+ PlatformSecureBoot.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ BaseMemoryLib
+ SerialPortLib
+ IohLib
+ S3BootScriptLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ DxeServicesLib
+ HobLib
+ PlatformDataLib
+ IntelQNCLib
+
+[Protocols]
+ gEfiPlatformTypeProtocolGuid
+ gEfiSpiProtocolGuid
+ gEfiSmmSpiProtocolGuid
+ gSecureBootHelperProtocolGuid
+ gEfiSmmBase2ProtocolGuid
+
+[Guids]
+ gEfiGlobalVariableGuid
+ gEfiImageSecurityDatabaseGuid
+ gEfiQuarkCapsuleGuid
+ gQuarkVariableLockGuid
+
+[FeaturePcd]
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock
+ gQuarkPlatformTokenSpaceGuid.PcdSupportSecureBoot
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageSize
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformDataBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformDataMaxLen
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+
+[Pcd]
+ gQuarkPlatformTokenSpaceGuid.PcdPkX509File
+ gQuarkPlatformTokenSpaceGuid.PcdKekX509File
+ gQuarkPlatformTokenSpaceGuid.PcdKekRsa2048File
diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf b/QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf
new file mode 100644
index 0000000..c872a96
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf
@@ -0,0 +1,82 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# PeiPlatformHelperLib.inf
+#
+# Abstract:
+#
+# Library producing helper routines for this platform.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiPlatformHelperLib
+ FILE_GUID = 024D3127-7B60-48f4-A6FE-726E19CD4CEB
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformHelperLib|PEIM PEI_CORE SEC
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ PlatformHelperLib.c
+ PlatformHelperPei.c
+ Crc32.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ BaseMemoryLib
+ PeiServicesTablePointerLib
+ PeiServicesLib
+ SerialPortLib
+ IohLib
+
+[Guids]
+ gEfiQuarkCapsuleGuid
+
+[FeaturePcd]
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+ gQuarkPlatformTokenSpaceGuid.PcdEsramStage1Base
diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c
new file mode 100644
index 0000000..0483134
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c
@@ -0,0 +1,553 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformHelperDxe.c
+
+Abstract:
+
+ Implementation of helper routines for DXE enviroment.
+
+--*/
+
+#include <PiDxe.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <Protocol/PlatformType.h>
+#include <Protocol/SmmBase2.h>
+#include <Protocol/Spi.h>
+
+#include <Guid/QuarkVariableLock.h>
+
+#include "CommonHeader.h"
+
+//
+// Global variables.
+//
+EFI_SPI_PROTOCOL *mPlatHelpSpiProtocolRef = NULL;
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this component.
+//
+
+
+EFI_SPI_PROTOCOL *
+LocateSpiProtocol (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ )
+{
+ if (mPlatHelpSpiProtocolRef == NULL) {
+ if (Smst != NULL) {
+ Smst->SmmLocateProtocol (
+ &gEfiSmmSpiProtocolGuid,
+ NULL,
+ (VOID **) &mPlatHelpSpiProtocolRef
+ );
+ } else {
+ gBS->LocateProtocol (
+ &gEfiSpiProtocolGuid,
+ NULL,
+ (VOID **) &mPlatHelpSpiProtocolRef
+ );
+ }
+ ASSERT (mPlatHelpSpiProtocolRef != NULL);
+ }
+ return mPlatHelpSpiProtocolRef;
+}
+
+//
+// Routines exported by this source module.
+//
+
+/**
+ Find pointer to RAW data in Firmware volume file.
+
+ @param FvNameGuid Firmware volume to search. If == NULL search all.
+ @param FileNameGuid Firmware volume file to search for.
+ @param SectionData Pointer to RAW data section of found file.
+ @param SectionDataSize Pointer to UNITN to get size of RAW data.
+
+ @retval EFI_SUCCESS Raw Data found.
+ @retval EFI_INVALID_PARAMETER FileNameGuid == NULL.
+ @retval EFI_NOT_FOUND Firmware volume file not found.
+ @retval EFI_UNSUPPORTED Unsupported in current enviroment (PEI or DXE).
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFindFvFileRawDataSection (
+ IN CONST EFI_GUID *FvNameGuid OPTIONAL,
+ IN CONST EFI_GUID *FileNameGuid,
+ OUT VOID **SectionData,
+ OUT UINTN *SectionDataSize
+ )
+{
+ if (FileNameGuid == NULL || SectionData == NULL || SectionDataSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (FvNameGuid != NULL) {
+ return EFI_UNSUPPORTED; // Searching in specific FV unsupported in DXE.
+ }
+
+ return GetSectionFromAnyFv (FileNameGuid, EFI_SECTION_RAW, 0, SectionData, SectionDataSize);
+}
+
+/**
+ Find free spi protect register and write to it to protect a flash region.
+
+ @param DirectValue Value to directly write to register.
+ if DirectValue == 0 the use Base & Length below.
+ @param BaseAddress Base address of region in Flash Memory Map.
+ @param Length Length of region to protect.
+
+ @retval EFI_SUCCESS Free spi protect register found & written.
+ @retval EFI_NOT_FOUND Free Spi protect register not found.
+ @retval EFI_DEVICE_ERROR Unable to write to spi protect register.
+**/
+EFI_STATUS
+EFIAPI
+PlatformWriteFirstFreeSpiProtect (
+ IN CONST UINT32 DirectValue,
+ IN CONST UINT32 BaseAddress,
+ IN CONST UINT32 Length
+ )
+{
+ UINT32 FreeOffset;
+ UINT32 PchRootComplexBar;
+ EFI_STATUS Status;
+
+ PchRootComplexBar = QNC_RCRB_BASE;
+
+ Status = WriteFirstFreeSpiProtect (
+ PchRootComplexBar,
+ DirectValue,
+ BaseAddress,
+ Length,
+ &FreeOffset
+ );
+
+ if (!EFI_ERROR (Status)) {
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchRootComplexBar + FreeOffset),
+ 1,
+ (VOID *) (UINTN) (PchRootComplexBar + FreeOffset)
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Lock legacy SPI static configuration information.
+
+ Function will assert if unable to lock config.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockConfig (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_SPI_PROTOCOL *SpiProtocol;
+
+ //
+ // Enable lock of legacy SPI static configuration information.
+ //
+
+ SpiProtocol = LocateSpiProtocol (NULL); // This routine will not be called in SMM.
+ ASSERT_EFI_ERROR (SpiProtocol != NULL);
+ if (SpiProtocol != NULL) {
+ Status = SpiProtocol->Lock (SpiProtocol);
+
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Platform: Spi Config Locked Down\n"));
+ } else if (Status == EFI_ACCESS_DENIED) {
+ DEBUG ((EFI_D_INFO, "Platform: Spi Config already locked down\n"));
+ } else {
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+}
+
+/**
+ Lock regions and config of SPI flash given the policy for this platform.
+
+ Function will assert if unable to lock regions or config.
+
+ @param PreBootPolicy If TRUE do Pre Boot Flash Lock Policy.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockPolicy (
+ IN CONST BOOLEAN PreBootPolicy
+ )
+{
+ EFI_PLATFORM_TYPE_PROTOCOL *PlatformType;
+ EFI_STATUS Status;
+ UINT64 CpuAddressNvStorage;
+ UINT64 CpuAddressPlatformData;
+ UINT64 CpuAddressFixedRecovery;
+ UINT64 CpuAddressFlashDevice;
+ UINT64 SpiAddress;
+ EFI_BOOT_MODE BootMode;
+
+ BootMode = GetBootModeHob ();
+
+ Status = gBS->LocateProtocol (&gEfiPlatformTypeProtocolGuid, NULL, (VOID **) &PlatformType);
+ ASSERT_EFI_ERROR (Status);
+
+ CpuAddressFlashDevice = SIZE_4GB - ((UINT64) PlatformType->FlashDeviceSize);
+ DEBUG (
+ (EFI_D_INFO,
+ "Platform:FlashDeviceSize = 0x%08x Bytes\n",
+ (UINTN) PlatformType->FlashDeviceSize)
+ );
+
+ //
+ // Lock regions if Secure lock down.
+ //
+
+ if (FeaturePcdGet (PcdEnableSecureLock)) {
+
+ CpuAddressNvStorage = (UINT64) PcdGet32 (PcdFlashNvStorageBase);
+
+ //
+ // Lock from start of flash device up to Smi writable flash storage areas.
+ //
+ SpiAddress = 0;
+ if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice))) {
+ DEBUG (
+ (EFI_D_INFO,
+ "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
+ (UINTN) SpiAddress, (UINTN)(CpuAddressNvStorage - CpuAddressFlashDevice))
+ );
+ Status = PlatformWriteFirstFreeSpiProtect (
+ 0,
+ (UINT32) SpiAddress,
+ (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // Move Spi Address to after Smi writable flash storage areas.
+ //
+ SpiAddress = CpuAddressNvStorage - CpuAddressFlashDevice;
+ SpiAddress += ((UINT64) PcdGet32 (PcdFlashNvStorageSize)) + ((UINT64) FLASH_REGION_OEM_NV_STORAGE_SIZE);
+
+ //
+ // Lock from end of OEM area to end of flash part.
+ //
+ if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, PlatformType->FlashDeviceSize - ((UINT32) SpiAddress))) {
+ DEBUG (
+ (EFI_D_INFO,
+ "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
+ (UINTN) SpiAddress,
+ (UINTN) (PlatformType->FlashDeviceSize - ((UINT32) SpiAddress)))
+ );
+ ASSERT (SpiAddress < ((UINT64) PlatformType->FlashDeviceSize));
+ Status = PlatformWriteFirstFreeSpiProtect (
+ 0,
+ (UINT32) SpiAddress,
+ PlatformType->FlashDeviceSize - ((UINT32) SpiAddress)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+
+ //
+ // Lock Platform Data storage area
+ //
+
+ CpuAddressPlatformData = (UINT64) PcdGet32 (PcdPlatformDataBaseAddress);
+ SpiAddress = CpuAddressPlatformData - CpuAddressFlashDevice;
+ if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress,(UINT32) (PcdGet32 (PcdPlatformDataMaxLen)))) {
+ DEBUG (
+ (EFI_D_INFO,
+ "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
+ (UINTN) SpiAddress, (UINTN)(PcdGet32 (PcdPlatformDataMaxLen)))
+ );
+ Status = PlatformWriteFirstFreeSpiProtect (
+ 0,
+ (UINT32) SpiAddress,
+ (UINT32) (PcdGet32 (PcdPlatformDataMaxLen))
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Move Spi Address to beginning of Fixed Recovery area.
+ //
+
+ CpuAddressFixedRecovery = (UINT64) PcdGet32 (PcdFlashFvFixedStage1AreaBase);
+ SpiAddress = CpuAddressFixedRecovery - CpuAddressFlashDevice;
+
+ //
+ // Lock Fixed Recovery area
+ //
+
+ if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress,(UINT32) (PcdGet32 (PcdFlashFvFixedStage1AreaSize)))) {
+ DEBUG (
+ (EFI_D_INFO,
+ "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
+ (UINTN) SpiAddress,
+ (UINTN) (PcdGet32 (PcdFlashFvFixedStage1AreaSize)))
+ );
+ ASSERT (SpiAddress < ((UINT64) PlatformType->FlashDeviceSize));
+ Status = PlatformWriteFirstFreeSpiProtect (
+ 0,
+ (UINT32) SpiAddress,
+ (UINTN) (PcdGet32 (PcdFlashFvFixedStage1AreaSize))
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Move Spi Address to beginning of BOOTROM override area.
+ //
+
+ SpiAddress = FLASH_REGION_BOOTROM_OVERRIDE_BASE - CpuAddressFlashDevice;
+
+ //
+ // Lock BOOTROM override area.
+ //
+ if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress,FLASH_REGION_BOOTROM_OVERRIDE_MAX_SIZE)) {
+ DEBUG (
+ (EFI_D_INFO,
+ "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
+ (UINTN) SpiAddress,
+ (UINTN) FLASH_REGION_BOOTROM_OVERRIDE_MAX_SIZE)
+ );
+ ASSERT (SpiAddress < ((UINT64) PlatformType->FlashDeviceSize));
+ Status = PlatformWriteFirstFreeSpiProtect (
+ 0,
+ (UINT32) SpiAddress,
+ FLASH_REGION_BOOTROM_OVERRIDE_MAX_SIZE
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ //
+ // Always Lock flash config registers if about to boot a boot option
+ // else lock depending on boot mode.
+ //
+ if (PreBootPolicy || (BootMode != BOOT_ON_FLASH_UPDATE)) {
+ PlatformFlashLockConfig ();
+ }
+
+ //
+ // Enable Quark Variable lock if PreBootPolicy.
+ //
+ if (PreBootPolicy) {
+ Status = gRT->SetVariable (
+ QUARK_VARIABLE_LOCK_NAME,
+ &gQuarkVariableLockGuid,
+ 0,
+ 0,
+ (VOID *)NULL
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+/**
+ Erase and Write to platform flash.
+
+ Routine accesses one flash block at a time, each access consists
+ of an erase followed by a write of FLASH_BLOCK_SIZE. One or both
+ of DoErase & DoWrite params must be TRUE.
+
+ Limitations:-
+ CpuWriteAddress must be aligned to FLASH_BLOCK_SIZE.
+ DataSize must be a multiple of FLASH_BLOCK_SIZE.
+
+ @param Smst If != NULL then InSmm and use to locate
+ SpiProtocol.
+ @param CpuWriteAddress Address in CPU memory map of flash region.
+ @param Data The buffer containing the data to be written.
+ @param DataSize Amount of data to write.
+ @param DoErase Earse each block.
+ @param DoWrite Write to each block.
+
+ @retval EFI_SUCCESS Operation successful.
+ @retval EFI_NOT_READY Required resources not setup.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFlashEraseWrite (
+ IN VOID *Smst,
+ IN UINTN CpuWriteAddress,
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN BOOLEAN DoErase,
+ IN BOOLEAN DoWrite
+ )
+{
+ EFI_STATUS Status;
+ UINT64 CpuBaseAddress;
+ SPI_INIT_INFO *SpiInfo;
+ UINT8 *WriteBuf;
+ UINTN Index;
+ UINTN SpiWriteAddress;
+ EFI_SPI_PROTOCOL *SpiProtocol;
+
+ if (!DoErase && !DoWrite) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (DoWrite && Data == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((CpuWriteAddress % FLASH_BLOCK_SIZE) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((DataSize % FLASH_BLOCK_SIZE) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ SpiProtocol = LocateSpiProtocol ((EFI_SMM_SYSTEM_TABLE2 *)Smst);
+ if (SpiProtocol == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Find info to allow usage of SpiProtocol->Execute.
+ //
+ Status = SpiProtocol->Info (
+ SpiProtocol,
+ &SpiInfo
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ ASSERT (SpiInfo->InitTable != NULL);
+ ASSERT (SpiInfo->EraseOpcodeIndex < SPI_NUM_OPCODE);
+ ASSERT (SpiInfo->ProgramOpcodeIndex < SPI_NUM_OPCODE);
+
+ CpuBaseAddress = PcdGet32 (PcdFlashAreaBaseAddress) - (UINT32)SpiInfo->InitTable->BiosStartOffset;
+ ASSERT(CpuBaseAddress >= (SIZE_4GB - SIZE_8MB));
+ if (CpuWriteAddress < CpuBaseAddress) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ SpiWriteAddress = CpuWriteAddress - ((UINTN) CpuBaseAddress);
+ WriteBuf = Data;
+ DEBUG (
+ (EFI_D_INFO, "PlatformFlashWrite:SpiWriteAddress=%08x EraseIndex=%d WriteIndex=%d\n",
+ SpiWriteAddress,
+ (UINTN) SpiInfo->EraseOpcodeIndex,
+ (UINTN) SpiInfo->ProgramOpcodeIndex
+ ));
+ for (Index =0; Index < DataSize / FLASH_BLOCK_SIZE; Index++) {
+ if (DoErase) {
+ DEBUG (
+ (EFI_D_INFO, "PlatformFlashWrite:Erase[%04x] SpiWriteAddress=%08x\n",
+ Index,
+ SpiWriteAddress
+ ));
+ Status = SpiProtocol->Execute (
+ SpiProtocol,
+ SpiInfo->EraseOpcodeIndex,// OpcodeIndex
+ 0, // PrefixOpcodeIndex
+ FALSE, // DataCycle
+ TRUE, // Atomic
+ FALSE, // ShiftOut
+ SpiWriteAddress, // Address
+ 0, // Data Number
+ NULL,
+ EnumSpiRegionAll // SPI_REGION_TYPE
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+
+ if (DoWrite) {
+ DEBUG (
+ (EFI_D_INFO, "PlatformFlashWrite:Write[%04x] SpiWriteAddress=%08x\n",
+ Index,
+ SpiWriteAddress
+ ));
+ Status = SpiProtocol->Execute (
+ SpiProtocol,
+ SpiInfo->ProgramOpcodeIndex, // OpcodeIndex
+ 0, // PrefixOpcodeIndex
+ TRUE, // DataCycle
+ TRUE, // Atomic
+ TRUE, // ShiftOut
+ SpiWriteAddress, // Address
+ FLASH_BLOCK_SIZE, // Data Number
+ WriteBuf,
+ EnumSpiRegionAll
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ WriteBuf+=FLASH_BLOCK_SIZE;
+ }
+ SpiWriteAddress+=FLASH_BLOCK_SIZE;
+ }
+ return EFI_SUCCESS;
+}
+
+/** Check if System booted with recovery Boot Stage1 image.
+
+ @retval TRUE If system booted with recovery Boot Stage1 image.
+ @retval FALSE If system booted with normal stage1 image.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformIsBootWithRecoveryStage1 (
+ VOID
+ )
+{
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+}
diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperLib.c b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperLib.c
new file mode 100644
index 0000000..b485fb3
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperLib.c
@@ -0,0 +1,308 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformHelperLib.c
+
+Abstract:
+
+ Helper routines with common PEI / DXE implementation.
+
+--*/
+
+#include "CommonHeader.h"
+
+static CHAR16 *mPlatTypeNameTable[] = { EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION };
+static UINTN mPlatTypeNameTableLen = ((sizeof(mPlatTypeNameTable)) / sizeof (CHAR16 *));
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this source module.
+//
+
+//
+// Routines shared with other souce modules in this component.
+//
+
+EFI_STATUS
+WriteFirstFreeSpiProtect (
+ IN CONST UINT32 PchRootComplexBar,
+ IN CONST UINT32 DirectValue,
+ IN CONST UINT32 BaseAddress,
+ IN CONST UINT32 Length,
+ OUT UINT32 *OffsetPtr
+ )
+{
+ UINT32 RegVal;
+ UINT32 Offset;
+ UINT32 StepLen;
+
+ ASSERT (PchRootComplexBar > 0);
+
+ Offset = 0;
+ if (OffsetPtr != NULL) {
+ *OffsetPtr = Offset;
+ }
+ if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) == 0) {
+ Offset = R_QNC_RCRB_SPIPBR0;
+ } else {
+ if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR1) == 0) {
+ Offset = R_QNC_RCRB_SPIPBR1;
+ } else {
+ if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR2) == 0) {
+ Offset = R_QNC_RCRB_SPIPBR2;
+ }
+ }
+ }
+ if (Offset != 0) {
+ if (DirectValue == 0) {
+ StepLen = ALIGN_LENGTH (Length,0x1000); // Bring up to 4K boundary.
+ RegVal = BaseAddress + StepLen - 1;
+ RegVal &= 0x00FFF000; // Set EDS Protected Range Limit (PRL).
+ RegVal |= ((BaseAddress >> 12) & 0xfff); // or in EDS Protected Range Base (PRB).
+ } else {
+ RegVal = DirectValue;
+ }
+ //
+ // Enable protection.
+ //
+ RegVal |= B_QNC_RCRB_SPIPBRn_WPE;
+ MmioWrite32 (PchRootComplexBar + Offset, RegVal);
+ if (RegVal == MmioRead32 (PchRootComplexBar + Offset)) {
+ if (OffsetPtr != NULL) {
+ *OffsetPtr = Offset;
+ }
+ return EFI_SUCCESS;
+ }
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_NOT_FOUND;
+}
+
+//
+// Routines exported by this component.
+//
+
+/**
+ Read 8bit character from debug stream.
+
+ Block until character is read.
+
+ @return 8bit character read from debug stream.
+
+**/
+CHAR8
+EFIAPI
+PlatformDebugPortGetChar8 (
+ VOID
+ )
+{
+ CHAR8 Got;
+
+ do {
+ if (SerialPortPoll ()) {
+ if (SerialPortRead ((UINT8 *) &Got, 1) == 1) {
+ break;
+ }
+ }
+ } while (TRUE);
+
+ return Got;
+}
+
+/**
+ Return platform type string given platform type enum.
+
+ ASSERT if invalid platform type enum.
+
+ ASSERT if EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION has no entries.
+
+ ASSERT if EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION has no string for type.
+
+ @return string for platform type enum.
+
+**/
+CHAR16 *
+EFIAPI
+PlatformTypeString (
+ IN CONST UINT16 Type
+ )
+{
+ ASSERT ((EFI_PLATFORM_TYPE) Type < TypePlatformMax);
+ ASSERT (mPlatTypeNameTableLen > 0);
+ ASSERT ((UINTN) Type < mPlatTypeNameTableLen);
+
+ return mPlatTypeNameTable [Type];
+}
+
+/**
+ Those capsules supported by the firmwares.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+**/
+
+EFI_STATUS
+EFIAPI
+PlatformSupportCapsuleImage (
+ IN VOID *CapsuleHeader
+ )
+{
+ if (CompareGuid (&gEfiQuarkCapsuleGuid, &(((EFI_CAPSULE_HEADER *)CapsuleHeader)->CapsuleGuid))) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Clear SPI Protect registers.
+
+ @retval EFI_SUCCESS SPI protect registers cleared.
+ @retval EFI_ACCESS_DENIED Unable to clear SPI protect registers.
+**/
+
+EFI_STATUS
+EFIAPI
+PlatformClearSpiProtect (
+ VOID
+ )
+{
+ UINT32 PchRootComplexBar;
+
+ PchRootComplexBar = QNC_RCRB_BASE;
+ //
+ // Check if the SPI interface has been locked-down.
+ //
+ if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0, 0);
+ if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR1, 0);
+ if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR2, 0);
+ if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Determine if an SPI address range is protected.
+
+ @param SpiBaseAddress Base of SPI range.
+ @param Length Length of SPI range.
+
+ @retval TRUE Range is protected.
+ @retval FALSE Range is not protected.
+**/
+BOOLEAN
+EFIAPI
+PlatformIsSpiRangeProtected (
+ IN CONST UINT32 SpiBaseAddress,
+ IN CONST UINT32 Length
+ )
+{
+ UINT32 RegVal;
+ UINT32 Offset;
+ UINT32 Limit;
+ UINT32 ProtectedBase;
+ UINT32 ProtectedLimit;
+ UINT32 PchRootComplexBar;
+
+ PchRootComplexBar = QNC_RCRB_BASE;
+
+ if (Length > 0) {
+ Offset = R_QNC_RCRB_SPIPBR0;
+ Limit = SpiBaseAddress + (Length - 1);
+ do {
+ RegVal = MmioRead32 (PchRootComplexBar + Offset);
+ if ((RegVal & B_QNC_RCRB_SPIPBRn_WPE) != 0) {
+ ProtectedBase = (RegVal & 0xfff) << 12;
+ ProtectedLimit = (RegVal & 0x00fff000) + 0xfff;
+ if (SpiBaseAddress >= ProtectedBase && Limit <= ProtectedLimit) {
+ return TRUE;
+ }
+ }
+ if (Offset == R_QNC_RCRB_SPIPBR0) {
+ Offset = R_QNC_RCRB_SPIPBR1;
+ } else if (Offset == R_QNC_RCRB_SPIPBR1) {
+ Offset = R_QNC_RCRB_SPIPBR2;
+ } else {
+ break;
+ }
+ } while (TRUE);
+ }
+ return FALSE;
+}
+
+/**
+ Set Legacy GPIO Level
+
+ @param LevelRegOffset GPIO level register Offset from GPIO Base Address.
+ @param GpioNum GPIO bit to change.
+ @param HighLevel If TRUE set GPIO High else Set GPIO low.
+
+**/
+VOID
+EFIAPI
+PlatformLegacyGpioSetLevel (
+ IN CONST UINT32 LevelRegOffset,
+ IN CONST UINT32 GpioNum,
+ IN CONST BOOLEAN HighLevel
+ )
+{
+ UINT32 RegValue;
+ UINT32 GpioBaseAddress;
+ UINT32 GpioNumMask;
+
+ GpioBaseAddress = LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
+ ASSERT (GpioBaseAddress > 0);
+
+ RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);
+ GpioNumMask = (1 << GpioNum);
+ if (HighLevel) {
+ RegValue |= (GpioNumMask);
+ } else {
+ RegValue &= ~(GpioNumMask);
+ }
+ IoWrite32 (GpioBaseAddress + LevelRegOffset, RegValue);
+}
diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperPei.c b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperPei.c
new file mode 100644
index 0000000..7d9346b
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperPei.c
@@ -0,0 +1,241 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformHelperPei.c
+
+Abstract:
+
+ Implementation of Helper routines for PEI enviroment.
+
+--*/
+
+#include <PiPei.h>
+
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PeiServicesLib.h>
+
+#include "CommonHeader.h"
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this source module.
+//
+
+//
+// Routines exported by this source module.
+//
+
+/**
+ Find pointer to RAW data in Firmware volume file.
+
+ @param FvNameGuid Firmware volume to search. If == NULL search all.
+ @param FileNameGuid Firmware volume file to search for.
+ @param SectionData Pointer to RAW data section of found file.
+ @param SectionDataSize Pointer to UNITN to get size of RAW data.
+
+ @retval EFI_SUCCESS Raw Data found.
+ @retval EFI_INVALID_PARAMETER FileNameGuid == NULL.
+ @retval EFI_NOT_FOUND Firmware volume file not found.
+ @retval EFI_UNSUPPORTED Unsupported in current enviroment (PEI or DXE).
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFindFvFileRawDataSection (
+ IN CONST EFI_GUID *FvNameGuid OPTIONAL,
+ IN CONST EFI_GUID *FileNameGuid,
+ OUT VOID **SectionData,
+ OUT UINTN *SectionDataSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN Instance;
+ EFI_PEI_FV_HANDLE VolumeHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ EFI_SECTION_TYPE SearchType;
+ EFI_FV_INFO VolumeInfo;
+ EFI_FV_FILE_INFO FileInfo;
+ CONST EFI_PEI_SERVICES **PeiServices;
+
+ if (FileNameGuid == NULL || SectionData == NULL || SectionDataSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *SectionData = NULL;
+ *SectionDataSize = 0;
+
+ PeiServices = GetPeiServicesTablePointer ();
+ SearchType = EFI_SECTION_RAW;
+ for (Instance = 0; !EFI_ERROR(((*PeiServices)->FfsFindNextVolume (PeiServices, Instance, &VolumeHandle))); Instance++) {
+ if (FvNameGuid != NULL) {
+ Status = (*PeiServices)->FfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (!CompareGuid (FvNameGuid, &VolumeInfo.FvName)) {
+ continue;
+ }
+ }
+ Status = (*PeiServices)->FfsFindFileByName (FileNameGuid, VolumeHandle, &FileHandle);
+ if (!EFI_ERROR (Status)) {
+ Status = (*PeiServices)->FfsGetFileInfo (FileHandle, &FileInfo);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (IS_SECTION2(FileInfo.Buffer)) {
+ *SectionDataSize = SECTION2_SIZE(FileInfo.Buffer) - sizeof(EFI_COMMON_SECTION_HEADER2);
+ } else {
+ *SectionDataSize = SECTION_SIZE(FileInfo.Buffer) - sizeof(EFI_COMMON_SECTION_HEADER);
+ }
+ Status = (*PeiServices)->FfsFindSectionData (PeiServices, SearchType, FileHandle, SectionData);
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Find free spi protect register and write to it to protect a flash region.
+
+ @param DirectValue Value to directly write to register.
+ if DirectValue == 0 the use Base & Length below.
+ @param BaseAddress Base address of region in Flash Memory Map.
+ @param Length Length of region to protect.
+
+ @retval EFI_SUCCESS Free spi protect register found & written.
+ @retval EFI_NOT_FOUND Free Spi protect register not found.
+ @retval EFI_DEVICE_ERROR Unable to write to spi protect register.
+**/
+EFI_STATUS
+EFIAPI
+PlatformWriteFirstFreeSpiProtect (
+ IN CONST UINT32 DirectValue,
+ IN CONST UINT32 BaseAddress,
+ IN CONST UINT32 Length
+ )
+{
+ return WriteFirstFreeSpiProtect (
+ QNC_RCRB_BASE,
+ DirectValue,
+ BaseAddress,
+ Length,
+ NULL
+ );
+}
+
+/**
+ Lock legacy SPI static configuration information.
+
+ Function will assert if unable to lock config.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockConfig (
+ VOID
+ )
+{
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+}
+
+/**
+ Lock regions and config of SPI flash given the policy for this platform.
+
+ Function will assert if unable to lock regions or config.
+
+ @param PreBootPolicy If TRUE do Pre Boot Flash Lock Policy.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockPolicy (
+ IN CONST BOOLEAN PreBootPolicy
+ )
+{
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+}
+
+/** Auto provision Secure Boot Resources.
+
+ Provision from platform data, and only provision if PK public cert found.
+
+ @retval TRUE UEFI 2.3.1 Secure Boot enabled.
+ @retval FALSE UEFI 2.3.1 Secure Boot Disabled.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformAutoProvisionSecureBoot (
+ VOID
+ )
+{
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ return FALSE;
+}
+
+/** Check if System booted with recovery Boot Stage1 image.
+
+ @retval TRUE If system booted with recovery Boot Stage1 image.
+ @retval FALSE If system booted with normal stage1 image.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformIsBootWithRecoveryStage1 (
+ VOID
+ )
+{
+ BOOLEAN IsRecoveryBoot;
+ QUARK_EDKII_STAGE1_HEADER *Edk2ImageHeader;
+
+ Edk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) (PcdGet32 (PcdEsramStage1Base) + PcdGet32 (PcdFvSecurityHeaderSize));
+ switch ((UINT8)Edk2ImageHeader->ImageIndex & QUARK_STAGE1_IMAGE_TYPE_MASK) {
+ case QUARK_STAGE1_RECOVERY_IMAGE_TYPE:
+ //
+ // Recovery Boot
+ //
+ IsRecoveryBoot = TRUE;
+ break;
+ default:
+ //
+ // Normal Boot
+ //
+ IsRecoveryBoot = FALSE;
+ break;
+ }
+
+ return IsRecoveryBoot;
+}
diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformSecureBoot.c b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformSecureBoot.c
new file mode 100644
index 0000000..a29b87f
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformSecureBoot.c
@@ -0,0 +1,515 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformSecureBoot.c
+
+Abstract:
+
+ Implementation of platform specific UEFI SecureBoot functionality.
+
+--*/
+
+#include <PiDxe.h>
+
+#include <Guid/ImageAuthentication.h>
+#include <Guid/ImageAuthentication.h>
+
+#include <Protocol/Spi.h>
+#include <Protocol/SecureBootHelper.h>
+
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DxeServicesLib.h>
+
+#include "CommonHeader.h"
+
+STATIC EFI_GUID NullGuid = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this source module.
+//
+
+STATIC
+VOID
+DeleteAutoProvisionSecureBootItems (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PDAT_AREA *SysArea;
+ PDAT_AREA *NewArea;
+ UINT64 SecureBootItemFilter;
+ UINTN AreaSize;
+ UINTN BlockCount;
+
+ Status = PDatLibGetSystemAreaPointer (TRUE, &SysArea);
+
+ if (Status == EFI_NOT_FOUND) {
+ return; // Allowed not to have any platform data.
+ }
+ ASSERT_EFI_ERROR (Status); // Other errors not allowed.
+ ASSERT (SysArea != NULL);
+
+ //
+ /// Filter out SecureBoot Items from SysArea into NewArea.
+ //
+ AreaSize = sizeof(PDAT_AREA) + SysArea->Header.Length;
+ NewArea = (PDAT_AREA *) AllocateZeroPool (AreaSize + FLASH_BLOCK_SIZE);
+ ASSERT (NewArea != NULL);
+ SecureBootItemFilter = ((UINT64)
+ ((PDAT_ITEM_ID_MASK(PDAT_ITEM_ID_PK)) | (PDAT_ITEM_ID_MASK(PDAT_ITEM_ID_SB_RECORD))
+ ));
+ Status = PDatLibCopyAreaWithFilterOut (
+ NewArea,
+ SysArea,
+ SecureBootItemFilter
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (NewArea->Header.Length <= SysArea->Header.Length);
+
+ //
+ // Get number of Flash Blocks to Write.
+ //
+ AreaSize = sizeof(PDAT_AREA) + NewArea->Header.Length;
+ BlockCount = (AreaSize / FLASH_BLOCK_SIZE);
+ if ((AreaSize % FLASH_BLOCK_SIZE) != 0) {
+ BlockCount++;
+ }
+
+ //
+ // Write NewArea to Flash.
+ //
+ Status = PlatformFlashEraseWrite (
+ NULL,
+ (UINTN) PcdGet32(PcdPlatformDataBaseAddress),
+ (UINT8 *) NewArea,
+ BlockCount * FLASH_BLOCK_SIZE,
+ TRUE,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ FreePool (NewArea);
+}
+
+STATIC
+UINT8 *
+FindPkCert (
+ OUT UINTN *CertSizePtr
+ )
+{
+ EFI_STATUS Status;
+ PDAT_AREA *Area;
+ PDAT_ITEM *PKItem;
+ EFI_GUID *PkX509File;
+ UINT8 *CertData;
+
+ ASSERT (CertSizePtr != NULL);
+ CertData = NULL;
+
+ //
+ // Try find Pk certificate in platform data first.
+ //
+ Status = PDatLibGetSystemAreaPointer (TRUE, &Area);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((EFI_D_INFO, "AutoProvisionSecureBoot: System Platform Data Area Signature not found.\n"));
+ } else {
+ DEBUG ((EFI_D_ERROR, "AutoProvisionSecureBoot: System Platform Data Area get failed error = %r.\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ PKItem = PDatLibFindItem (Area, PDAT_ITEM_ID_PK, FALSE, NULL);
+
+ if (PKItem) {
+ ASSERT (PKItem->Header.Length > 0);
+ *CertSizePtr = PKItem->Header.Length;
+ return PKItem->Data;
+ }
+ }
+ DEBUG ((EFI_D_INFO, "AutoProvisionSecureBoot: PK X509 Public Cert not found in PDAT\n"));
+
+ //
+ // Finally check to see if cert in Firmware volumes.
+ //
+ PkX509File = PcdGetPtr(PcdPkX509File);
+ if (CompareGuid (&NullGuid, PkX509File) == FALSE) {
+ Status = PlatformFindFvFileRawDataSection (
+ NULL,
+ PkX509File,
+ (VOID **) &CertData,
+ CertSizePtr
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_NOT_FOUND) {
+ ASSERT_EFI_ERROR (Status);
+ CertData = NULL;
+ }
+ } else {
+ ASSERT (CertData != NULL && *CertSizePtr > 0);
+ }
+ }
+
+ return CertData;
+}
+
+STATIC
+VOID
+ProvisionFVRecords (
+ IN SECUREBOOT_HELPER_PROTOCOL *SecureBootHelperProtocol
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID *KekX509File;
+ EFI_GUID *KekRsa2048File;
+ UINT8 *CertData;
+ UINTN CertSize;
+
+ DEBUG ((EFI_D_INFO, ">>ProvisionFVRecords\n"));
+ KekX509File = PcdGetPtr(PcdKekX509File);
+ if (CompareGuid (&NullGuid, KekX509File) == FALSE) {
+ Status = PlatformFindFvFileRawDataSection (
+ NULL,
+ KekX509File,
+ (VOID **) &CertData,
+ &CertSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_NOT_FOUND) {
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ ASSERT (CertData != NULL && CertSize > 0);
+ DEBUG ((EFI_D_INFO, "Enroll X509 Cert into KEK 0x%04x:%g\n", CertSize, KekX509File));
+ Status = SecureBootHelperProtocol->SetupEnrollX509 (
+ SecureBootHelperProtocol,
+ KEKStore,
+ NULL,
+ CertData,
+ CertSize,
+ KekX509File
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ KekRsa2048File = PcdGetPtr(PcdKekRsa2048File);
+ if (CompareGuid (&NullGuid, KekRsa2048File) == FALSE) {
+ Status = PlatformFindFvFileRawDataSection (
+ NULL,
+ KekRsa2048File,
+ (VOID **) &CertData,
+ &CertSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_NOT_FOUND) {
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ ASSERT (CertData != NULL && CertSize > 0);
+ DEBUG ((EFI_D_INFO, "Enroll Rsa2048 storing file (*.pbk) into KEK database 0x%04x:%g\n", CertSize, KekRsa2048File));
+ Status = SecureBootHelperProtocol->SetupEnrollKekRsa2048 (
+ SecureBootHelperProtocol,
+ NULL,
+ CertData,
+ CertSize,
+ KekRsa2048File
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ DEBUG ((EFI_D_INFO, "<<ProvisionFVRecords\n"));
+}
+
+STATIC
+VOID
+ProvisionPlatformDataRecords (
+ IN SECUREBOOT_HELPER_PROTOCOL *SecureBootHelperProtocol
+ )
+{
+ EFI_STATUS Status;
+ PDAT_ITEM *CurrItem;
+ PDAT_LIB_FINDCONTEXT PDatFindContext;
+ SECUREBOOT_STORE_TYPE StoreType;
+ EFI_GUID *SignatureOwner;
+ PDAT_SB_PAYLOAD_HEADER *SbHeader;
+ UINT8 *CertData;
+ UINTN CertSize;
+
+ DEBUG ((EFI_D_INFO, ">>ProvisionPlatformDataRecords\n"));
+
+ CurrItem = PDatLibFindFirstWithFilter (
+ NULL,
+ PDAT_ITEM_ID_MASK (PDAT_ITEM_ID_SB_RECORD),
+ &PDatFindContext,
+ NULL
+ );
+
+ if (CurrItem == NULL) {
+ return; // No records do nothing.
+ }
+ DEBUG ((EFI_D_INFO, "ProvisionPlatformDataRecords: Items of id '0x%04x' found to provision\n", (UINTN) PDAT_ITEM_ID_SB_RECORD ));
+ do {
+ ASSERT (CurrItem->Header.Length > (sizeof(SbHeader) + 1));
+ SbHeader = (PDAT_SB_PAYLOAD_HEADER *) CurrItem->Data;
+ StoreType = (SECUREBOOT_STORE_TYPE) SbHeader->StoreType;
+ CertData = &CurrItem->Data[sizeof(SbHeader)];
+ CertSize = CurrItem->Header.Length - sizeof(SbHeader);
+ if ((SbHeader->Flags & PDAT_SB_FLAG_HAVE_GUID) != 0) {
+ ASSERT (CurrItem->Header.Length > (sizeof(PDAT_SB_PAYLOAD_HEADER) + sizeof(EFI_GUID) + 1));
+ SignatureOwner = (EFI_GUID *) CertData;
+ CertData += sizeof(EFI_GUID);
+ CertSize -= sizeof(EFI_GUID);
+ } else {
+ SignatureOwner = NULL;
+ }
+ DEBUG ((
+ EFI_D_INFO, "SbRec TotLen '0x%04x' Store '%02x' Type '%02x' Flags '0x%04x' GUID '%g'\n",
+ CurrItem->Header.Length,
+ StoreType,
+ SbHeader->CertType,
+ SbHeader->Flags,
+ SignatureOwner
+ ));
+
+ if (SbHeader->CertType == PDAT_SB_CERT_TYPE_X509) {
+ ASSERT ((StoreType == DBStore) || (StoreType == KEKStore) || (StoreType == DBXStore));
+ Status = SecureBootHelperProtocol->SetupEnrollX509 (
+ SecureBootHelperProtocol,
+ StoreType,
+ NULL,
+ CertData,
+ CertSize,
+ SignatureOwner
+ );
+ } else if (SbHeader->CertType == PDAT_SB_CERT_TYPE_SHA256) {
+ ASSERT ((StoreType == DBStore) || (StoreType == DBXStore));
+ Status = SecureBootHelperProtocol->SetupEnrollImageSignature (
+ SecureBootHelperProtocol,
+ StoreType,
+ NULL,
+ CertData,
+ CertSize,
+ SignatureOwner
+ );
+ } else if (SbHeader->CertType == PDAT_SB_CERT_TYPE_RSA2048) {
+ ASSERT (StoreType == KEKStore);
+ Status = SecureBootHelperProtocol->SetupEnrollKekRsa2048 (
+ SecureBootHelperProtocol,
+ NULL,
+ CertData,
+ CertSize,
+ SignatureOwner
+ );
+ } else {
+ DEBUG ((EFI_D_ERROR, "ProvisionPlatformDataRecords: Unsupported Cert Type = '%d'.\n", (UINTN) SbHeader->CertType));
+ Status = EFI_UNSUPPORTED;
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ CurrItem = PDatLibFindNextWithFilter (
+ PDAT_ITEM_ID_MASK (PDAT_ITEM_ID_SB_RECORD),
+ &PDatFindContext,
+ NULL
+ );
+ } while (CurrItem != NULL);
+
+ DEBUG ((EFI_D_INFO, "<<ProvisionPlatformDataRecords\n"));
+}
+
+//
+// Routines exported by this source module.
+//
+
+/** Auto provision Secure Boot Resources.
+
+ Provision from platform data, and only provision if PK public cert found.
+
+ @retval TRUE UEFI 2.3.1 Secure Boot enabled.
+ @retval FALSE UEFI 2.3.1 Secure Boot Disabled.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformAutoProvisionSecureBoot (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ SECUREBOOT_HELPER_PROTOCOL *SecureBootHelperProtocol;
+ UINT8 *PkX509Data;
+ UINTN PkX509DataSize;
+ BOOLEAN SecureBootEnabled;
+
+ SecureBootEnabled = FALSE;
+
+ if(FeaturePcdGet (PcdSupportSecureBoot)) {
+ Status = gBS->LocateProtocol(
+ &gSecureBootHelperProtocolGuid,
+ NULL,
+ (VOID**) &SecureBootHelperProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ SecureBootEnabled = SecureBootHelperProtocol->IsSecureBootEnabled (
+ SecureBootHelperProtocol
+ );
+ if (SecureBootEnabled) {
+ DEBUG ((EFI_D_INFO, "AutoProvisionSecureBoot: System provisioned, nothing to do\n"));
+ } else {
+ PkX509Data = FindPkCert (&PkX509DataSize);
+ if (PkX509Data == NULL) {
+ DEBUG ((EFI_D_INFO, "AutoProvisionSecureBoot: PK X509 Public Cert not found, do nothing\n"));
+ } else {
+
+ //
+ // Provision auto provisiong records stored in platform data and FVs.
+ //
+ ProvisionPlatformDataRecords (SecureBootHelperProtocol);
+ ProvisionFVRecords (SecureBootHelperProtocol);
+
+ //
+ // Before enrolling PK insure Db & Dbx exist (if they do not exist
+ // create a auth. var with a null cert).
+ //
+ Status = SecureBootHelperProtocol->SetupCreateEmptyDbDbxIfNotExist (
+ SecureBootHelperProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Now enable secure boot by enrolling PK public cert.
+ //
+ Status = SecureBootHelperProtocol->SetupEnrollX509 (
+ SecureBootHelperProtocol,
+ PKStore,
+ NULL,
+ PkX509Data,
+ PkX509DataSize,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SecureBootEnabled = SecureBootHelperProtocol->IsSecureBootEnabled (
+ SecureBootHelperProtocol
+ );
+ ASSERT (SecureBootEnabled);
+
+ PlatformValidateSecureBootVars ();
+
+ DeleteAutoProvisionSecureBootItems ();
+ }
+ }
+ }
+ return SecureBootEnabled;
+}
+
+/** Validate Secure boot variables setup correctly for this platform.
+
+ ASSERT if problem found.
+ Only validate if PcdSupportSecureBoot AND SecureBootEnabled.
+
+**/
+VOID
+EFIAPI
+PlatformValidateSecureBootVars (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ SECUREBOOT_VARIABLE_STATS Stats;
+ BOOLEAN SecureBootEnabled;
+ SECUREBOOT_HELPER_PROTOCOL *SecureBootHelperProtocol;
+
+ //
+ // Only validate if PcdSupportSecureBoot AND SecureBootEnabled.
+ //
+ if(FeaturePcdGet (PcdSupportSecureBoot)) {
+ Status = gBS->LocateProtocol(
+ &gSecureBootHelperProtocolGuid,
+ NULL,
+ (VOID**) &SecureBootHelperProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ SecureBootEnabled = SecureBootHelperProtocol->IsSecureBootEnabled (
+ SecureBootHelperProtocol
+ );
+ if (SecureBootEnabled) {
+ Status = SecureBootHelperProtocol->GetSecureBootVarStats (
+ SecureBootHelperProtocol,
+ &Stats
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // For this platform all cert vars need to be enrolled with
+ // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute and
+ // KEK must have a X509 or Rsa2048 cert.
+ //
+ DEBUG (
+ (EFI_D_INFO, "ValidateSecureBoot: Enrolled pk:kek:db:dbx %d:%d:%d:%d\n",
+ Stats.PkEnrolled,
+ Stats.KekEnrolled,
+ Stats.DbEnrolled,
+ Stats.DbxEnrolled
+ ));
+ ASSERT (Stats.PkEnrolled && Stats.KekEnrolled && Stats.DbEnrolled && Stats.DbxEnrolled);
+ DEBUG (
+ (EFI_D_INFO, "ValidateSecureBoot: Attributes pk:kek:db:dbx 0x%08x:0x%08x:0x%08x:0x%08x\n",
+ Stats.PkAttributes,
+ Stats.KekAttributes,
+ Stats.DbAttributes,
+ Stats.DbxAttributes
+ ));
+ ASSERT (
+ ((Stats.PkAttributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&
+ ((Stats.KekAttributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&
+ ((Stats.DbAttributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&
+ ((Stats.DbxAttributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0)
+ );
+ DEBUG (
+ (EFI_D_INFO, "ValidateSecureBoot: KekCertCounts X509:Rsa2048 %d:%d\n",
+ Stats.KekX509CertCount,
+ Stats.KekRsa2048CertCount
+ ));
+ ASSERT (Stats.KekX509CertCount > 0 || Stats.KekRsa2048CertCount > 0);
+ }
+ }
+}
diff --git a/QuarkPlatformPkg/Library/PlatformPcieHelperLib/CommonHeader.h b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/CommonHeader.h
new file mode 100644
index 0000000..616c240
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/CommonHeader.h
@@ -0,0 +1,92 @@
+/**@file
+ Common header file shared by all source files in this component.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/IntelQNCLib.h>
+#include <QNCAccessLib.h>
+#include <IntelQNCRegs.h>
+#include <IntelQNCConfig.h>
+#include <Pcal9555.h>
+#include <Platform.h>
+#include <PlatformBoards.h>
+
+#include <Library/PlatformPcieHelperLib.h>
+
+//
+// Routines shared between souce modules in this component.
+//
+
+VOID
+EFIAPI
+PlatformPcieErratas (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+SocUnitEarlyInitialisation (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+SocUnitReleasePcieControllerPreWaitPllLock (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+EFI_STATUS
+EFIAPI
+SocUnitReleasePcieControllerPostPllLock (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+VOID
+EFIAPI
+GalileoFabEPERSTAssert (
+ VOID
+ );
+
+VOID
+EFIAPI
+GalileoFabEPERSTDeAssert (
+ VOID
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Library/PlatformPcieHelperLib/DxePlatformPcieHelperLib.inf b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/DxePlatformPcieHelperLib.inf
new file mode 100644
index 0000000..10faef7
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/DxePlatformPcieHelperLib.inf
@@ -0,0 +1,83 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# DxePlatformPcieHelperLib.inf
+#
+# Abstract:
+#
+# Library producing Pci express helper routines for DXE enviroment.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxePlatformPcieHelperLib
+ FILE_GUID = 0AEA3B34-2BC9-4fe7-98F3-6F9D963A28E1
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformPcieHelperLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ PlatformPcieHelperLib.c
+ SocUnit.c
+ PlatformPcieHelperDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ IoLib
+ DebugLib
+ TimerLib
+ QNCAccessLib
+ IntelQNCLib
+ UefiLib
+
+[Protocols]
+ gEfiI2CHcProtocolGuid
+
+[Guids]
+
+[FeaturePcd]
+
+[FixedPcd]
diff --git a/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PeiPlatformPcieHelperLib.inf b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PeiPlatformPcieHelperLib.inf
new file mode 100644
index 0000000..5c30749
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PeiPlatformPcieHelperLib.inf
@@ -0,0 +1,79 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# PeiPlatformPcieHelperLib.inf
+#
+# Abstract:
+#
+# Library producing Pci Express Helper routines for PEI enviroment.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiPlatformPcieHelperLib
+ FILE_GUID = C153F460-5D8A-4d44-83BB-A8AF5CEF132C
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformPcieHelperLib|PEIM PEI_CORE SEC
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ PlatformPcieHelperLib.c
+ SocUnit.c
+ PlatformPcieHelperPei.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ IoLib
+ DebugLib
+ TimerLib
+ QNCAccessLib
+ IntelQNCLib
+
+[Guids]
+
+[FeaturePcd]
+
+[FixedPcd]
diff --git a/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperDxe.c b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperDxe.c
new file mode 100644
index 0000000..ed3ff9d
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperDxe.c
@@ -0,0 +1,198 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformPcieHelperDxe.c
+
+Abstract:
+
+ Implementation of Pci express helper routines for DXE enviroment.
+
+--*/
+
+#include <PiDxe.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/PlatformType.h>
+#include <Protocol/I2CHc.h>
+
+#include "CommonHeader.h"
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this component.
+//
+
+/**
+ Set the level of Pcal9555 IO Expander GPIO high or low.
+
+ No error returned. Function asserts if unable to address io expander.
+ Expected to be used with on board devices.
+
+ @param I2cBus I2c Host controller protocol.
+ @param Pcal9555SlaveAddr I2c Slave address of Pcal9555 Io Expander.
+ @param GpioNum Gpio to change values 0-7 for Port0 and 8-15
+ for Port1.
+ @param HighLevel If TRUE set pin high else set pin low.
+
+**/
+STATIC
+VOID
+Pcal9555GpioSetLevel (
+ IN EFI_I2C_HC_PROTOCOL *I2cBus,
+ IN CONST UINTN Pcal9555SlaveAddr,
+ IN CONST UINT16 GpioNum,
+ IN CONST BOOLEAN HighLevel
+ )
+{
+ EFI_STATUS Status;
+ UINTN ReadLength;
+ UINTN WriteLength;
+ UINT8 Data[2];
+ EFI_I2C_DEVICE_ADDRESS I2cDeviceAddr;
+ EFI_I2C_ADDR_MODE I2cAddrMode;
+ UINT8 *RegValuePtr;
+ UINT8 GpioNumMask;
+ UINT8 SubAddr;
+
+ ASSERT (I2cBus != NULL);
+
+ I2cDeviceAddr.I2CDeviceAddress = Pcal9555SlaveAddr;
+ I2cAddrMode = EfiI2CSevenBitAddrMode;
+
+ if (GpioNum < 8) {
+ SubAddr = PCAL9555_REG_OUT_PORT0;
+ GpioNumMask = (UINT8) (1 << GpioNum);
+ } else {
+ SubAddr = PCAL9555_REG_OUT_PORT0 + 1;
+ GpioNumMask = (UINT8) (1 << (GpioNum - 8));
+ }
+
+ //
+ // Output port value always at 2nd byte in Data variable.
+ //
+ RegValuePtr = &Data[1];
+
+ //
+ // On read entry sub address at 2nd byte, on read exit output
+ // port value in 2nd byte.
+ //
+ Data[1] = SubAddr;
+ WriteLength = 1;
+ ReadLength = 1;
+ Status = I2cBus->ReadMultipleByte (
+ I2cBus,
+ I2cDeviceAddr,
+ I2cAddrMode,
+ &WriteLength,
+ &ReadLength,
+ &Data[1]
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Adjust output port value given callers request.
+ //
+ if (HighLevel) {
+ *RegValuePtr = *RegValuePtr | GpioNumMask;
+ } else {
+ *RegValuePtr = *RegValuePtr & ~(GpioNumMask);
+ }
+
+ //
+ // Update register. Sub address at 1st byte, value at 2nd byte.
+ //
+ WriteLength = 2;
+ Data[0] = SubAddr;
+ Status = I2cBus->WriteMultipleByte (
+ I2cBus,
+ I2cDeviceAddr,
+ I2cAddrMode,
+ &WriteLength,
+ Data
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+//
+// Routines exported by this source module.
+//
+
+/**
+ Galileo FabE assert PCI express PERST# signal.
+
+**/
+VOID
+EFIAPI
+GalileoFabEPERSTAssert (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_I2C_HC_PROTOCOL *I2cBus;
+
+ Status = gBS->LocateProtocol (&gEfiI2CHcProtocolGuid, NULL, (VOID **) &I2cBus);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Inverter after pin on GalileoGen2 so assert signal with high gpio value.
+ //
+ Pcal9555GpioSetLevel (I2cBus, PCAL9555_GALILEO_GEN2_7BIT_SLAVE_ADDR, PCAL9555_GALILEO_GEN2_PERST_GPIO, TRUE);
+}
+
+/**
+ Galileo FabE de assert PCI express PERST# signal.
+
+**/
+VOID
+EFIAPI
+GalileoFabEPERSTDeAssert (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_I2C_HC_PROTOCOL *I2cBus;
+
+ Status = gBS->LocateProtocol (&gEfiI2CHcProtocolGuid, NULL, (VOID **) &I2cBus);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Inverter after pin on GalileoFabE so de-assert signal with low gpio value.
+ //
+ Pcal9555GpioSetLevel (I2cBus, PCAL9555_GALILEO_GEN2_7BIT_SLAVE_ADDR, PCAL9555_GALILEO_GEN2_PERST_GPIO, FALSE);
+}
diff --git a/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.c b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.c
new file mode 100644
index 0000000..30ae691
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.c
@@ -0,0 +1,143 @@
+/** @file
+ Platform Pcie Helper Lib.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+
+//
+// Routines local to this source module.
+//
+STATIC
+VOID
+LegacyGpioSetLevel (
+ IN CONST UINT32 LevelRegOffset,
+ IN CONST UINT32 GpioNum,
+ IN CONST BOOLEAN HighLevel
+ )
+{
+ UINT32 RegValue;
+ UINT32 GpioBaseAddress;
+ UINT32 GpioNumMask;
+
+ GpioBaseAddress = LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
+ ASSERT (GpioBaseAddress > 0);
+
+ RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);
+ GpioNumMask = (1 << GpioNum);
+ if (HighLevel) {
+ RegValue |= (GpioNumMask);
+ } else {
+ RegValue &= ~(GpioNumMask);
+ }
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL, RegValue);
+}
+
+//
+// Routines exported by this component.
+//
+
+/**
+ Platform assert PCI express PERST# signal.
+
+ @param PlatformType See EFI_PLATFORM_TYPE enum definitions.
+
+**/
+VOID
+EFIAPI
+PlatformPERSTAssert (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+{
+ if (PlatformType == GalileoFabE) {
+ GalileoFabEPERSTAssert ();
+ } else if (PlatformType == GalileoGen2) {
+ LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_GEN2_PCIEXP_PERST_RESUMEWELL_GPIO, FALSE);
+ } else {
+ LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, PCIEXP_PERST_RESUMEWELL_GPIO, FALSE);
+ }
+}
+
+/**
+ Platform de assert PCI express PERST# signal.
+
+ @param PlatformType See EFI_PLATFORM_TYPE enum definitions.
+
+**/
+VOID
+EFIAPI
+PlatformPERSTDeAssert (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+{
+ if (PlatformType == GalileoFabE) {
+ GalileoFabEPERSTDeAssert ();
+ } else if (PlatformType == GalileoGen2) {
+ LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_GEN2_PCIEXP_PERST_RESUMEWELL_GPIO, TRUE);
+ } else {
+ LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, PCIEXP_PERST_RESUMEWELL_GPIO, TRUE);
+ }
+}
+
+/** Early initialisation of the PCIe controller.
+
+ @param PlatformType See EFI_PLATFORM_TYPE enum definitions.
+
+ @retval EFI_SUCCESS Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPciExpressEarlyInit (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+{
+
+ //
+ // Release and wait for PCI controller to come out of reset.
+ //
+ SocUnitReleasePcieControllerPreWaitPllLock (PlatformType);
+ MicroSecondDelay (PCIEXP_DELAY_US_WAIT_PLL_LOCK);
+ SocUnitReleasePcieControllerPostPllLock (PlatformType);
+
+ //
+ // Early PCIe initialisation
+ //
+ SocUnitEarlyInitialisation ();
+
+ //
+ // Do North cluster early PCIe init.
+ //
+ PciExpressEarlyInit ();
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperPei.c b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperPei.c
new file mode 100644
index 0000000..e06a203
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperPei.c
@@ -0,0 +1,81 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformPcieHelperPei.c
+
+Abstract:
+
+ Implementation of Pci Express Helper routines for PEI enviroment.
+
+--*/
+
+#include <PiPei.h>
+
+#include "CommonHeader.h"
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this source module.
+//
+
+//
+// Routines exported by this source module.
+//
+
+/**
+ Galileo FabE assert PCI express PERST# signal.
+
+**/
+VOID
+EFIAPI
+GalileoFabEPERSTAssert (
+ VOID
+ )
+{
+ // Not implemented for PEI.
+}
+
+/**
+ Galileo FabE de assert PCI express PERST# signal.
+
+**/
+VOID
+EFIAPI
+GalileoFabEPERSTDeAssert (
+ VOID
+ )
+{
+ // Not implemented for PEI.
+}
diff --git a/QuarkPlatformPkg/Library/PlatformPcieHelperLib/SocUnit.c b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/SocUnit.c
new file mode 100644
index 0000000..9ce63eb
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/SocUnit.c
@@ -0,0 +1,149 @@
+/** @file
+ System On Chip Unit (SOCUnit) routines.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+
+/** Early initialisation of the SOC Unit
+
+ @retval EFI_SUCCESS Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+SocUnitEarlyInitialisation (
+ VOID
+ )
+{
+ UINT32 NewValue;
+
+ //
+ // Set the mixer load resistance
+ //
+ NewValue = QNCPortIORead (QUARK_SC_PCIE_AFE_SB_PORT_ID, QUARK_PCIE_AFE_PCIE_RXPICTRL0_L0);
+ NewValue &= OCFGPIMIXLOAD_1_0_MASK;
+ QNCPortIOWrite (QUARK_SC_PCIE_AFE_SB_PORT_ID, QUARK_PCIE_AFE_PCIE_RXPICTRL0_L0, NewValue);
+
+ NewValue = QNCPortIORead (QUARK_SC_PCIE_AFE_SB_PORT_ID, QUARK_PCIE_AFE_PCIE_RXPICTRL0_L1);
+ NewValue &= OCFGPIMIXLOAD_1_0_MASK;
+ QNCPortIOWrite (QUARK_SC_PCIE_AFE_SB_PORT_ID, QUARK_PCIE_AFE_PCIE_RXPICTRL0_L1, NewValue);
+
+ return EFI_SUCCESS;
+}
+
+/** Tasks to release PCI controller from reset pre wait for PLL Lock.
+
+ @retval EFI_SUCCESS Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+SocUnitReleasePcieControllerPreWaitPllLock (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+{
+ UINT32 NewValue;
+
+ //
+ // Assert PERST# and validate time assertion time.
+ //
+ PlatformPERSTAssert (PlatformType);
+ ASSERT (PCIEXP_PERST_MIN_ASSERT_US <= (PCIEXP_DELAY_US_POST_CMNRESET_RESET + PCIEXP_DELAY_US_WAIT_PLL_LOCK + PCIEXP_DELAY_US_POST_SBI_RESET));
+
+ //
+ // PHY Common lane reset.
+ //
+ NewValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG);
+ NewValue |= SOCCLKEN_CONFIG_PHY_I_CMNRESET_L;
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG, NewValue);
+
+ //
+ // Wait post common lane reset.
+ //
+ MicroSecondDelay (PCIEXP_DELAY_US_POST_CMNRESET_RESET);
+
+ //
+ // PHY Sideband interface reset.
+ // Controller main reset
+ //
+ NewValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG);
+ NewValue |= (SOCCLKEN_CONFIG_SBI_RST_100_CORE_B | SOCCLKEN_CONFIG_PHY_I_SIDE_RST_L);
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG, NewValue);
+
+ return EFI_SUCCESS;
+}
+
+/** Tasks to release PCI controller from reset after PLL has locked
+
+ @retval EFI_SUCCESS Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+SocUnitReleasePcieControllerPostPllLock (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+{
+ UINT32 NewValue;
+
+ //
+ // Controller sideband interface reset.
+ //
+ NewValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG);
+ NewValue |= SOCCLKEN_CONFIG_SBI_BB_RST_B;
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG, NewValue);
+
+ //
+ // Wait post sideband interface reset.
+ //
+ MicroSecondDelay (PCIEXP_DELAY_US_POST_SBI_RESET);
+
+ //
+ // Deassert PERST#.
+ //
+ PlatformPERSTDeAssert (PlatformType);
+
+ //
+ // Wait post de assert PERST#.
+ //
+ MicroSecondDelay (PCIEXP_DELAY_US_POST_PERST_DEASSERT);
+
+ //
+ // Controller primary interface reset.
+ //
+ NewValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG);
+ NewValue |= SOCCLKEN_CONFIG_BB_RST_B;
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG, NewValue);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.c b/QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.c
new file mode 100644
index 0000000..c5415f8
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.c
@@ -0,0 +1,240 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformSecServicesLib.c
+
+Abstract:
+
+ Provide platform specific services to QuarkResetVector & QuarkSecLib.
+
+--*/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MfhLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Platform.h>
+
+typedef VOID (EFIAPI *PLATFORM_BOOT_IMAGE) (VOID);
+
+//
+// Routines local to this source module.
+//
+
+/** Copy boot image to sram and call it.
+
+**/
+STATIC
+VOID
+CopyImageToSramAndCall (
+ IN CONST UINT32 FlashAddress,
+ IN CONST UINT32 LengthBytes
+ )
+{
+ volatile UINT32 Index;
+ UINT32 *Dest;
+ UINT32 *Src;
+ UINT32 OffsetLocation;
+ UINT32 SramStage1Base;
+ PLATFORM_BOOT_IMAGE BootImage;
+
+ SramStage1Base = PcdGet32 (PcdEsramStage1Base);
+ Dest = (UINT32 *) SramStage1Base;
+ Src = (UINT32 *) FlashAddress;
+ for (Index = 0; Index < (LengthBytes / 4); Index++, Dest++, Src++) {
+ *Dest = *Src;
+ }
+ OffsetLocation = (SramStage1Base + PcdGet32 (PcdFvSecurityHeaderSize));
+ BootImage = (PLATFORM_BOOT_IMAGE) ((*((UINT32 *) OffsetLocation)) + OffsetLocation);
+
+ //
+ // Boot to image at FlashAddress.
+ //
+ BootImage ();
+
+ //
+ // We should never return if we do then loop forever.
+ //
+ for (Index = 0; Index == 0;);
+}
+
+//
+// Routines exported by this source module.
+//
+
+/** Copy and call fixed recovery image.
+
+**/
+VOID
+EFIAPI
+PlatformCopyFixedRecoveryImageToSramAndCall (
+ VOID
+ )
+{
+ volatile UINT32 Index;
+ UINT32 *Dest;
+ UINT32 *Src;
+ UINT32 OffsetLocation;
+ volatile UINT32 SramStage1Base;
+ volatile UINT32 HeaderSize;
+ volatile UINT32 CopyLength;
+ PLATFORM_BOOT_IMAGE BootImage;
+
+ //
+ // Make all locals derived from PCDs volatile so that they
+ // are put on the stack before the copy.
+ //
+ SramStage1Base = PcdGet32 (PcdEsramStage1Base);
+ HeaderSize = PcdGet32 (PcdFvSecurityHeaderSize);
+ Dest = (UINT32 *) SramStage1Base;
+ Src = (UINT32 *) PcdGet32 (PcdFlashFvFixedStage1AreaBase);
+ CopyLength = (PcdGet32 (PcdFlashFvFixedStage1AreaSize) / 4);
+
+ for (Index = 0; Index < CopyLength; Index++, Dest++, Src++) {
+ *Dest = *Src;
+ }
+ OffsetLocation = (SramStage1Base + HeaderSize);
+ BootImage = (PLATFORM_BOOT_IMAGE) ((*((UINT32 *) OffsetLocation)) + OffsetLocation);
+
+ //
+ // Boot to fixed recovery image.
+ //
+ BootImage ();
+
+ //
+ // We should never return if we do then loop forever.
+ //
+ for (Index = 0; Index == 0;);
+}
+
+/** Check if running recovery image in SRAM.
+
+ @retval TRUE If running recovery image from SRAM.
+ @retval FALSE If not recovery image from SRAM.
+**/
+BOOLEAN
+EFIAPI
+PlatformAmIFixedRecoveryRunningFromSram (
+ VOID
+ )
+{
+ UINT32 CheckAddr;
+ QUARK_EDKII_STAGE1_HEADER *Edk2ImageHeader;
+
+ CheckAddr = (UINT32) &PlatformAmIFixedRecoveryRunningFromSram;
+ if ((CheckAddr >= PcdGet32 (PcdEsramStage1Base)) && (CheckAddr < (PcdGet32 (PcdEsramStage1Base) + PcdGet32 (PcdESramMemorySize)))) {
+ Edk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) (PcdGet32 (PcdEsramStage1Base) + PcdGet32 (PcdFvSecurityHeaderSize));
+ return ((UINT8)Edk2ImageHeader->ImageIndex & QUARK_STAGE1_IMAGE_TYPE_MASK) == QUARK_STAGE1_RECOVERY_IMAGE_TYPE;
+ }
+ return FALSE;
+}
+
+/** Check if force recovery conditions met.
+
+ @return 0 if conditions not met or already running recovery image in SRAM.
+ @return address PlatformCopyFixedRecoveryImageToSramAndCall if conditions met.
+**/
+UINT32
+EFIAPI
+PlatformIsForceRecoveryConditionsMet (
+ VOID
+ )
+{
+ UINT32 Sticky32;
+ UINT32 Straps32;
+
+ //
+ // Check for 'Force Recovery Boot' by reading 'B_CFG_STICKY_RW_FORCE_RECOVERY'
+ //
+ Sticky32 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW);
+ Straps32 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_STPDDRCFG);
+
+ if ((Sticky32 & B_CFG_STICKY_RW_FORCE_RECOVERY) || ((Straps32 & B_STPDDRCFG_FORCE_RECOVERY) == 0)) {
+ //
+ // Clear sticky bit 'B_CFG_STICKY_RW_FORCE_RECOVERY'
+ //
+ Sticky32 &= ~B_CFG_STICKY_RW_FORCE_RECOVERY;
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW, Sticky32);
+
+ //
+ // Check if already running recovery image.
+ //
+ if (PlatformAmIFixedRecoveryRunningFromSram ()) {
+ //
+ // Already running recovery, do nothing.
+ //
+ return 0;
+ }
+
+ //
+ // Indicate conditions met by returning address of PlatformCopyFixedRecoveryImageToSramAndCall.
+ //
+ return (UINT32) &PlatformCopyFixedRecoveryImageToSramAndCall;
+ }
+
+ return 0;
+}
+
+/** Copy boot stage1 image to sram and Call it.
+
+ This routine is called from the QuarkResetVector to copy stage1 image to SRAM
+ the routine should NOT be called from QuarkSecLib.
+
+**/
+VOID
+EFIAPI
+PlatformCopyBootStage1ImageToSramAndCall (
+ VOID
+ )
+{
+ MFH_FLASH_ITEM FlashItem;
+
+ //
+ // Find First stage1 flash module info or fixed recovery module info.
+ //
+ if (!MfhLibFindFirstStage1OrFixedRecovery (&FlashItem, NULL)) {
+ //
+ // No stage1 boot image found, force call to fixed recovery.
+ //
+ PlatformCopyFixedRecoveryImageToSramAndCall ();
+ }
+
+ //
+ // Copy MFH specified image to SRAM and call it.
+ //
+ CopyImageToSramAndCall (
+ FlashItem.FlashAddress,
+ FlashItem.LengthBytes
+ );
+}
diff --git a/QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.inf b/QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.inf
new file mode 100644
index 0000000..40718ac
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.inf
@@ -0,0 +1,86 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# PlatformSecServicesLib.inf
+#
+# Abstract:
+#
+# Library to provide platform services to QuarkResetVector & QuarkSecLib.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformSecServicesLib
+ FILE_GUID = 0036E802-05D5-47b4-996B-8C27A45623B6
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformSecServicesLib
+
+[BuildOptions]
+#
+# Useful to verify PlatformCopyFixedRecoveryImageToSramAndCall is only
+# dependant on stack.
+#
+ MSFT:*_*_IA32_CC_FLAGS = /FAcs
+ GCC:*_*_IA32_CC_FLAGS = -save-temps
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PlatformSecServicesLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ MfhLib
+ IntelQNCLib
+ QNCAccessLib
+
+[Ppis]
+
+[Pcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+ gQuarkPlatformTokenSpaceGuid.PcdEsramStage1Base
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdESramMemorySize
diff --git a/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.c b/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.c
new file mode 100644
index 0000000..f36db99
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.c
@@ -0,0 +1,70 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformSecureLib.c
+
+Abstract:
+
+ Provides a secure platform-specific method to detect physically present user.
+
+--*/
+
+/**
+
+ This function provides a platform-specific method to detect whether the platform
+ is operating by a physically present user.
+
+ Programmatic changing of platform security policy (such as disable Secure Boot,
+ or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during
+ Boot Services or after exiting EFI Boot Services. Only a physically present user
+ is allowed to perform these operations.
+
+ NOTE THAT: This function cannot depend on any EFI Variable Service since they are
+ not available when this function is called in AuthenticateVariable driver.
+
+ @retval TRUE The platform is operated by a physically present user.
+ @retval FALSE The platform is NOT operated by a physically present user.
+
+**/
+BOOLEAN
+EFIAPI
+UserPhysicalPresent (
+ VOID
+ )
+{
+ //
+ // This platform does not support a physically present user being able to
+ // change security resources.
+ //
+
+ return FALSE;
+}
diff --git a/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf b/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
new file mode 100644
index 0000000..de3e623
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
@@ -0,0 +1,60 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# PlatformSecureLib.inf
+#
+# Abstract:
+#
+# Provides a secure platform-specific method to detect physically present user.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformSecureLib
+ FILE_GUID = 38BB5221-F685-469f-846E-F1C508FC5F4A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformSecureLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_DRIVER
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ PlatformSecureLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
diff --git a/QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.c b/QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.c
new file mode 100644
index 0000000..8ef2a24
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.c
@@ -0,0 +1,369 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformUnProvisionedHandlerLib.c
+
+Abstract:
+
+ Library to handle Security Access Protocol SAP image loading
+ when secure boot is un provisioned.
+
+--*/
+
+#include <PiDxe.h>
+
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/SecureBootHelper.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/SecurityManagementLib.h>
+
+/** Get the file image from mask.
+
+ If This or File is NULL, then ASSERT().
+ If sanity checks on This pointer fail then assert.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] File This is a pointer to the device path of the file
+ to get IMAGE_FROM_XXX mask for.
+
+ @return UINT32 Mask which is one of IMAGE_FROM_XXX defs in protocol header file.
+
+**/
+STATIC
+UINT32
+EFIAPI
+GetImageFromMask (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ //
+ // First check to see if File is from a Firmware Volume
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
+ Status = gBS->LocateDevicePath (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ DeviceHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return IMAGE_FROM_FV;
+ }
+ }
+
+ //
+ // Next check to see if File is from a Block I/O device
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
+ Status = gBS->LocateDevicePath (
+ &gEfiBlockIoProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ BlockIo = NULL;
+ Status = gBS->OpenProtocol (
+ DeviceHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status) && BlockIo != NULL) {
+ if (BlockIo->Media != NULL) {
+ if (BlockIo->Media->RemovableMedia) {
+ //
+ // Block I/O is present and specifies the media is removable
+ //
+ return IMAGE_FROM_REMOVABLE_MEDIA;
+ } else {
+ //
+ // Block I/O is present and specifies the media is not removable
+ //
+ return IMAGE_FROM_FIXED_MEDIA;
+ }
+ }
+ }
+ }
+
+ //
+ // File is not in a Firmware Volume or on a Block I/O device, so check to see if
+ // the device path supports the Simple File System Protocol.
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
+ Status = gBS->LocateDevicePath (
+ &gEfiSimpleFileSystemProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Simple File System is present without Block I/O, so assume media is fixed.
+ //
+ return IMAGE_FROM_FIXED_MEDIA;
+ }
+
+ //
+ // File is not from an FV, Block I/O or Simple File System, so the only options
+ // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
+ //
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
+ while (!IsDevicePathEndType (TempDevicePath)) {
+ switch (DevicePathType (TempDevicePath)) {
+
+ case MEDIA_DEVICE_PATH:
+ if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
+ return IMAGE_FROM_OPTION_ROM;
+ }
+ break;
+
+ case MESSAGING_DEVICE_PATH:
+ if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
+ return IMAGE_FROM_PXE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+ return IMAGE_UNKNOWN;
+}
+
+/** Trace a Device Path.
+
+ @param[in] DevPath Device Path to trace.
+
+**/
+STATIC
+VOID
+EFIAPI
+TraceDevPath (
+ IN CHAR16 *Context,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevPath
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *AsText;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
+
+ EFI_DEVICE_PATH_PROTOCOL *DupPath;
+ DupPath = DuplicateDevicePath (DevPath);
+ if (DupPath == NULL) {
+ DEBUG ((EFI_D_INFO, "%s DuplicateDevicePath FAIL\n", Context));
+ return;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathToTextProtocolGuid,
+ NULL,
+ (VOID **) &DevPathToText
+ );
+ if (!EFI_ERROR (Status)) {
+ AsText = DevPathToText->ConvertDevicePathToText (
+ DupPath,
+ FALSE,
+ TRUE
+ );
+ DEBUG ((EFI_D_INFO, "%s %s\n", Context, (AsText) ? AsText : L"ConvertDevicePathToText FAIL"));
+ } else {
+ DEBUG ((EFI_D_INFO, "%s Locate gEfiDevicePathToTextProtocolGuid FAIL\n", Context));
+ }
+
+ FreePool (DupPath);
+}
+
+/**
+ The security handler is used to abstract platform-specific policy
+ from the DXE core response to an attempt to use a file that returns a
+ given status for the authentication check from the section extraction protocol.
+
+ The possible responses in a given SAP implementation may include locking
+ flash upon failure to authenticate, attestation logging for all signed drivers,
+ and other exception operations. The File parameter allows for possible logging
+ within the SAP of the driver.
+
+ If File is NULL, then EFI_INVALID_PARAMETER is returned.
+
+ If the file specified by File with an authentication status specified by
+ AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.
+
+ If the file specified by File with an authentication status specified by
+ AuthenticationStatus is not safe for the DXE Core to use under any circumstances,
+ then EFI_ACCESS_DENIED is returned.
+
+ If the file specified by File with an authentication status specified by
+ AuthenticationStatus is not safe for the DXE Core to use right now, but it
+ might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is
+ returned.
+
+ @param[in] AuthenticationStatus
+ This is the authentication status returned from the security
+ measurement services for the input file.
+ @param[in] File This is a pointer to the device path of the file that is
+ being dispatched. This will optionally be used for logging.
+ @param[in] FileBuffer File buffer matches the input file device path.
+ @param[in] FileSize Size of File buffer matches the input file device path.
+
+ @retval EFI_SUCCESS The file specified by File did authenticate, and the
+ platform policy dictates that the DXE Core may use File.
+ @retval EFI_INVALID_PARAMETER File is NULL.
+ @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
+ the platform policy dictates that File should be placed
+ in the untrusted state. A file may be promoted from
+ the untrusted to the trusted state at a future time
+ with a call to the Trust() DXE Service.
+ @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
+ the platform policy dictates that File should not be
+ used for any purpose.
+
+**/
+EFI_STATUS
+EFIAPI
+UnProvisionedHandler (
+ IN OUT UINT32 AuthenticationStatus,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
+ IN VOID *FileBuffer OPTIONAL,
+ IN UINTN FileSize OPTIONAL,
+ IN BOOLEAN BootPolicy OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ImageFromMask;
+ BOOLEAN SecureBootEnabled;
+ UINT32 LoadPolicy;
+ SECUREBOOT_HELPER_PROTOCOL *SecureBootHelperProtocol;
+
+ SecureBootHelperProtocol = NULL;
+
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ TraceDevPath (L"AuthFile:-", File);
+ DEBUG_CODE_END ();
+
+ if (FeaturePcdGet (PcdSupportSecureBoot)) {
+ if (SecureBootHelperProtocol == NULL) {
+ Status = gBS->LocateProtocol(
+ &gSecureBootHelperProtocolGuid,
+ NULL,
+ (VOID**) &SecureBootHelperProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (SecureBootHelperProtocol != NULL);
+ }
+ SecureBootEnabled = SecureBootHelperProtocol->IsSecureBootEnabled (
+ SecureBootHelperProtocol
+ );
+ if (SecureBootEnabled) {
+ //
+ // Secure boot provisioned so let other handlers decide.
+ //
+ return EFI_SUCCESS;
+ }
+ }
+
+ ImageFromMask = GetImageFromMask (
+ File
+ );
+ LoadPolicy = (UINT32) ~(IMAGE_UNKNOWN);
+ if (FeaturePcdGet (PcdEnableSecureLock)) {
+ LoadPolicy = IMAGE_FROM_FV;
+ }
+ if ((ImageFromMask & LoadPolicy) == 0) {
+ DEBUG ((EFI_D_INFO, "Platform Deny File FromMask 0x%08x LoadPolicy 0x%08x\n", ImageFromMask, LoadPolicy));
+ Status = EFI_ACCESS_DENIED;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+ return Status;
+}
+
+/** Register the security handler for Un Provisioned image verification.
+
+ @param ImageHandle ImageHandle of the loaded driver.
+ @param SystemTable Pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS Register successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to register this handler.
+**/
+EFI_STATUS
+EFIAPI
+PlatformUnProvisionedHandlerLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+
+ //
+ // For this platform only enforce a policy if Secure Lock enabled or Secure
+ // boot is supported in build.
+ //
+ if (FeaturePcdGet (PcdEnableSecureLock) || FeaturePcdGet (PcdSupportSecureBoot)) {
+ return RegisterSecurity2Handler (
+ UnProvisionedHandler,
+ EFI_AUTH_OPERATION_VERIFY_IMAGE
+ );
+ }
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.inf b/QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.inf
new file mode 100644
index 0000000..c5f1451
--- /dev/null
+++ b/QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.inf
@@ -0,0 +1,85 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# PlatformUnProvisionedHandlerLib.inf
+#
+# Abstract:
+#
+# Library to handle Security Access Protocol SAP image loading
+# when secure boot is un provisioned.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformUnProvisionedHandlerLib
+ FILE_GUID = 99F40381-4D29-4f56-83FA-7A07A25A34B1
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = PlatformUnProvisionedHandlerLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PlatformUnProvisionedHandlerLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ DevicePathLib
+ UefiBootServicesTableLib
+ PeCoffLib
+ BaseLib
+ SecurityManagementLib
+
+[Protocols]
+ gEfiFirmwareVolume2ProtocolGuid
+ gEfiBlockIoProtocolGuid
+ gEfiDiskIoProtocolGuid
+ gEfiDevicePathToTextProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+ gSecureBootHelperProtocolGuid
+
+[FeaturePcd]
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock
+ gQuarkPlatformTokenSpaceGuid.PcdSupportSecureBoot
diff --git a/QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.c b/QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.c
new file mode 100644
index 0000000..91690fa
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.c
@@ -0,0 +1,341 @@
+/** @file
+ Library implementation for Flash Device Library based on Multiple Flash Support
+ library intance.
+
+ BaseLib for PEI & DXE so Memory Allocation routine pointers have to be passed in.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/QuarkBootRomLib.h>
+
+/**
+ Security library to authenticate a signed image.
+
+ @param[in] ImageBaseAddress Pointer to the current image under
+ consideration
+ @param[in] CallerSignedKeyModule Pointer to signed key module to
+ validate image against. If NULL use
+ default.
+ @param[in] AuthKeyModule If TRUE authenticate key module
+ as well as image.
+ @param[in] KeyBankNumberPtr Pointer to key bank number. If NULL
+ use default bank.
+ @param[in] QAllocPool Pointer allocate pool routine for
+ UEFI emviroment.
+ @param[in] QFreePool Pointer free pool routine for
+ UEFI emviroment.
+
+ @retval EFI_SUCCESS Image is legal
+ @retval EFI_SECURITY_VIOLATION Image is NOT legal.
+ @retval EFI_INVALID_PARAMETER Param options required QAllocPool
+ and QFreePool to be provided.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete
+ operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SecurityAuthenticateImage (
+ IN VOID *ImageBaseAddress,
+ IN QuarkSecurityHeader_t *CallerSignedKeyModule OPTIONAL,
+ IN CONST BOOLEAN AuthKeyModule,
+ IN UINT8 *KeyBankNumberPtr OPTIONAL,
+ IN QUARK_AUTH_ALLOC_POOL QAllocPool OPTIONAL,
+ IN QUARK_AUTH_FREE_POOL QFreePool OPTIONAL
+ )
+{
+ BOOLEAN (*ValidateModuleCallBack)(QuarkSecurityHeader_t*, RSA2048PublicKey_t*, ScratchMemory_t*); // bootrom code validate entry function pointer
+ UINT8 MemoryBufferArray[QUARK_CRYPTO_HEAP_SIZE_BYTES]; // Allocate a heap to be used by the BootRom crypto functions
+ UINT32 *ValidateModuleCallBackAddress;
+ ScratchMemory_t *scratchAreaInfo;
+ RSA2048PublicKey_t *OemRsaKeyAddress;
+ QuarkSecurityHeader_t *SignedKeyModule; // Location in memory of key module to be validated.
+ QuarkSecurityHeader_t *SignedImageBaseAddress; // Location in memory of image to be validated
+ EFI_STATUS Status;
+ BOOLEAN RomResult;
+ UINT8 KeyBankNumber;
+
+ ValidateModuleCallBackAddress = NULL;
+ ValidateModuleCallBack = NULL;
+
+ //
+ // Function requires both or none of memory resource routines.
+ //
+ if (QAllocPool != NULL && QFreePool == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Determine SoC Key bank number to use.
+ //
+ if (KeyBankNumberPtr == NULL) {
+ KeyBankNumber = QUARK_DEFAULT_INTEL_KEY_FUSE_BANK;
+ } else {
+ KeyBankNumber = *KeyBankNumberPtr;
+ }
+
+ //
+ // Get the address of the OEM RSA Public Key And Authenticate Key if asked.
+ //
+ if (CallerSignedKeyModule == NULL) {
+ SignedKeyModule = (QuarkSecurityHeader_t *) QUARK_KEY_MODULE_BASE_ADDRESS;
+ } else {
+ SignedKeyModule = CallerSignedKeyModule;
+ }
+ if (AuthKeyModule) {
+ Status = SecurityAuthenticateKeyModule (
+ SignedKeyModule,
+ KeyBankNumber,
+ MemoryBufferArray,
+ QUARK_CRYPTO_HEAP_SIZE_BYTES,
+ QAllocPool,
+ QFreePool
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ OemRsaKeyAddress = (RSA2048PublicKey_t *) (((UINT32)SignedKeyModule->ModuleHeaderSizeBytes) + (UINT32) QUARK_KEY_MODULE_BASE_ADDRESS);
+
+ //
+ // Get the address of the image to be authenticated (including the CSH)
+ //
+ SignedImageBaseAddress = (QuarkSecurityHeader_t *)((UINT32)ImageBaseAddress - PcdGet32 (PcdFvSecurityHeaderSize));
+
+ //
+ // Initialise memory to pass as heap to Validate function to all zeros
+ //
+ ZeroMem (MemoryBufferArray, QUARK_CRYPTO_HEAP_SIZE_BYTES);
+
+ //
+ // Init the Scratch Memory Structure.
+ //
+ scratchAreaInfo = (ScratchMemory_t *)&MemoryBufferArray;
+ scratchAreaInfo->HeapStart = (UINT8 *)(scratchAreaInfo + 1); // Next address after the structure itself - use pointer++ to figure that address for us.
+ scratchAreaInfo->HeapEnd = (UINT8 *)(scratchAreaInfo) + QUARK_CRYPTO_HEAP_SIZE_BYTES;
+ scratchAreaInfo->NextFreeMem = scratchAreaInfo->HeapStart; // Reset our next free memory pointer to the base address.
+ scratchAreaInfo->FatalCode = 0;
+ scratchAreaInfo->DebugCode = 0;
+
+ //
+ // Validate signed image using Oem Key.
+ //
+ ValidateModuleCallBackAddress = (UINT32*) QUARK_BOOTROM_VALIDATE_FUNCTION_ENTRYPOINT_ADDRESS;
+ ValidateModuleCallBack = (BOOLEAN(*)(QuarkSecurityHeader_t*, RSA2048PublicKey_t*, ScratchMemory_t*))((UINT32)(*ValidateModuleCallBackAddress)); // actual address here to jump to make sure to get it each time!
+
+ RomResult = ValidateModuleCallBack (
+ (QuarkSecurityHeader_t*) SignedImageBaseAddress,
+ (RSA2048PublicKey_t*) OemRsaKeyAddress,
+ (ScratchMemory_t*) scratchAreaInfo
+ );
+
+ DEBUG ((EFI_D_INFO, "SecurityAuthenticateImage RomResult:%d DebugCode:0x%08X: FatalCode:0x%08X\n",
+ (UINTN) RomResult,
+ (UINTN) scratchAreaInfo->DebugCode,
+ (UINTN) scratchAreaInfo->FatalCode
+ ));
+
+ if (RomResult) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_SECURITY_VIOLATION;
+ }
+
+ return Status;
+}
+
+/**
+ Security library to authenticate a signed key module.
+
+ @param[in] SignedKetModule Pointer to key module to authenticate.
+ @param[in] KeyBankNumber Key bank number to use.
+ @param[in] CallerMemBuf Heap to be used by the BootRom crypto
+ functions. If == NULL alloc a heap.
+ @param[in] QAllocPool Pointer allocate pool routine for
+ UEFI emviroment.
+ @param[in] QFreePool Pointer free pool routine for
+ UEFI emviroment.
+
+ @retval EFI_SUCCESS Key module is legal
+ @retval EFI_SECURITY_VIOLATION Key module is NOT legal.
+ @retval EFI_INVALID_PARAMETER Param options required QAllocPool
+ and QFreePool to be provided.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete
+ operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SecurityAuthenticateKeyModule (
+ IN QuarkSecurityHeader_t *CallerSignedKeyModule,
+ IN CONST UINT8 KeyBankNumber,
+ IN UINT8 *CallerMemBuf OPTIONAL,
+ IN UINTN CallerMemBufSize OPTIONAL,
+ IN QUARK_AUTH_ALLOC_POOL QAllocPool OPTIONAL,
+ IN QUARK_AUTH_FREE_POOL QFreePool OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *MemoryBuffer;
+ ScratchMemory_t *scratchAreaInfo;
+ UINT8 *KeyAlloc;
+ UINT8 *BufAlloc;
+ VALIDATE_KEY_MODULE ValidateKeyModule;
+ QuarkRomFatalErrorCode ValidateKeyResult;
+ UINT8 *ModuleData;
+ RSA2048PublicKey_t *ModuleKey;
+ UINT8 *Signature;
+ UINTN MemBufSize;
+ QuarkSecurityHeader_t *SignedKeyModule;
+
+ if (CallerSignedKeyModule == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ SignedKeyModule = CallerSignedKeyModule;
+
+ //
+ // Assume no mem allocations. If != NULL before function exit then call
+ // QFreePool with non NULL values.
+ //
+ KeyAlloc = NULL;
+ BufAlloc = NULL;
+
+ //
+ // Function requires both or none of memory resource routines.
+ //
+ if (QAllocPool != NULL && QFreePool == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get Heap to be used by the BootRom crypto functions.
+ //
+ if (CallerMemBuf == NULL) {
+ if (QAllocPool == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ MemBufSize = QUARK_CRYPTO_HEAP_SIZE_BYTES;
+ BufAlloc = QAllocPool (MemBufSize);
+ if (BufAlloc == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemoryBuffer = BufAlloc;
+ } else {
+ MemoryBuffer = CallerMemBuf;
+ MemBufSize = CallerMemBufSize;
+ }
+
+ //
+ // Initialise memory to pass as heap to Validate function to all zeros
+ //
+ ZeroMem (MemoryBuffer, MemBufSize);
+
+ //
+ // Init the Scratch Memory Structure.
+ //
+ scratchAreaInfo = (ScratchMemory_t *)MemoryBuffer;
+ scratchAreaInfo->HeapStart = (UINT8 *)(scratchAreaInfo + 1); // Next address after the structure itself - use pointer++ to figure that address for us.
+ scratchAreaInfo->HeapEnd = (UINT8 *)(scratchAreaInfo) + MemBufSize;
+ scratchAreaInfo->NextFreeMem = scratchAreaInfo->HeapStart; // Reset our next free memory pointer to the base address.
+ scratchAreaInfo->FatalCode = 0;
+ scratchAreaInfo->DebugCode = 0;
+
+ //
+ // Do work from now on if no error detected.
+ //
+ Status = EFI_SUCCESS;
+
+ if (QAllocPool != NULL && SignedKeyModule->ModuleSizeBytes > 0 && SignedKeyModule->ModuleSizeBytes <= QUARK_KEY_MODULE_MAX_SIZE) {
+ KeyAlloc = (UINT8 *) QAllocPool (SignedKeyModule->ModuleSizeBytes);
+ if (KeyAlloc != NULL) {
+ CopyMem (
+ (VOID *) KeyAlloc,
+ (VOID *) SignedKeyModule,
+ SignedKeyModule->ModuleSizeBytes
+ );
+
+ //
+ // Override local pointer to allocated signed key module.
+ //
+ SignedKeyModule = (QuarkSecurityHeader_t *) KeyAlloc;
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get address of ValidateKeyModule routine in rom.
+ //
+ ValidateKeyModule = *((VALIDATE_KEY_MODULE *) QUARK_BOOTROM_VALIDATE_KEY_ENTRYPOINT_ADDRESS);
+
+ //
+ // Determine indivdual params and call rom routine.
+ //
+ ModuleData = ((UINT8 *) SignedKeyModule) + SignedKeyModule->ModuleHeaderSizeBytes; // Data is after indicated size of header.
+ ModuleKey = (RSA2048PublicKey_t *) (((UINT8 *)SignedKeyModule)+ sizeof(QuarkSecurityHeader_t)); // Key is right after CSH
+ Signature = ((UINT8 *) ModuleKey) + SignedKeyModule->KeySizeBytes; // Signature is after indicated size of key.
+ ValidateKeyResult = ValidateKeyModule (
+ SignedKeyModule,
+ ModuleData,
+ ModuleKey,
+ Signature,
+ scratchAreaInfo,
+ KeyBankNumber
+ );
+
+ DEBUG ((EFI_D_INFO, "SecurityAuthenticateKeyModule Result:%d DebugCode:0x%08X: FatalCode:0x%08X\n",
+ (UINTN) ValidateKeyResult,
+ (UINTN) scratchAreaInfo->DebugCode,
+ (UINTN) scratchAreaInfo->FatalCode
+ ));
+
+ if (ValidateKeyResult != QUARK_ROM_NO_ERROR) {
+ Status = EFI_SECURITY_VIOLATION;
+ }
+ }
+
+ //
+ // Free allocated memory before exit.
+ //
+ if (KeyAlloc != NULL) {
+ QFreePool (KeyAlloc);
+ }
+ if (BufAlloc != NULL) {
+ QFreePool (BufAlloc);
+ }
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.inf b/QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.inf
new file mode 100644
index 0000000..7568ed4
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.inf
@@ -0,0 +1,61 @@
+## @file
+# Library instace of Flash Device Library Class
+#
+# This library implement the flash device library class for the QuarkNcSocId platform.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QuarkBootRomLib
+ FILE_GUID = 030a9292-8ac4-4ff8-b346-44b6809a7e81
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SecurityAuthenticationLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ QuarkBootRomLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Flat32.S b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Flat32.S
new file mode 100644
index 0000000..5d541a0
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Flat32.S
@@ -0,0 +1,688 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# Flat32.S
+#
+# Abstract:
+#
+# This is the code that goes from real-mode to protected mode.
+# It consumes the reset vector, configures the stack, and enters PEI.
+#
+#
+#------------------------------------------------------------------------------
+
+
+#
+# CR0 cache control bit definition
+#
+.equ CR0_CACHE_DISABLE, 0x040000000
+.equ CR0_NO_WRITE, 0x020000000
+
+.macro RET32
+ jmp %esp
+.endm
+
+#
+# ROM/SPI/MEMORY Definitions
+#
+.equ QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000) # Memory Base Address = 0
+.equ QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000) # DDR3 Memory Size = 2GB
+.equ QUARK_ESRAM_MEM_BASE_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES) # eSRAM Memory above DDR3
+.equ QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000) # eSRAM Memory Size = 512K
+.equ QUARK_STACK_SIZE_BYTES, (0x008000) # Quark stack size = 32K
+.equ QUARK_STACK_BASE_ADDRESS, (QUARK_ESRAM_MEM_BASE_ADDRESS + QUARK_ESRAM_MEM_SIZE_BYTES) - QUARK_STACK_SIZE_BYTES # Top of eSRAM - stack size
+
+#
+# RTC/CMOS definitions
+#
+.equ RTC_INDEX, (0x70)
+.equ NMI_DISABLE, (0x80) # Bit7=1 disables NMI
+.equ NMI_ENABLE, (0x00) # Bit7=0 disables NMI
+.equ RTC_DATA, (0x71)
+
+#
+# PCI Configuration definitions
+#
+.equ PCI_CFG, (0x80000000) # PCI configuration access mechanism
+.equ PCI_ADDRESS_PORT, (0xCF8)
+.equ PCI_DATA_PORT, (0xCFC)
+
+#
+# Quark PCI devices
+#
+.equ HOST_BRIDGE_PFA, (0x0000) # B0:D0:F0 (Host Bridge)
+.equ ILB_PFA, (0x00F8) # B0:D31:F0 (Legacy Block)
+
+#
+# ILB PCI Config Registers
+#
+.equ BDE, (0x0D4) # BIOS Decode Enable register
+.equ DECODE_ALL_REGIONS_ENABLE, (0xFF000000) # Decode all BIOS decode ranges
+
+#
+# Host Bridge PCI Config Registers
+#
+.equ MESSAGE_BUS_CONTROL_REG, (0xD0) # Message Bus Control Register
+.equ SB_OPCODE_FIELD, (0x18) # Bit location of Opcode field
+.equ OPCODE_SIDEBAND_REG_READ, (0x10) # Read opcode
+.equ OPCODE_SIDEBAND_REG_WRITE, (0x11) # Write opcode
+.equ SB_PORT_FIELD, (0x10) # Bit location of Port ID field
+.equ MEMORY_ARBITER_PORT_ID, (0x00)
+.equ HOST_BRIDGE_PORT_ID, (0x03)
+.equ MEMORY_MANAGER_PORT_ID, (0x05)
+.equ SB_ADDR_FIELD, (0x08) # Bit location of Register field
+.equ SB_BE_FIELD, (0x04) # Bit location of Byte Enables field
+.equ ALL_BYTE_EN, (0x0F) # All Byte Enables
+.equ MESSAGE_DATA_REG, (0xD4) # Message Data Register
+
+#
+# Memory Arbiter Config Registers
+#
+.equ AEC_CTRL_OFFSET, (0x00)
+
+#
+# Host Bridge Config Registers
+#
+.equ HMISC2_OFFSET, (0x03) # PCI configuration access mechanism
+.equ OR_PM_FIELD, (0x10)
+
+.equ HMBOUND_OFFSET, (0x08)
+.equ HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
+.equ HECREG_OFFSET, (0x09)
+.equ EC_BASE, (0xE0000000)
+.equ EC_ENABLE, (0x01)
+.equ HLEGACY_OFFSET, (0x0A)
+.equ NMI, (0x00004000) # Bit location of Register field
+.equ SMI, (0x00001000) # Bit location of Register field
+.equ INTR, (0x00000400) # Bit location of Register field
+
+#
+# Memory Manager Config Registers
+#
+.equ ESRAMPGCTRL_BLOCK_OFFSET, (0x82)
+.equ ESRAM_ADDRESS_2G, (0x10000080)
+
+#
+# Contrary to the name, this file contains 16 bit code as well.
+#
+.text
+#----------------------------------------------------------------------------
+#
+# Procedure: _ModuleEntryPoint
+#
+# Input: None
+#
+# Output: None
+#
+# Destroys: Assume all registers
+#
+# Description:
+#
+# 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 a while in PEI and possibly DXE.
+#
+# After enabling protected mode, a far jump is executed to
+# transfer to PEI using the newly loaded GDT.
+#
+# Return: None
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+ #
+ # Warm Reset (INIT#) check.
+ #
+ .byte 0xbe,0x00,0xf0 #movw $0xF000, %si
+ .byte 0x8e,0xde #movw %si, %ds
+ .byte 0xbe,0xf0,0xff #movw $0xFFF0, %si
+ .byte 0x80,0x3c,0xea #cmpb $0xEA, (%si) # Is it warm reset ?
+ jne NotWarmReset # Jump if not.
+ .byte 0xb0,0x08 #movb $0x08, %al
+ .byte 0xba,0xf9,0x0c #movw $0xcf9, %dx
+ .byte 0xee #outb %al, %dx
+ .byte 0xb0,0x55 #movb $0x55, %al
+ .byte 0xe6,0x80 #outb %al, $0x80
+ jmp .
+NotWarmReset:
+
+ #
+ # Load the GDT table in GdtDesc
+ #
+ .byte 0x66,0xbe #movl $GdtDesc, %esi
+ .long GdtDesc
+
+ .byte 0x66,0x2e,0x0f,0x01,0x14 #lgdt %cs:(%si)
+
+ #
+ # Transition to 16 bit protected mode
+ #
+ .byte 0x0f,0x20,0xc0 #movl %cr0, %eax # Get control register 0
+ .byte 0x66,0x83,0xc8,0x03 #orl $0x0000003, %eax # Set PE bit (bit #0) & MP bit (bit #1)
+ .byte 0x0f,0x22,0xc0 #movl %eax, %cr0 # Activate protected mode
+
+ #
+ # Now we're in 16 bit protected mode
+ # Set up the selectors for 32 bit protected mode entry
+ #
+ .byte 0xb8 #movw SYS_DATA_SEL, %ax
+ .word SYS_DATA_SEL
+
+ .byte 0x8e,0xd8 #movw %ax, %ds
+ .byte 0x8e,0xc0 #movw %ax, %es
+ .byte 0x8e,0xe0 #movw %ax, %fs
+ .byte 0x8e,0xe8 #movw %ax, %gs
+ .byte 0x8e,0xd0 #movw %ax, %ss
+
+ #
+ # Transition to Flat 32 bit protected mode
+ # The jump to a far pointer causes the transition to 32 bit mode
+ #
+ .byte 0x66,0xbe #movl ProtectedModeEntryLinearAddress, %esi
+ .long ProtectedModeEntryLinearAddress
+ .byte 0x66,0x2e,0xff,0x2c #jmp %cs:(%esi)
+
+#
+# Protected mode portion initializes stack, configures cache, and calls C entry point
+#
+
+#----------------------------------------------------------------------------
+#
+# Procedure: ProtectedModeEntryPoint
+#
+# Input: Executing in 32 Bit Protected (flat) mode
+# cs: 0-4GB
+# ds: 0-4GB
+# es: 0-4GB
+# fs: 0-4GB
+# gs: 0-4GB
+# ss: 0-4GB
+# Maskable interrupts disabled (IF=0)
+# NMI disabled (RTC port)
+# SMI disabled (HMISC2 register)
+#
+# Output: This function never returns
+#
+# Destroys:
+# eax
+# ebx
+# ecx
+# esi
+# edi
+# ebp
+# esp
+#
+# Description:
+# Perform any essential early platform initilaisation
+# Setup a stack
+# Call the main EDKII Sec C code
+#
+#----------------------------------------------------------------------------
+#
+# This signature is used by build tools to locate this entry point in the 32-bit SPI code
+#
+.byte 0x53,0x50,0x49,0x20,0x45,0x6e,0x74,0x72,0x79,0x20,0x50,0x6f,0x69,0x6e,0x74,0x20 #'SPI Entry Point '
+ASM_GLOBAL ASM_PFX(ProtectedModeEntryPoint)
+ASM_PFX(ProtectedModeEntryPoint):
+
+ leal L0, %esp
+ jmp stackless_EarlyPlatformInit
+L0:
+
+ #
+ # Set up stack pointer
+ #
+ movl $QUARK_STACK_BASE_ADDRESS, %esp
+ movl $QUARK_STACK_SIZE_BYTES, %esi
+ addl %esi, %esp # ESP = top of stack (stack grows downwards).
+
+ #
+ # Check if force recovery conditions met.
+ #
+ call ASM_PFX(PlatformIsForceRecoveryConditionsMet)
+ testl %eax, %eax
+ jz NormalBoot
+
+ #
+ # Copy fixed recovery image to SRAM and call it.
+ # eax has address of routine to copy Fixed Recovery image to SRAM and call it.
+ # copy this routine to QUARK_STACK_BASE_ADDRESS, we have just setup the stack
+ # so it won't reach down to QUARK_STACK_BASE_ADDRESS yet.
+ # Doing this since we don't want the copy routine to copy over itself.
+ #
+ mov $(0x00000100), %ecx # 256 DWORDs = 1K
+ movl $QUARK_STACK_BASE_ADDRESS, %edi # The destination address in QUARK_STACK_BASE_ADDRESS.
+CopyRoutineLoop:
+ movl %ds:(%eax), %ebx
+ movl %ebx, %ds:(%edi)
+ addl $(0x04), %eax
+ addl $(0x04), %edi
+ loopl CopyRoutineLoop
+
+ #
+ # call routine which will copy and call fixed recovery image.
+ #
+ movl $QUARK_STACK_BASE_ADDRESS, %eax
+ call *%eax
+
+ #
+ # Forever loop at end of last routine so should not return here.
+ #
+ jmp .
+
+NormalBoot:
+
+
+ #
+ # Store the the BIST value in EBP
+ #
+ movl $0, %ebp # No processor BIST on Quark
+
+ #
+ # Push processor count to stack first, then BIST status (AP then BSP)
+ #
+ movl $1, %eax
+ cpuid
+ shrl $16, %ebx
+ andl $0x000000FF, %ebx
+ cmpb $1, %bl
+ jae PushProcessorCount
+
+ #
+ # Some processors report 0 logical processors. Effectively 0 = 1.
+ # So we fix up the processor count
+ #
+ incl %ebx
+
+PushProcessorCount:
+ pushl %ebx
+
+ #
+ # We need to implement a long-term solution for BIST capture. For now, we just copy BSP BIST
+ # for all processor threads
+ #
+ xorl %ecx, %ecx
+ movb %bl, %cl
+
+PushBist:
+ pushl %ebp
+ loop PushBist
+
+ #
+ # Pass entry point of the PEI core
+ #
+ movl $0xFFFFFFE0, %edi
+ pushl %ds:(%edi)
+
+ #
+ # Pass BFV into the PEI Core
+ # Sec/Pei FV Base Address in eSRAM is QUARK_ESRAM_MEM_BASE_ADDRESS + PcdFvSecurityHeaderSize.
+ #
+ movl _gPcd_FixedAtBuild_PcdFvSecurityHeaderSize, %eax
+ addl $QUARK_ESRAM_MEM_BASE_ADDRESS, %eax
+ pushl %eax
+
+ #
+ # Pass Temp Ram Base into the PEI Core
+ #
+ pushl $QUARK_STACK_BASE_ADDRESS
+
+ #
+ # Pass stack size into the PEI Core
+ #
+ pushl $QUARK_STACK_SIZE_BYTES
+
+ #
+ # Pass Control into the PEI Core
+ #
+ call SecStartup
+
+ #
+ # PEI Core should never return to here, this is just to capture an invalid return.
+ #
+ jmp .
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_EarlyPlatformInit
+#
+# Input: esp - Return address
+#
+# Output: None
+#
+# Destroys: Assume all registers
+#
+# Description:
+# Any early platform initialisation required
+#
+# Return:
+# None
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(stackless_EarlyPlatformInit)
+ASM_PFX(stackless_EarlyPlatformInit):
+
+ #
+ # Save return address
+ #
+ movl %esp, %ebp
+
+ #
+ # Ensure cache is disabled.
+ #
+ movl %cr0, %eax
+ orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax
+ invd
+ movl %eax, %cr0
+
+ #
+ # Enable NMI operation
+ # Good convention suggests you should read back RTC data port after
+ # accessing the RTC index port.
+ #
+ movb $(NMI_ENABLE), %al
+ movw $(RTC_INDEX), %dx
+ outb %al, %dx
+ movw $(RTC_DATA), %dx
+ inb %dx, %al
+
+ #
+ # Clear Host Bridge SMI, NMI, INTR fields
+ #
+ movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L3, %esp
+ jmp stackless_SideBand_Read
+L3:
+ andl $~(NMI + SMI + INTR), %eax # Clear NMI, SMI, INTR fields
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L4, %esp
+ jmp stackless_SideBand_Write
+L4:
+
+ #
+ # Set up the HMBOUND register
+ #
+ movl $(HMBOUND_ADDRESS), %eax # Data (Set HMBOUND location)
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L5, %esp
+ jmp stackless_SideBand_Write
+L5:
+
+ #
+ # Enable PCIEXBAR
+ #
+ movl $(EC_BASE + EC_ENABLE), %eax # Data
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L6, %esp
+ jmp stackless_SideBand_Write
+L6:
+
+ movl $(EC_BASE + EC_ENABLE), %eax # Data
+ movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx
+ leal L7, %esp
+ jmp stackless_SideBand_Write
+L7:
+
+ #
+ # Restore return address
+ #
+ movl %ebp, %esp
+ RET32
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_SideBand_Read
+#
+# Input: esp - return address
+# ecx[15:8] - Register offset
+# ecx[23:16] - Port ID
+# ecx[31:24] - Opcode
+#
+# Output: eax - Data read
+#
+# Destroys:
+# eax
+# ebx
+# cl
+# esi
+#
+# Description:
+# Perform requested sideband read
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(stackless_SideBand_Read)
+ASM_PFX(stackless_SideBand_Read):
+
+ movl %esp, %esi # Save the return address
+
+ #
+ # Load the SideBand Packet Register to generate the transaction
+ #
+ movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
+ movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
+ xchgl %ecx, %eax
+ leal L8, %esp
+ jmp stackless_PCIConfig_Write
+L8:
+ xchgl %ecx, %eax
+
+ #
+ # Read the SideBand Data Register
+ #
+ movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
+ leal L9, %esp
+ jmp stackless_PCIConfig_Read
+L9:
+
+ movl %esi, %esp # Restore the return address
+ RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_SideBand_Write
+#
+# Input: esp - return address
+# eax - Data
+# ecx[15:8] - Register offset
+# ecx[23:16] - Port ID
+# ecx[31:24] - Opcode
+#
+# Output: None
+#
+# Destroys:
+# ebx
+# cl
+# esi
+#
+# Description:
+# Perform requested sideband write
+#
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(stackless_SideBand_Write)
+ASM_PFX(stackless_SideBand_Write):
+
+ movl %esp, %esi # Save the return address
+
+ #
+ # Load the SideBand Data Register with the data
+ #
+ movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
+ leal L10, %esp
+ jmp stackless_PCIConfig_Write
+L10:
+
+ #
+ # Load the SideBand Packet Register to generate the transaction
+ #
+ movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
+ movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
+ xchgl %ecx, %eax
+ leal L11, %esp
+ jmp stackless_PCIConfig_Write
+L11:
+ xchgl %ecx, %eax
+
+ movl %esi, %esp # Restore the return address
+ RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_PCIConfig_Write
+#
+# Input: esp - return address
+# eax - Data to write
+# ebx - PCI Config Address
+#
+# Output: None
+#
+# Destroys:
+# dx
+#
+# Description:
+# Perform a DWORD PCI Configuration write
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(stackless_PCIConfig_Write)
+ASM_PFX(stackless_PCIConfig_Write):
+
+ #
+ # Write the PCI Config Address to the address port
+ #
+ xchgl %ebx, %eax
+ movw $(PCI_ADDRESS_PORT), %dx
+ outl %eax, %dx
+ xchgl %ebx, %eax
+
+ #
+ # Write the PCI DWORD Data to the data port
+ #
+ movw $(PCI_DATA_PORT), %dx
+ outl %eax, %dx
+
+ RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure: stackless_PCIConfig_Read
+#
+# Input: esp - return address
+# ebx - PCI Config Address
+#
+# Output: eax - Data read
+#
+# Destroys:
+# eax
+# dx
+#
+# Description:
+# Perform a DWORD PCI Configuration read
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(stackless_PCIConfig_Read)
+ASM_PFX(stackless_PCIConfig_Read):
+
+ #
+ # Write the PCI Config Address to the address port
+ #
+ xchgl %ebx, %eax
+ movw $(PCI_ADDRESS_PORT), %dx
+ outl %eax, %dx
+ xchgl %ebx, %eax
+
+ #
+ # Read the PCI DWORD Data from the data port
+ #
+ movw $(PCI_DATA_PORT), %dx
+ inl %dx, %eax
+
+ RET32
+
+
+#
+# ROM-based Global-Descriptor Table for the Tiano PEI Phase
+#
+.align 16
+#
+# GDT[0]: 000h: Null entry, never used.
+#
+.equ NULL_SEL, . - GDT_BASE # Selector [0]
+GDT_BASE:
+BootGdtTable:
+ .long 0
+ .long 0
+#
+# Linear code segment descriptor
+#
+.equ LINEAR_CODE_SEL, . - GDT_BASE # Selector [08h]
+ .word 0xFFFF # limit 0FFFFh
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9B # present, ring 0, data, expand-up, not-writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+#
+# System data segment descriptor
+#
+.equ SYS_DATA_SEL, . - GDT_BASE # Selector [018h]
+ .word 0xFFFF # limit 0FFFFh
+ .word 0 # base 0
+ .byte 0
+ .byte 0x93 # present, ring 0, data, expand-up, not-writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+.equ GDT_SIZE, . - BootGdtTable # Size, in bytes
+
+#
+# GDT Descriptor
+#
+GdtDesc: # GDT descriptor
+ .word GDT_SIZE - 1
+ .long BootGdtTable
+
+ProtectedModeEntryLinearAddress:
+ProtectedModeEntryLinearOffset:
+ .long ProtectedModeEntryPoint
+ .word LINEAR_CODE_SEL
+
+#
+# Used by C code
+#
+ASM_GLOBAL ASM_PFX(TopOfStack)
+ASM_PFX(TopOfStack):
+ .long QUARK_STACK_BASE_ADDRESS + QUARK_STACK_SIZE_BYTES
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Flat32.asm b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Flat32.asm
new file mode 100755
index 0000000..7dcb745
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Flat32.asm
@@ -0,0 +1,616 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; Flat32.asm
+;
+; Abstract:
+;
+; This is the code that goes from real-mode to protected mode.
+; It consumes the reset vector, configures the stack, and enters PEI.
+;
+;
+;------------------------------------------------------------------------------
+
+
+;
+; Define assembler characteristics
+;
+.686p
+.model flat, c
+
+;
+; Include processor definitions
+;
+INCLUDE Ia32.inc
+INCLUDE Platform.inc
+
+PlatformIsForceRecoveryConditionsMet PROTO C
+
+;
+; Declare PcdGet32 (PcdFvSecurityHeaderSize) as a double word.
+;
+EXTERNDEF C PcdGet32 (PcdFvSecurityHeaderSize):DWORD
+
+;
+; External and public declarations
+; TopOfStack is used by C code
+; SecStartup is the entry point to the C code
+; Neither of these names can be modified without
+; updating the C code.
+;
+PUBLIC TopOfStack
+EXTRN SecStartup: NEAR
+
+;
+; Contrary to the name, this file contains 16 bit code as well.
+;
+_TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
+
+;----------------------------------------------------------------------------
+;
+; Procedure: _ModuleEntryPoint
+;
+; Input: None
+;
+; Output: None
+;
+; Destroys: Assume all registers
+;
+; Description:
+;
+; 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 a while in PEI and possibly DXE.
+;
+; After enabling protected mode, a far jump is executed to
+; transfer to PEI using the newly loaded GDT.
+;
+; Return: None
+;
+;----------------------------------------------------------------------------
+align 16
+_ModuleEntryPoint PROC C PUBLIC
+
+ ;
+ ; Warm Reset (INIT#) check.
+ ;
+ mov si, 0F000h
+ mov ds, si
+ mov si, 0FFF0h
+ cmp BYTE PTR [si], 0EAh ; Is it warm reset ?
+ jne NotWarmReset ; JIf not.
+
+ mov al, 08
+ mov dx, 0cf9h
+ out dx, al
+ mov al, 055h
+ out 080h, al;
+ jmp $
+NotWarmReset:
+
+ ;
+ ; Load the GDT table in GdtDesc
+ ;
+ mov esi, OFFSET GdtDesc
+ db 66h
+ lgdt fword ptr cs:[si]
+
+ ;
+ ; Transition to 16 bit protected mode
+ ;
+ 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
+
+ ;
+ ; Now we're in 16 bit protected mode
+ ; Set up the selectors for 32 bit protected mode entry
+ ;
+ mov ax, SYS_DATA_SEL
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ ;
+ ; Transition to Flat 32 bit protected mode
+ ; The jump to a far pointer causes the transition to 32 bit mode
+ ;
+ mov esi, offset ProtectedModeEntryLinearAddress
+ jmp fword ptr cs:[si]
+
+_ModuleEntryPoint ENDP
+
+_TEXT_REALMODE ENDS
+
+.code
+;
+; Protected mode portion initializes stack, configures cache, and calls C entry point
+;
+
+;----------------------------------------------------------------------------
+;
+; Procedure: ProtectedModeEntryPoint
+;
+; Input: Executing in 32 Bit Protected (flat) mode
+; cs: 0-4GB
+; ds: 0-4GB
+; es: 0-4GB
+; fs: 0-4GB
+; gs: 0-4GB
+; ss: 0-4GB
+; Maskable interrupts disabled (IF=0)
+; NMI disabled (RTC port)
+; SMI disabled (HMISC2 register)
+;
+; Output: This function never returns
+;
+; Destroys:
+; eax
+; ebx
+; ecx
+; esi
+; edi
+; ebp
+; esp
+;
+; Description:
+; Perform any essential early platform initilaisation
+; Setup a stack
+; Call the main EDKII Sec C code
+;
+;----------------------------------------------------------------------------
+;
+; This signature is used by build tools to locate this entry point in the 32-bit SPI code
+;
+SPI_ENTRY_SIGNATURE DB 01h DUP ('SPI Entry Point ')
+ProtectedModeEntryPoint PROC NEAR C PUBLIC
+
+ JMP32 stackless_EarlyPlatformInit
+
+ ;
+ ; Set up stack pointer
+ ;
+ mov esp, QUARK_STACK_BASE_ADDRESS
+ mov esi, QUARK_STACK_SIZE_BYTES
+ add esp, esi ; ESP = top of stack (stack grows downwards).
+
+ ;
+ ; Check if force recovery conditions met.
+ ;
+ call PlatformIsForceRecoveryConditionsMet
+ test eax, eax
+ jz NormalBoot
+
+ ;
+ ; Copy fixed recovery image to SRAM and call it.
+ ; eax has address of routine to copy Fixed Recovery image to SRAM and call it.
+ ; copy this routine to QUARK_STACK_BASE_ADDRESS, we have just setup the stack
+ ; so it won't reach down to QUARK_STACK_BASE_ADDRESS yet.
+ ; Doing this since we don't want the copy routine to copy over itself.
+ ;
+ mov ecx, 000000100h ; 256 DWORDs = 1K
+ mov edi, QUARK_STACK_BASE_ADDRESS ; The destination address in QUARK_STACK_BASE_ADDRESS.
+CopyRoutineLoop:
+ mov ebx, DWORD PTR ds:[eax]
+ mov DWORD PTR ds:[edi], ebx
+ add eax, 04h
+ add edi, 04h
+ loopd CopyRoutineLoop
+
+ ;
+ ; call routine which will copy & call fixed recovery image.
+ ;
+ mov eax, QUARK_STACK_BASE_ADDRESS
+ call eax
+
+ ;
+ ; Forever loop at end of last routine so should not return here.
+ ;
+ jmp $
+
+NormalBoot:
+
+ ;
+ ; Store the the BIST value in EBP
+ ;
+ mov ebp, 00h ; No processor BIST on Quark
+
+ ;
+ ; Push processor count to stack first, then BIST status (AP then BSP)
+ ;
+ mov eax, 1
+ cpuid
+ shr ebx, 16
+ and ebx, 0000000FFh
+ cmp bl, 1
+ jae PushProcessorCount
+
+ ;
+ ; Some processors report 0 logical processors. Effectively 0 = 1.
+ ; So we fix up the processor count
+ ;
+ inc ebx
+
+PushProcessorCount:
+ push ebx
+
+ ;
+ ; We need to implement a long-term solution for BIST capture. For now, we just copy BSP BIST
+ ; for all processor threads
+ ;
+ xor ecx, ecx
+ mov cl, bl
+PushBist:
+ push ebp
+ loop PushBist
+
+ ;
+ ; Pass entry point of the PEI core
+ ;
+ mov edi, 0FFFFFFE0h
+ push DWORD PTR ds:[edi]
+
+ ;
+ ; Pass BFV into the PEI Core
+ ; Sec/Pei FV Base Address in eSRAM is QUARK_ESRAM_MEM_BASE_ADDRESS + PcdFvSecurityHeaderSize.
+ ;
+ mov eax, PcdGet32 (PcdFvSecurityHeaderSize) ; eax <- Security Header Size.
+ add eax, QUARK_ESRAM_MEM_BASE_ADDRESS ; eax <- Sec/Pei FV Base Address in eSRAM.
+
+ push eax
+
+ ;
+ ; Pass Temp Ram Base into the PEI Core
+ ;
+ push QUARK_STACK_BASE_ADDRESS
+
+ ;
+ ; Pass stack size into the PEI Core
+ ; It should be QUARK_STACK_SIZE_BYTES
+ ;
+ push QUARK_STACK_SIZE_BYTES
+
+ ;
+ ; Pass Control into the PEI Core
+ ;
+ call SecStartup
+
+ ;
+ ; PEI Core should never return to here, this is just to capture an invalid return.
+ ;
+ jmp $
+
+ProtectedModeEntryPoint ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_EarlyPlatformInit
+;
+; Input: esp - Return address
+;
+; Output: None
+;
+; Destroys: Assume all registers
+;
+; Description:
+; Any early platform initialisation required
+;
+; Return:
+; None
+;
+;----------------------------------------------------------------------------
+stackless_EarlyPlatformInit PROC NEAR C PUBLIC
+
+ ;
+ ; Save return address
+ ;
+ mov ebp, esp
+
+ ;
+ ; Ensure cache is disabled.
+ ;
+ mov eax, cr0
+ or eax, CR0_CACHE_DISABLE + CR0_NO_WRITE
+ invd
+ mov cr0, eax
+
+ ;
+ ; Enable NMI operation
+ ; Good convention suggests you should read back RTC data port after
+ ; accessing the RTC index port.
+ ;
+ mov al, NMI_ENABLE
+ mov dx, RTC_INDEX
+ out dx, al
+ mov dx, RTC_DATA
+ in al, dx
+
+ ;
+ ; Clear Host Bridge SMI, NMI, INTR fields
+ ;
+ mov ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HLEGACY_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Read
+ and eax, NOT(NMI + SMI + INTR) ; Clear NMI, SMI, INTR fields
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HLEGACY_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+
+ ;
+ ; Set up the HMBOUND register
+ ;
+ mov eax, HMBOUND_ADDRESS ; Data (Set HMBOUND location)
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+ ;
+ ; Enable PCIEXBAR
+ ;
+ mov eax, (EC_BASE + EC_ENABLE) ; Data
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_ARBITER_PORT_ID SHL SB_PORT_FIELD) OR (AEC_CTRL_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+ mov eax, (EC_BASE + EC_ENABLE) ; Data
+ mov ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HECREG_OFFSET SHL SB_ADDR_FIELD)
+ JMP32 stackless_SideBand_Write
+
+ ;
+ ; Restore return address
+ ;
+ mov esp, ebp
+ RET32
+
+stackless_EarlyPlatformInit ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_SideBand_Read
+;
+; Input: esp - return address
+; ecx[15:8] - Register offset
+; ecx[23:16] - Port ID
+; ecx[31:24] - Opcode
+;
+; Output: eax - Data read
+;
+; Destroys:
+; eax
+; ebx
+; cl
+; esi
+;
+; Description:
+; Perform requested sideband read
+;
+;----------------------------------------------------------------------------
+stackless_SideBand_Read PROC NEAR C PUBLIC
+
+ mov esi, esp ; Save the return address
+
+ ;
+ ; Load the SideBand Packet Register to generate the transaction
+ ;
+ mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG ; PCI Configuration address
+ mov cl, (ALL_BYTE_EN SHL SB_BE_FIELD) ; Set all Byte Enable bits
+ xchg eax, ecx
+ JMP32 stackless_PCIConfig_Write
+ xchg eax, ecx
+
+ ;
+ ; Read the SideBand Data Register
+ ;
+ mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG ; PCI Configuration address
+ JMP32 stackless_PCIConfig_Read
+
+ mov esp, esi ; Restore the return address
+ RET32
+
+stackless_SideBand_Read ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_SideBand_Write
+;
+; Input: esp - return address
+; eax - Data
+; ecx[15:8] - Register offset
+; ecx[23:16] - Port ID
+; ecx[31:24] - Opcode
+;
+; Output: None
+;
+; Destroys:
+; ebx
+; cl
+; esi
+;
+; Description:
+; Perform requested sideband write
+;
+;
+;----------------------------------------------------------------------------
+stackless_SideBand_Write PROC NEAR C PUBLIC
+
+ mov esi, esp ; Save the return address
+
+ ;
+ ; Load the SideBand Data Register with the data
+ ;
+ mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG ; PCI Configuration address
+ JMP32 stackless_PCIConfig_Write
+
+ ;
+ ; Load the SideBand Packet Register to generate the transaction
+ ;
+ mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG ; PCI Configuration address
+ mov cl, (ALL_BYTE_EN SHL SB_BE_FIELD) ; Set all Byte Enable bits
+ xchg eax, ecx
+ JMP32 stackless_PCIConfig_Write
+ xchg eax, ecx
+
+ mov esp, esi ; Restore the return address
+ RET32
+
+stackless_SideBand_Write ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_PCIConfig_Write
+;
+; Input: esp - return address
+; eax - Data to write
+; ebx - PCI Config Address
+;
+; Output: None
+;
+; Destroys:
+; dx
+;
+; Description:
+; Perform a DWORD PCI Configuration write
+;
+;----------------------------------------------------------------------------
+stackless_PCIConfig_Write PROC NEAR C PUBLIC
+
+ ;
+ ; Write the PCI Config Address to the address port
+ ;
+ xchg eax, ebx
+ mov dx, PCI_ADDRESS_PORT
+ out dx, eax
+ xchg eax, ebx
+
+ ;
+ ; Write the PCI DWORD Data to the data port
+ ;
+ mov dx, PCI_DATA_PORT
+ out dx, eax
+
+ RET32
+
+stackless_PCIConfig_Write ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure: stackless_PCIConfig_Read
+;
+; Input: esp - return address
+; ebx - PCI Config Address
+;
+; Output: eax - Data read
+;
+; Destroys:
+; eax
+; dx
+;
+; Description:
+; Perform a DWORD PCI Configuration read
+;
+;----------------------------------------------------------------------------
+stackless_PCIConfig_Read PROC NEAR C PUBLIC
+
+ ;
+ ; Write the PCI Config Address to the address port
+ ;
+ xchg eax, ebx
+ mov dx, PCI_ADDRESS_PORT
+ out dx, eax
+ xchg eax, ebx
+
+ ;
+ ; Read the PCI DWORD Data from the data port
+ ;
+ mov dx, PCI_DATA_PORT
+ in eax, dx
+
+ RET32
+
+stackless_PCIConfig_Read ENDP
+
+;
+; ROM-based Global-Descriptor Table for the Tiano PEI Phase
+;
+align 16
+PUBLIC BootGdtTable
+
+;
+; GDT[0]: 0x00: Null entry, never used.
+;
+NULL_SEL equ $ - GDT_BASE ; Selector [0]
+GDT_BASE:
+BootGdtTable DD 0
+ DD 0
+;
+; Linear code segment descriptor
+;
+LINEAR_CODE_SEL equ $ - GDT_BASE ; Selector [0x8]
+ DW 0FFFFh ; limit 0xFFFF
+ 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 [0x10]
+ DW 0FFFFh ; limit 0xFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 093h ; present, ring 0, data, expand-up, not-writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+
+GDT_SIZE EQU $ - BootGDTtable ; Size, in bytes
+
+;
+; GDT Descriptor
+;
+GdtDesc: ; GDT descriptor
+ DW GDT_SIZE - 1 ; GDT limit
+ DD OFFSET BootGdtTable ; GDT base address
+
+ProtectedModeEntryLinearAddress LABEL FWORD
+ProtectedModeEntryLinearOffset LABEL DWORD
+ DD OFFSET ProtectedModeEntryPoint ; Offset of our 32 bit code
+ DW LINEAR_CODE_SEL
+
+;
+; Used by C code
+;
+TopOfStack DD QUARK_STACK_BASE_ADDRESS + QUARK_STACK_SIZE_BYTES
+
+
+END
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Ia32.inc b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Ia32.inc
new file mode 100644
index 0000000..f2f4353
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Ia32.inc
@@ -0,0 +1,45 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; Ia32.inc
+;
+; Abstract:
+;
+; IA32 architecture MSRs
+;
+;------------------------------------------------------------------------------
+
+;
+; CR0 cache control bit definition
+;
+CR0_CACHE_DISABLE EQU 040000000h
+CR0_NO_WRITE EQU 020000000h
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Platform.inc b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Platform.inc
new file mode 100755
index 0000000..b6e7066
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/Platform.inc
@@ -0,0 +1,131 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; Platform.inc
+;
+; Abstract:
+;
+; Platform Specific Definitions
+;
+;------------------------------------------------------------------------------
+
+JMP32 MACRO FunctionName
+ lea esp, @F
+ jmp FunctionName
+@@:
+ENDM
+
+RET32 MACRO
+ jmp esp
+ENDM
+
+;
+; ROM/SPI/MEMORY Definitions
+;
+QUARK_DDR3_MEM_BASE_ADDRESS EQU 000000000h ; Memory Base Address = 0
+QUARK_MAX_DDR3_MEM_SIZE_BYTES EQU 080000000h ; DDR3 Memory Size = 2GB
+QUARK_ESRAM_MEM_BASE_ADDRESS EQU (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES) ; eSRAM Memory above DDR3
+QUARK_ESRAM_MEM_SIZE_BYTES EQU 000080000h ; eSRAM Memory Size = 512K
+QUARK_STACK_SIZE_BYTES EQU 008000h ; Quark stack size = 32K
+QUARK_STACK_BASE_ADDRESS EQU (QUARK_ESRAM_MEM_BASE_ADDRESS+QUARK_ESRAM_MEM_SIZE_BYTES)-QUARK_STACK_SIZE_BYTES ; Top of eSRAM - stack size
+
+;
+; RTC/CMOS definitions
+;
+RTC_INDEX EQU 070h
+ NMI_DISABLE EQU 080h ; Bit7=1 disables NMI
+ NMI_ENABLE EQU 000h ; Bit7=0 disables NMI
+RTC_DATA EQU 071h
+
+;
+; PCI Configuration definitions
+;
+PCI_CFG EQU 1 SHL 01Fh ; PCI configuration access mechanism
+PCI_ADDRESS_PORT EQU 0CF8h
+PCI_DATA_PORT EQU 0CFCh
+
+;
+; Quark PCI devices
+;
+HOST_BRIDGE_PFA EQU 0000h ; B0:D0:F0 (Host Bridge)
+ILB_PFA EQU 00F8h ; B0:D31:F0 (Legacy Block)
+
+;
+; ILB PCI Config Registers
+;
+BDE EQU 0D4h ; BIOS Decode Enable register
+ DECODE_ALL_REGIONS_ENABLE EQU 0FF000000h ; Decode all BIOS decode ranges
+
+;
+; Host Bridge PCI Config Registers
+;
+MESSAGE_BUS_CONTROL_REG EQU 0D0h ; Message Bus Control Register
+ SB_OPCODE_FIELD EQU 018h ; Bit location of Opcode field
+ OPCODE_SIDEBAND_REG_READ EQU 010h ; Read opcode
+ OPCODE_SIDEBAND_REG_WRITE EQU 011h ; Write opcode
+ SB_PORT_FIELD EQU 010h ; Bit location of Port ID field
+ MEMORY_ARBITER_PORT_ID EQU 00h
+ HOST_BRIDGE_PORT_ID EQU 03h
+ MEMORY_MANAGER_PORT_ID EQU 05h
+ SB_ADDR_FIELD EQU 008h ; Bit location of Register field
+ SB_BE_FIELD EQU 004h ; Bit location of Byte Enables field
+ ALL_BYTE_EN EQU 00Fh ; All Byte Enables
+MESSAGE_DATA_REG EQU 0D4h ; Message Data register
+
+;
+; Memory Arbiter Config Registers
+;
+AEC_CTRL_OFFSET EQU 00h
+
+;
+; Host Bridge Config Registers
+;
+HMISC2_OFFSET EQU 03h
+ OR_PM_FIELD EQU 010h
+
+HMBOUND_OFFSET EQU 08h
+ HMBOUND_ADDRESS EQU (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
+HECREG_OFFSET EQU 09h
+ EC_BASE EQU 0E0000000h
+ EC_ENABLE EQU 01h
+HLEGACY_OFFSET EQU 0Ah
+ NMI EQU 1 SHL 0Eh ; Pin 14
+ SMI EQU 1 SHL 0Ch ; Pin 12
+ INTR EQU 1 SHL 0Ah ; Pin 10
+
+;
+; Memory Manager Config Registers
+;
+ESRAMPGCTRL_BLOCK_OFFSET EQU 082h
+ ESRAM_ADDRESS_2G EQU ((01h SHL 1Ch) + (QUARK_ESRAM_MEM_BASE_ADDRESS SHR 18h))
+
+
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/SecCpu.S b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/SecCpu.S
new file mode 100644
index 0000000..f57baae
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/SecCpu.S
@@ -0,0 +1,56 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# SecCpu.S
+#
+# Abstract:
+#
+# Sec CPU functions
+#
+#------------------------------------------------------------------------------
+
+ .code:
+
+#
+# Local APIC timer is enabled in this function.
+#
+ASM_GLOBAL ASM_PFX(SecCpuInitTimer)
+ASM_PFX(SecCpuInitTimer):
+ movl %ds:(_gPcd_FixedAtBuild_PcdCpuLocalApicBaseAddress), %eax
+ andl $0xfffff000, %eax
+ movl $0xa, 0x3e0(%eax) # divided by 128 (divide config register)
+ btsl $17, 0x320(%eax) # set timer mode to "periodic"
+ movl $-1, 0x380(%eax) # start timer by writing to init count
+ ret
+
+
+
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/SecCpu.asm b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/SecCpu.asm
new file mode 100644
index 0000000..24415a2
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/Ia32/SecCpu.asm
@@ -0,0 +1,65 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; SecCpu.asm
+;
+; Abstract:
+;
+; Sec CPU functions
+;
+;------------------------------------------------------------------------------
+
+ .686p
+ .xmm
+ .model flat,c
+
+INCLUDE Ia32.inc
+
+;
+; Declare PcdGet32 (PcdCpuLocalApicBaseAddress) as a double word
+;
+EXTERNDEF C PcdGet32 (PcdCpuLocalApicBaseAddress):DWORD
+
+ .code
+
+;
+; Local APIC timer is enabled in this function.
+;
+SecCpuInitTimer PROC
+ mov eax, PcdGet32 (PcdCpuLocalApicBaseAddress) ; eax <- local APIC base
+ mov dword ptr [eax + 3e0h], 0ah ; divided by 128 (divide config register)
+ bts dword ptr [eax + 320h], 17 ; set timer mode to "periodic"
+ mov dword ptr [eax + 380h], -1 ; start timer by writing to init count
+ ret
+SecCpuInitTimer ENDP
+
+ END
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.c b/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.c
new file mode 100644
index 0000000..ac08952
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.c
@@ -0,0 +1,133 @@
+/** @file
+ Null instance of Sec Platform Hook Lib.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include "QuarkSecLib.h"
+
+extern UINT32 *TopOfStack;
+
+
+/**
+ Library constructor for platform SEC library.
+
+ The constructor will be invoked by SecCore module in IA32FamilyCpuBasePkg once the transition
+ to C code at SecStartup() function.
+
+**/
+RETURN_STATUS
+EFIAPI
+QNCSecLibConstructor (
+ VOID
+ )
+{
+ SecCpuInitTimer ();
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ A developer supplied function to perform platform specific operations.
+
+ It's a developer supplied function to perform any operations appropriate to a
+ given platform. It's invoked just before passing control to PEI core by SEC
+ core. Platform developer may modify the SecCoreData and PPI list that is
+ passed to PEI Core.
+
+ @param SecCoreData The same parameter as passing to PEI core. It
+ could be overridden by this function.
+ @param PpiList The default PPI list passed from generic SEC
+ part.
+
+ @return The final PPI list that platform wishes to passed to PEI core.
+
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+EFIAPI
+SecPlatformMain (
+ IN OUT EFI_SEC_PEI_HAND_OFF *SecCoreData,
+ IN EFI_PEI_PPI_DESCRIPTOR *PpiList
+ )
+{
+
+ return NULL;
+}
+
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param StructureSize Pointer to the variable describing size of the input buffer.
+ @param 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 CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_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 = *(UINT32 *) (UINTN) (TopOfStack - 1);
+ Size = Count * sizeof (UINT32);
+
+ if ((*StructureSize) < (UINT64) Size) {
+ *StructureSize = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *StructureSize = Size;
+ BIST = (UINT32 *) ((UINT32) TopOfStack - sizeof (UINT32) - Size);
+
+ CopyMem (PlatformInformationRecord, BIST, Size);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.h b/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.h
new file mode 100644
index 0000000..e71a33b
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.h
@@ -0,0 +1,60 @@
+/** @file
+ Null instance of Sec Platform Hook Lib.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+#ifndef _QUARK_SEC_LIB_H_
+#define _QUARK_SEC_LIB_H_
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/TemporaryRamSupport.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+
+VOID *
+EFIAPI
+SecCpuInitTimer (
+ VOID
+ );
+
+#endif
+
+
+
+
+
+
+
diff --git a/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.inf b/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.inf
new file mode 100644
index 0000000..a5f2b57
--- /dev/null
+++ b/QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.inf
@@ -0,0 +1,99 @@
+#/** @file
+# Library functions for QuarkNcSocId Sec hook library.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QuarkSecLib
+ FILE_GUID = 35465AE1-FB64-4a41-A1BE-BAAC568423C3
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformSecLib
+ CONSTRUCTOR = QNCSecLibConstructor
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+ QuarkSecLib.c
+ QuarkSecLib.h
+
+[Sources.IA32]
+ Ia32/Flat32.asm
+ Ia32/SecCpu.asm
+ Ia32/Flat32.S
+ Ia32/SecCpu.S
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ BaseLib
+ BaseMemoryLib
+ PciLib
+ PcdLib
+ PlatformSecServicesLib
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+
+[Pcd.common]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+
+[BuildOptions]
+ MSFT:*_*_IA32_PP_FLAGS = /FIQuarkSecLib.h
diff --git a/QuarkPlatformPkg/Library/RecoveryOemHookLib/CommonHeader.h b/QuarkPlatformPkg/Library/RecoveryOemHookLib/CommonHeader.h
new file mode 100755
index 0000000..e3a1628
--- /dev/null
+++ b/QuarkPlatformPkg/Library/RecoveryOemHookLib/CommonHeader.h
@@ -0,0 +1,48 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+
+#include <PiPei.h>
+
+#include <Ppi/DeviceRecoveryModule.h>
+
+#include <Library/RecoveryOemHookLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/ResetSystemLib.h>
+
+#endif
diff --git a/QuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.c b/QuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.c
new file mode 100755
index 0000000..da779ba
--- /dev/null
+++ b/QuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.c
@@ -0,0 +1,79 @@
+/** @file
+ This file includes the function that can be customized by OEM.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+
+/**
+ This function allows the user to force a system recovery
+
+**/
+VOID
+EFIAPI
+OemInitiateRecovery (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ //
+ // Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset
+ //
+ Data32 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW);
+ Data32 |= B_CFG_STICKY_RW_FORCE_RECOVERY;
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW, Data32);
+
+ //
+ // Initialte the warm reset
+ //
+ ResetWarm ();
+}
+
+/**
+ This function allows the user to force a system recovery and deadloop.
+
+ Deadloop required since system should not execute beyond this point.
+ Deadloop should never happen since OemInitiateRecovery () called within
+ this routine should never return since it executes a Warm Reset.
+
+**/
+VOID
+EFIAPI
+OemInitiateRecoveryAndWait (
+ VOID
+ )
+{
+ volatile UINTN Index;
+
+ OemInitiateRecovery ();
+ for (Index = 0; Index == 0;);
+}
diff --git a/QuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.inf b/QuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.inf
new file mode 100755
index 0000000..25ad0e0
--- /dev/null
+++ b/QuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.inf
@@ -0,0 +1,68 @@
+## @file
+# Library Hook Point functions for Intel QNC.
+#
+# This library provides hook points for OEM w.r.t recovery
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RecoveryOemHookLib
+ FILE_GUID = DE6D4FB9-12DB-4dbb-ACF1-92514388355F
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RecoveryOemHookLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ RecoveryOemHookLib.c
+ CommonHeader.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ QNCAccessLib
+ ResetSystemLib
+
+[Ppis]
+ gEfiPeiDeviceRecoveryModulePpiGuid # PPI SOMETIMES_CONSUMED
+
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/CommonHeader.h b/QuarkPlatformPkg/Library/SecureBootHelperLib/CommonHeader.h
new file mode 100644
index 0000000..9c7c931
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/CommonHeader.h
@@ -0,0 +1,118 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ CommonHeader.h
+
+Abstract:
+
+ The common header file for the SecureBootHelperLib component.
+
+--*/
+
+#ifndef _SECUREBOOT_HELPER_LIB_COMMON_HEADER_H_
+#define _SECUREBOOT_HELPER_LIB_COMMON_HEADER_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/TcgService.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/DebugPort.h>
+#include <Protocol/VariableWrite.h>
+#include <Protocol/Security.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DxeServicesLib.h>
+
+#include <Library/BaseCryptLib.h>
+#include <Library/SecurityManagementLib.h>
+#include <Library/PlatformSecureLib.h>
+#include <Guid/AuthenticatedVariableFormat.h>
+#include <Guid/ImageAuthentication.h>
+
+#include <Protocol/SecureBootHelper.h>
+
+//
+// Structure definitions.
+//
+
+/// Private Data shared between modules in this component.
+typedef struct {
+ UINT32 Signature; ///< 32bit structure signature.
+ SECUREBOOT_HELPER_PROTOCOL SBHP; ///< Secure Boot Helper protocol storage.
+ EFI_HANDLE ImageHandle;///< Image handle passed to SecureBootHelperInitialize.
+} SECUREBOOT_HELPER_PRIVATE_DATA;
+
+#define SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('S', 'B', 'H', 'P')
+#define SECUREBOOT_HELPER_PRIVATE_FROM_SBHP(a) CR (a, SECUREBOOT_HELPER_PRIVATE_DATA, SBHP, SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE)
+
+//
+// Prototypes for functions private to this component.
+//
+
+VOID *
+EFIAPI
+MyGetFileBufferByFilePath (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ OUT UINTN *FileSize,
+ OUT UINT32 *AuthenticationStatus
+ );
+
+EFI_STATUS
+EFIAPI
+MyInt2OctStr (
+ IN CONST UINTN *Integer,
+ IN UINTN IntSizeInWords,
+ OUT UINT8 *OctetString,
+ IN UINTN OSSizeInBytes
+ );
+
+//
+// Include prototypes for local source modules.
+//
+#include "SecureBootCrypto.h"
+#include "SecureBootVariable.h"
+#include "SecureBootPeImage.h"
+
+#endif // _SECUREBOOT_HELPER_LIB_COMMON_HEADER_H_
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootCrypto.c b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootCrypto.c
new file mode 100644
index 0000000..aaefb1f
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootCrypto.c
@@ -0,0 +1,185 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SecureBootCrypto.c
+
+Abstract:
+
+ Secure boot crypto. services for Secure Boot Helper Protocol.
+
+--*/
+
+#include "CommonHeader.h"
+
+//
+// OID ASN.1 Value for Hash Algorithms.
+//
+UINT8 mHashOidValueArray[] = {
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5.
+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1.
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224.
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256.
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384.
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512.
+ };
+
+HASH_TABLE mHashTable[] = {
+ { L"SHA1", 20, &mHashOidValueArray[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
+ { L"SHA224", 28, &mHashOidValueArray[13], 9, NULL, NULL, NULL, NULL },
+ { L"SHA256", 32, &mHashOidValueArray[22], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final},
+ { L"SHA384", 48, &mHashOidValueArray[31], 9, NULL, NULL, NULL, NULL },
+ { L"SHA512", 64, &mHashOidValueArray[40], 9, NULL, NULL, NULL, NULL }
+};
+
+/**
+ Caculate hash of multiple buffers using the specified Hash algorithm.
+
+ @param[in] This Pointer to located SECUREBOOT_HELPER_PROTOCOL.
+ @param[in] HashAlg Hash algorithm type see HASHALG_"XXX" defs.
+ @param[in, out] DigestSize Size of Digest, on out set to bytes used in Digest.
+ @param[out] Digest Hash digest written to this buffer.
+ @param ... Pairs of parmas, Buffer Base pointer (A NULL
+ terminates the list) followed by buffer len.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER DigestBuf == NULL or DigestSize == NULL.
+ @retval EFI_BUFFER_TOO_SMALL DigestBuf buffer is too small.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete operation.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+ @retval EFI_UNSUPPORTED The specified algorithm is not supported.
+
+ **/
+EFI_STATUS
+EFIAPI
+HashMultipleBuffers (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST UINT32 HashAlg,
+ IN OUT UINTN *DigestSize,
+ OUT UINT8 *DigestBuf,
+ ...
+ )
+{
+ BOOLEAN Result;
+ EFI_GUID CertType;
+ VOID *HashCtx;
+ UINTN CtxSize;
+ UINT8 *HashBase;
+ UINTN HashSize;
+ VA_LIST Args;
+ UINTN SumOfBytesHashed;
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+
+ //
+ // Verify This pointer.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check params.
+ //
+ if (DigestBuf == NULL || DigestSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ZeroMem (DigestBuf, *DigestSize);
+ if (HashAlg == HASHALG_SHA1) {
+ if (*DigestSize < SHA1_DIGEST_SIZE) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *DigestSize = SHA1_DIGEST_SIZE;
+ CertType = gEfiCertSha1Guid;
+ } else if (HashAlg == HASHALG_SHA256) {
+ if (*DigestSize < SHA256_DIGEST_SIZE) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *DigestSize = SHA256_DIGEST_SIZE;
+ CertType = gEfiCertSha256Guid;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ CtxSize = mHashTable[HashAlg].GetContextSize();
+
+ HashCtx = AllocatePool (CtxSize);
+ if (HashCtx == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize a SHA hash context.
+ //
+ Result = mHashTable[HashAlg].HashInit(HashCtx);
+
+ VA_START (Args, DigestBuf);
+
+ SumOfBytesHashed = 0;
+ while (Result == TRUE) {
+ //
+ // If HashBase is NULL, then it's the end of the list.
+ //
+ HashBase = VA_ARG (Args, UINT8 *);
+ if (HashBase == NULL) {
+ break;
+ }
+ HashSize = VA_ARG (Args, UINTN);
+ Result = mHashTable[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
+ if (Result) {
+ SumOfBytesHashed += HashSize;
+ }
+ }
+ VA_END (Args);
+
+ //
+ // Finalize result.
+ //
+ if (SumOfBytesHashed > 0) {
+ Result = mHashTable[HashAlg].HashFinal(HashCtx, DigestBuf);
+ }
+ else {
+ Result = FALSE;
+ }
+
+ //
+ // Free used resources.
+ //
+ if (HashCtx != NULL) {
+ FreePool (HashCtx);
+ }
+
+ return Result ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+}
+
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootCrypto.h b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootCrypto.h
new file mode 100644
index 0000000..da268b5
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootCrypto.h
@@ -0,0 +1,185 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SecureBootCrypto.h
+
+Abstract:
+
+ Header file for SecureBootCrypto.c.
+
+--*/
+
+#ifndef __SECUREBOOT_HELPER_CRYPTO_HEADER_H_
+#define __SECUREBOOT_HELPER_CRYPTO_HEADER_H_
+
+//
+//
+// PKCS7 Certificate definition.
+//
+typedef struct {
+ WIN_CERTIFICATE Hdr;
+ UINT8 CertData[1];
+} WIN_CERTIFICATE_EFI_PKCS;
+
+/**
+ Retrieves the size, in bytes, of the context buffer required for hash operations.
+
+ @return The size, in bytes, of the context buffer required for hash operations.
+
+**/
+typedef
+UINTN
+(EFIAPI *HASH_GET_CONTEXT_SIZE)(
+ VOID
+ );
+
+/**
+ Initializes user-supplied memory pointed by HashContext as hash context for
+ subsequent use.
+
+ If HashContext is NULL, then ASSERT().
+
+ @param[in, out] HashContext Pointer to Context being initialized.
+
+ @retval TRUE HASH context initialization succeeded.
+ @retval FALSE HASH context initialization failed.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *HASH_INIT)(
+ IN OUT VOID *HashContext
+ );
+
+
+/**
+ Performs digest on a data buffer of the specified length. This function can
+ be called multiple times to compute the digest of long or discontinuous data streams.
+
+ If HashContext is NULL, then ASSERT().
+
+ @param[in, out] HashContext Pointer to the MD5 context.
+ @param[in] Data Pointer to the buffer containing the data to be hashed.
+ @param[in] DataLength Length of Data buffer in bytes.
+
+ @retval TRUE HASH data digest succeeded.
+ @retval FALSE Invalid HASH context. After HashFinal function has been called, the
+ HASH context cannot be reused.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *HASH_UPDATE)(
+ IN OUT VOID *HashContext,
+ IN CONST VOID *Data,
+ IN UINTN DataLength
+ );
+
+/**
+ Completes hash computation and retrieves the digest value into the specified
+ memory. After this function has been called, the context cannot be used again.
+
+ If HashContext is NULL, then ASSERT().
+ If HashValue is NULL, then ASSERT().
+
+ @param[in, out] HashContext Pointer to the MD5 context
+ @param[out] HashValue Pointer to a buffer that receives the HASH digest
+ value.
+
+ @retval TRUE HASH digest computation succeeded.
+ @retval FALSE HASH digest computation failed.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *HASH_FINAL)(
+ IN OUT VOID *HashContext,
+ OUT UINT8 *HashValue
+ );
+
+
+//
+// Hash Algorithm Table
+//
+typedef struct {
+ //
+ // Name for Hash Algorithm.
+ //
+ CHAR16 *Name;
+ //
+ // Digest Length.
+ //
+ UINTN DigestLength;
+ //
+ // Hash Algorithm OID ASN.1 Value.
+ //
+ UINT8 *OidValue;
+ //
+ // Length of Hash OID Value.
+ //
+ UINTN OidLength;
+ //
+ // Pointer to Hash GetContentSize function.
+ //
+ HASH_GET_CONTEXT_SIZE GetContextSize;
+ //
+ // Pointer to Hash Init function.
+ //
+ HASH_INIT HashInit;
+ //
+ // Pointer to Hash Update function.
+ //
+ HASH_UPDATE HashUpdate;
+ //
+ // Pointer to Hash Final function.
+ //
+ HASH_FINAL HashFinal;
+} HASH_TABLE;
+
+extern UINT8 mHashOidValueArray[];
+extern HASH_TABLE mHashTable[];
+
+//
+// Services functions for export in protocols.
+//
+
+EFI_STATUS
+EFIAPI
+HashMultipleBuffers (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST UINT32 HashAlg,
+ IN OUT UINTN *DigestSize,
+ OUT UINT8 *DigestBuf,
+ ...
+ );
+
+#endif // __SECUREBOOT_HELPER_CRYPTO_HEADER_H_
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.c b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.c
new file mode 100644
index 0000000..587761e
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.c
@@ -0,0 +1,241 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SecureBootHelperLib.c
+
+Abstract:
+
+ This component produces the secure boot helper protocol.
+
+--*/
+
+#include "CommonHeader.h"
+
+//
+// Handle for the secure boot helper protocol.
+//
+EFI_HANDLE mSecureBootHelperProtocolHandle = NULL;
+
+/**
+ Convert a nonnegative integer to an octet string of a specified length.
+
+ @param[in] Integer Pointer to the nonnegative integer to be converted.
+ @param[in] IntSizeInWords Length of integer buffer in words.
+ @param[out] OctetString Converted octet string of the specified length.
+ @param[in] OSSizeInBytes Intended length of resulting octet string in bytes.
+
+Returns:
+
+ @retval EFI_SUCCESS Data conversion successfully.
+ @retval EFI_BUFFER_TOOL_SMALL Buffer is too small for output string.
+
+**/
+EFI_STATUS
+EFIAPI
+MyInt2OctStr (
+ IN CONST UINTN *Integer,
+ IN UINTN IntSizeInWords,
+ OUT UINT8 *OctetString,
+ IN UINTN OSSizeInBytes
+ )
+{
+ CONST UINT8 *Ptr1;
+ UINT8 *Ptr2;
+
+ for (Ptr1 = (CONST UINT8 *)Integer, Ptr2 = OctetString + OSSizeInBytes - 1;
+ Ptr1 < (UINT8 *)(Integer + IntSizeInWords) && Ptr2 >= OctetString;
+ Ptr1++, Ptr2--) {
+ *Ptr2 = *Ptr1;
+ }
+
+ for (; Ptr1 < (CONST UINT8 *)(Integer + IntSizeInWords) && *Ptr1 == 0; Ptr1++);
+
+ if (Ptr1 < (CONST UINT8 *)(Integer + IntSizeInWords)) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (Ptr2 >= OctetString) {
+ ZeroMem (OctetString, Ptr2 - OctetString + 1);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the image file buffer data and buffer size by its device path.
+
+ Access the file either from a firmware volume, from a file system interface,
+ or from the load file interface.
+
+ Allocate memory to store the found image. The caller is responsible to free memory.
+
+ If File is NULL, then NULL is returned.
+ If FileSize is NULL, then NULL is returned.
+ If AuthenticationStatus is NULL, then NULL is returned.
+
+ @param[in] FilePath Pointer to the device path of the file that is abstracted to
+ the file buffer.
+ @param[out] FileSize Pointer to the size of the abstracted file buffer.
+ @param[out] AuthenticationStatus Pointer to a caller-allocated UINT32 in which the authentication
+ status is returned.
+
+ @retval NULL File is NULL, or FileSize is NULL, or the file can't be found.
+ @retval other The abstracted file buffer. The caller is responsible to free memory.
+**/
+VOID *
+EFIAPI
+MyGetFileBufferByFilePath (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ OUT UINTN *FileSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+{
+ VOID *FileBuffer;
+ FileBuffer = NULL;
+
+ //
+ // Try to get image by FALSE boot policy for the exact boot file path.
+ //
+ FileBuffer = GetFileBufferByFilePath (FALSE, FilePath, FileSize, AuthenticationStatus);
+ if (FileBuffer == NULL) {
+ //
+ // Try to get image by TRUE boot policy for the inexact boot file path.
+ //
+ FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, AuthenticationStatus);
+ }
+ return FileBuffer;
+}
+
+/** Check if platform is operating by a physically present user.
+
+ This function provides a platform-specific method to detect whether the platform
+ is operating by a physically present user.
+
+ Programmatic changing of platform security policy (such as disable Secure Boot,
+ or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during
+ Boot Services or after exiting EFI Boot Services. Only a physically present user
+ is allowed to perform these operations.
+
+ NOTE THAT: This function cannot depend on any EFI Variable Service since they are
+ not available when this function is called in AuthenticateVariable driver.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval TRUE The platform is operated by a physically present user.
+ @retval FALSE The platform is NOT operated by a physically present user.
+
+**/
+BOOLEAN
+EFIAPI
+IsUserPhysicalPresent (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+ ASSERT (This != NULL);
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ ASSERT (PrivateData->Signature == SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE);
+
+ return UserPhysicalPresent ();
+}
+
+/**
+ Installs Secure Boot Helper Protocol.
+
+ @param ImageHandle The image handle of this driver.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS Install the Secure Boot Helper Protocol successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SecureBootHelperInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+
+ //
+ // Create & Init a private data structure.
+ //
+ PrivateData = AllocateZeroPool (sizeof (SECUREBOOT_HELPER_PRIVATE_DATA));
+ if (PrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ PrivateData->ImageHandle = ImageHandle;
+ PrivateData->Signature = SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE;
+ PrivateData->SBHP.IsUserPhysicalPresent = IsUserPhysicalPresent;
+ PrivateData->SBHP.HashMultipleBuffers = HashMultipleBuffers;
+ PrivateData->SBHP.LoadPeImage = LoadPeImage;
+ PrivateData->SBHP.IsSecureBootEnabled = IsSecureBootEnabled;
+ PrivateData->SBHP.IsSecureBootInCustomMode = IsSecureBootInCustomMode;
+ PrivateData->SBHP.SetupSetSecureBootCustomMode = SetupSetSecureBootCustomMode;
+ PrivateData->SBHP.SetupSetSecureBootDefaultMode = SetupSetSecureBootDefaultMode;
+ PrivateData->SBHP.SetupCreateTimeBasedAuthVarPayload = SetupCreateTimeBasedAuthVarPayload;
+ PrivateData->SBHP.SetupSetTimeBasedAuthVariable = SetupSetTimeBasedAuthVariable;
+ PrivateData->SBHP.SetupDeleteCert = SetupDeleteCert;
+ PrivateData->SBHP.SetupAppendCert = SetupAppendCert;
+ PrivateData->SBHP.FindFirstCert = FindFirstCert;
+ PrivateData->SBHP.FindNextCert = FindNextCert;
+ PrivateData->SBHP.FindCertClose = FindCertClose;
+ PrivateData->SBHP.IsPkEnrolled = IsPkEnrolled;
+ PrivateData->SBHP.SetupEnrollX509 = SetupEnrollX509;
+ PrivateData->SBHP.SetupEnrollKekRsa2048 = SetupEnrollKekRsa2048;
+ PrivateData->SBHP.SetupEnrollImageSignature = SetupEnrollImageSignature;
+ PrivateData->SBHP.SetupDeleteStoreRecord = SetupDeleteStoreRecord;
+ PrivateData->SBHP.GetImageFromMask = GetImageFromMask;
+ PrivateData->SBHP.GetSecureBootVarStats = GetSecureBootVarStats;
+ PrivateData->SBHP.SetupCreateTimeBasedAuthVar = SetupCreateTimeBasedAuthVar;
+ PrivateData->SBHP.SetupCreateEmptyDbDbxIfNotExist = SetupCreateEmptyDbDbxIfNotExist;
+
+ //
+ // Make sure the Secure Boot Helper DXE Protocol is not already installed
+ // in the system.
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gSecureBootHelperProtocolGuid);
+
+ //
+ // Install the SecureBoot Helper Protocol onto a new handle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mSecureBootHelperProtocolHandle,
+ &gSecureBootHelperProtocolGuid,
+ &PrivateData->SBHP,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.inf b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.inf
new file mode 100644
index 0000000..7086a07
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.inf
@@ -0,0 +1,98 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# SecureBootHelperLib.inf
+#
+# Abstract:
+#
+# This library produces the secure boot helper protocol.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecureBootHelperDxeLib
+ FILE_GUID = 906F3610-8FDA-4cac-93FC-50E1F5C77812
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = SecureBootHelperInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CommonHeader.h
+ SecureBootHelperLib.c
+ SecureBootVariable.h
+ SecureBootVariable.c
+ SecureBootPeImage.h
+ SecureBootPeImage.c
+ SecureBootCrypto.h
+ SecureBootCrypto.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CryptoPkg/CryptoPkg.dec
+ SecurityPkg/SecurityPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ DebugLib
+ BaseCryptLib
+ SecurityManagementLib
+ PlatformSecureLib
+ DxeServicesLib
+
+[Protocols]
+ gSecureBootHelperProtocolGuid ## PRODUCED
+
+[Guids]
+ gEfiGlobalVariableGuid
+ gEfiCustomModeEnableGuid
+ gEfiSecureBootEnableDisableGuid
+ gEfiCertPkcs7Guid
+ gEfiCertRsa2048Guid ## CONSUMES
+ gEfiCertX509Guid ## CONSUMES
+ gEfiCertSha1Guid ## CONSUMES
+ gEfiCertSha256Guid ## CONSUMES
+ gEfiCertTypeRsa2048Sha256Guid ## CONSUMES
+ gEfiImageSecurityDatabaseGuid ## CONSUMES
+
+[Pcd]
+
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootPeImage.c b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootPeImage.c
new file mode 100644
index 0000000..5018e37
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootPeImage.c
@@ -0,0 +1,711 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SecureBootPeImage.c
+
+Abstract:
+
+ Secure boot PE Image file services for Secure Boot Helper Protocol.
+
+--*/
+
+#include "CommonHeader.h"
+
+/**
+ Calculate hash of Pe/Coff image based on the authenticode image hashing in
+ PE/COFF Specification 8.0 Appendix A
+
+ if on return LoadInfo->ImageDigestSize == 0 then hash failed.
+
+ @param[in out] LoadInfo On in basic file load info; on also hash info.
+ @param[in] HashAlg Hash algorithm type.
+
+ @retval TRUE Successfully hash image.
+ @retval FALSE Fail in hash image.
+
+**/
+STATIC
+BOOLEAN
+HashPeImage (
+ IN OUT SECUREBOOT_PEIMAGE_LOAD_INFO *LoadInfo,
+ IN UINT32 HashAlg
+ )
+{
+ BOOLEAN Ok;
+ UINT16 Magic;
+ EFI_IMAGE_SECTION_HEADER *Section;
+ VOID *HashCtx;
+ UINTN CtxSize;
+ UINT8 *HashBase;
+ UINTN HashSize;
+ UINTN SumOfBytesHashed;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ UINTN Index;
+ UINTN Pos;
+ UINTN ImageDigestSize;
+
+ ASSERT (LoadInfo != NULL);
+ if (LoadInfo == NULL) {
+ return FALSE;
+ }
+ HashCtx = NULL;
+ SectionHeader = NULL;
+ Ok = FALSE;
+
+ LoadInfo->ImageDigestSize = ImageDigestSize = 0;
+
+ if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {
+ return FALSE;
+ }
+
+ //
+ // Initialize context of hash.
+ //
+ ZeroMem (LoadInfo->ImageDigest, sizeof(LoadInfo->ImageDigest));
+
+ if (HashAlg == HASHALG_SHA1) {
+ ImageDigestSize = SHA1_DIGEST_SIZE;
+ CopyGuid (&LoadInfo->ImageCertType, &gEfiCertSha1Guid);
+ } else if (HashAlg == HASHALG_SHA256) {
+ ImageDigestSize = SHA256_DIGEST_SIZE;
+ CopyGuid (&LoadInfo->ImageCertType, &gEfiCertSha256Guid);
+ }
+ if (ImageDigestSize > sizeof(LoadInfo->ImageDigest)) {
+ return FALSE;
+ }
+
+ CtxSize = mHashTable[HashAlg].GetContextSize();
+
+ HashCtx = AllocatePool (CtxSize);
+ ASSERT (HashCtx != NULL);
+ if (HashCtx == NULL) {
+ return FALSE;
+ }
+
+ // 1. Load the image header into memory.
+
+ // 2. Initialize a SHA hash context.
+ Ok = mHashTable[HashAlg].HashInit(HashCtx);
+ if (!Ok) {
+ goto Done;
+ }
+ //
+ // Measuring PE/COFF Image Header;
+ // But CheckSum field and SECURITY data directory (certificate) are excluded
+ // Get the magic value from the PE/COFF Optional Header
+ //
+ if (LoadInfo->NtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && LoadInfo->NtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
+ // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+ // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ } else {
+ Magic = LoadInfo->NtHeader.Pe32->OptionalHeader.Magic;
+ }
+
+ //
+ // 3. Calculate the distance from the base of the image header to the image checksum address.
+ // 4. Hash the image header from its base to beginning of the image checksum.
+ //
+ HashBase = LoadInfo->ImageBase;
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ HashSize = (UINTN) ((UINT8 *) (&LoadInfo->NtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashSize = (UINTN) ((UINT8 *) (&LoadInfo->NtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
+ }
+
+ Ok = mHashTable[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
+ if (!Ok) {
+ goto Done;
+ }
+ //
+ // 5. Skip over the image checksum (it occupies a single ULONG).
+ // 6. Get the address of the beginning of the Cert Directory.
+ // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
+ //
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ HashBase = (UINT8 *) &LoadInfo->NtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = (UINTN) ((UINT8 *) (&LoadInfo->NtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashBase = (UINT8 *) &LoadInfo->NtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = (UINTN) ((UINT8 *) (&LoadInfo->NtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
+ }
+
+ Ok = mHashTable[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
+ if (!Ok) {
+ goto Done;
+ }
+ //
+ // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
+ // 9. Hash everything from the end of the Cert Directory to the end of image header.
+ //
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset
+ //
+ HashBase = (UINT8 *) &LoadInfo->NtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
+ HashSize = LoadInfo->NtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&LoadInfo->NtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - LoadInfo->ImageBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashBase = (UINT8 *) &LoadInfo->NtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
+ HashSize = LoadInfo->NtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&LoadInfo->NtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - LoadInfo->ImageBase);
+ }
+
+ Ok = mHashTable[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
+ if (!Ok) {
+ goto Done;
+ }
+ //
+ // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
+ //
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ SumOfBytesHashed = LoadInfo->NtHeader.Pe32->OptionalHeader.SizeOfHeaders;
+ } else {
+ //
+ // Use PE32+ offset
+ //
+ SumOfBytesHashed = LoadInfo->NtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
+ }
+
+ //
+ // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
+ // structures in the image. The 'NumberOfSections' field of the image
+ // header indicates how big the table should be. Do not include any
+ // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * LoadInfo->NtHeader.Pe32->FileHeader.NumberOfSections);
+ ASSERT (SectionHeader != NULL);
+ //
+ // 12. Using the 'PointerToRawData' in the referenced section headers as
+ // a key, arrange the elements in the table in ascending order. In other
+ // words, sort the section headers according to the disk-file offset of
+ // the section.
+ //
+ Section = (EFI_IMAGE_SECTION_HEADER *) (
+ LoadInfo->ImageBase +
+ LoadInfo->PeCoffHdrOff +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ LoadInfo->NtHeader.Pe32->FileHeader.SizeOfOptionalHeader
+ );
+ for (Index = 0; Index < LoadInfo->NtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
+ Pos = Index;
+ while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
+ CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
+ Pos--;
+ }
+ CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
+ Section += 1;
+ }
+
+ //
+ // 13. Walk through the sorted table, bring the corresponding section
+ // into memory, and hash the entire section (using the 'SizeOfRawData'
+ // field in the section header to determine the amount of data to hash).
+ // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
+ // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
+ //
+ for (Index = 0; Index < LoadInfo->NtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
+ Section = &SectionHeader[Index];
+ if (Section->SizeOfRawData == 0) {
+ continue;
+ }
+ HashBase = LoadInfo->ImageBase + Section->PointerToRawData;
+ HashSize = (UINTN) Section->SizeOfRawData;
+
+ Ok = mHashTable[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
+ if (!Ok) {
+ goto Done;
+ }
+
+ SumOfBytesHashed += HashSize;
+ }
+
+ //
+ // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
+ // data in the file that needs to be added to the hash. This data begins
+ // at file offset SUM_OF_BYTES_HASHED and its length is:
+ // FileSize - (CertDirectory->Size)
+ //
+ if (LoadInfo->ImageSize > SumOfBytesHashed) {
+ HashBase = LoadInfo->ImageBase + SumOfBytesHashed;
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ HashSize = (UINTN)(
+ LoadInfo->ImageSize -
+ LoadInfo->NtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
+ SumOfBytesHashed);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashSize = (UINTN)(
+ LoadInfo->ImageSize -
+ LoadInfo->NtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
+ SumOfBytesHashed);
+ }
+
+ Ok = mHashTable[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
+ if (!Ok) {
+ goto Done;
+ }
+ }
+
+ Ok = mHashTable[HashAlg].HashFinal(HashCtx, LoadInfo->ImageDigest);
+
+Done:
+ if (HashCtx != NULL) {
+ FreePool (HashCtx);
+ }
+ if (SectionHeader != NULL) {
+ FreePool (SectionHeader);
+ }
+ if (Ok) {
+ LoadInfo->ImageDigestSize = ImageDigestSize;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
+ Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
+ 8.0 Appendix A.
+
+ if on return LoadInfo->ImageDigestSize == 0 then hash failed.
+
+ @param[in out] LoadInfo On in basic file load info; on also hash info.
+
+ @retval EFI_UNSUPPORTED Hash algorithm is not supported.
+ @retval EFI_SUCCESS Hash successfully.
+
+**/
+STATIC
+EFI_STATUS
+HashPeImageByType (
+ IN OUT SECUREBOOT_PEIMAGE_LOAD_INFO *LoadInfo
+ )
+{
+ UINT8 Index;
+ WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
+
+ PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (LoadInfo->ImageBase + LoadInfo->SecDataDir->Offset);
+
+ for (Index = 0; Index < HASHALG_MAX; Index++) {
+ //
+ // Check the Hash algorithm in PE/COFF Authenticode.
+ // According to PKCS#7 Definition:
+ // SignedData ::= SEQUENCE {
+ // version Version,
+ // digestAlgorithms DigestAlgorithmIdentifiers,
+ // contentInfo ContentInfo,
+ // .... }
+ // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
+ // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
+ // Fixed offset (+32) is calculated based on two bytes of length encoding.
+ //
+ if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
+ //
+ // Only support two bytes of Long Form of Length Encoding.
+ //
+ continue;
+ }
+
+ if (CompareMem (PkcsCertData->CertData + 32, mHashTable[Index].OidValue, mHashTable[Index].OidLength) == 0) {
+ break;
+ }
+ }
+
+ if (Index == HASHALG_MAX) {
+ LoadInfo->ImageDigestSize = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
+ //
+ if (!HashPeImage(LoadInfo, Index)) {
+ LoadInfo->ImageDigestSize = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Load PE/COFF image information into buffer and check its validity.
+
+ Function returns Pointer to SECUREBOOT_PEIMAGE_LOAD_INFO see
+ Protocol/SecureBootHelperDxe.h.
+
+ Function also calculates HASH of image if CalcHash param == TRUE.
+ If SecurityCert in image then hash algo. is the algo specified by the
+ SecurityCert else a SHA256 digest is calculated.
+
+ Caller must FreePool returned pointer when they are finished.
+
+ @param[in] FileDevicePath Device Path of PE image file.
+ @param[in] CalcHash Flag to tell loader to calc. hash of image.
+
+ @retval NULL unable to load image.
+ @return Pointer to SECUREBOOT_PEIMAGE_LOAD_INFO struct which contains is a
+ memory block with image info and actual image data.
+
+**/
+SECUREBOOT_PEIMAGE_LOAD_INFO *
+LoadPeImageWork (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST BOOLEAN CalcHash
+ )
+{
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_NT_HEADERS32 *NtHeader32;
+ EFI_IMAGE_NT_HEADERS64 *NtHeader64;
+ UINT32 AStat;
+ WIN_CERTIFICATE_UEFI_GUID *GuidCertData;
+ SECUREBOOT_PEIMAGE_LOAD_INFO *LoadInfo;
+ UINT8 *FirstAlloc;
+ UINTN FirstAllocSize;
+
+ if (FileDevicePath == NULL) {
+ return NULL;
+ }
+
+ FirstAlloc = MyGetFileBufferByFilePath (
+ FileDevicePath,
+ &FirstAllocSize,
+ &AStat);
+
+ if (FirstAlloc == NULL) {
+ return NULL;
+ }
+ LoadInfo = AllocatePool (sizeof (*LoadInfo) + FirstAllocSize + 16);
+ if (LoadInfo == NULL) {
+ FreePool (FirstAlloc);
+ return NULL;
+ }
+ ZeroMem (LoadInfo, sizeof (*LoadInfo));
+ LoadInfo->ImageBase = (UINT8 *) LoadInfo;
+
+ LoadInfo->ImageBase = ALIGN_POINTER (
+ (LoadInfo->ImageBase + sizeof (*LoadInfo)),
+ sizeof (UINT64)
+ );
+ LoadInfo->ImageSize = FirstAllocSize;
+ CopyMem (LoadInfo->ImageBase, FirstAlloc, FirstAllocSize);
+ FreePool (FirstAlloc);
+
+ NtHeader32 = NULL;
+ NtHeader64 = NULL;
+
+ //
+ // Read the Dos header
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER*) (LoadInfo->ImageBase);
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
+ {
+ //
+ // DOS image header is present,
+ // So read the PE header after the DOS image header
+ //
+ LoadInfo->PeCoffHdrOff = DosHdr->e_lfanew;
+ } else {
+ LoadInfo->PeCoffHdrOff = 0;
+ }
+
+ //
+ // Read PE header and check the signature validity and machine compatibility
+ //
+ NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (LoadInfo->ImageBase + LoadInfo->PeCoffHdrOff);
+ if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ FreePool (LoadInfo);
+ return NULL;
+ }
+
+ LoadInfo->NtHeader.Pe32 = NtHeader32;
+
+ //
+ // Check the architecture field of PE header and get the Certificate Data Directory data
+ // Note the size of FileHeader field is constant for both IA32 and X64 arch
+ //
+ if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)
+ || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)) {
+ //
+ // IA-32 Architecture
+ //
+ LoadInfo->ImageType = ImageType_IA32;
+ LoadInfo->SecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
+ } else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)
+ || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)) {
+ //
+ // 64-bits Architecture
+ //
+ LoadInfo->ImageType = ImageType_X64;
+ NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (LoadInfo->ImageBase + LoadInfo->PeCoffHdrOff);
+ LoadInfo->SecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
+ } else {
+ FreePool (LoadInfo);
+ return NULL;
+ }
+
+ if (LoadInfo->SecDataDir->SizeOfCert != 0) {
+ //
+ // Get the certificate data pointer.
+ //
+ LoadInfo->Certificate = (WIN_CERTIFICATE *) (LoadInfo->ImageBase + LoadInfo->SecDataDir->Offset);
+ }
+
+ if (CalcHash) {
+ if (LoadInfo->Certificate == NULL) {
+
+ HashPeImage (LoadInfo, HASHALG_SHA256);
+ } else {
+ if (LoadInfo->Certificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
+ GuidCertData = (WIN_CERTIFICATE_UEFI_GUID *) LoadInfo->Certificate;
+ if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) == 0) {
+ HashPeImage (LoadInfo, HASHALG_SHA256);
+ }
+ } else if (LoadInfo->Certificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+ HashPeImageByType (LoadInfo);
+ } else {
+ LoadInfo->ImageDigestSize = 0;
+ }
+ }
+ }
+
+ return LoadInfo;
+}
+
+/** Load PE/COFF image information into buffer and check its validity.
+
+ Function returns Pointer to SECUREBOOT_PEIMAGE_LOAD_INFO see
+ Protocol/SecureBootHelperDxe.h.
+
+ Function also calculates HASH of image if CalcHash param == TRUE.
+ If SecurityCert in image then hash algo. is the algo specified by the
+ Cert else a SHA256 digest is calculated.
+
+ Caller must FreePool returned pointer when they are finished.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] FileDevicePath Device Path of PE image file.
+ @param[in] CalcHash Flag to tell loader to calc. hash of image.
+
+ @retval NULL unable to load image.
+ @return Pointer to SECUREBOOT_PEIMAGE_LOAD_INFO struct which contains is a
+ memory block with image info and actual image data.
+
+**/
+SECUREBOOT_PEIMAGE_LOAD_INFO *
+EFIAPI
+LoadPeImage (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST BOOLEAN CalcHash
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+
+ //
+ // Verify This pointer.
+ //
+ if (This == NULL) {
+ return NULL;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return NULL;
+ }
+
+ return LoadPeImageWork (FileDevicePath, CalcHash);
+}
+
+/** Get the file image from mask.
+
+ If This or File is NULL, then ASSERT().
+ If sanity checks on This pointer fail then assert.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] File This is a pointer to the device path of the file
+ to get IMAGE_FROM_XXX mask for.
+
+ @return UINT32 Mask which is one of IMAGE_FROM_XXX defs in protocol header file.
+
+**/
+UINT32
+EFIAPI
+GetImageFromMask (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ //
+ // Verify This pointer.
+ //
+ ASSERT (This != NULL);
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ ASSERT (PrivateData->Signature == SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE);
+ ASSERT (File != NULL);
+
+ //
+ // First check to see if File is from a Firmware Volume
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
+ Status = gBS->LocateDevicePath (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ DeviceHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return IMAGE_FROM_FV;
+ }
+ }
+
+ //
+ // Next check to see if File is from a Block I/O device
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
+ Status = gBS->LocateDevicePath (
+ &gEfiBlockIoProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ BlockIo = NULL;
+ Status = gBS->OpenProtocol (
+ DeviceHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status) && BlockIo != NULL) {
+ if (BlockIo->Media != NULL) {
+ if (BlockIo->Media->RemovableMedia) {
+ //
+ // Block I/O is present and specifies the media is removable
+ //
+ return IMAGE_FROM_REMOVABLE_MEDIA;
+ } else {
+ //
+ // Block I/O is present and specifies the media is not removable
+ //
+ return IMAGE_FROM_FIXED_MEDIA;
+ }
+ }
+ }
+ }
+
+ //
+ // File is not in a Firmware Volume or on a Block I/O device, so check to see if
+ // the device path supports the Simple File System Protocol.
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
+ Status = gBS->LocateDevicePath (
+ &gEfiSimpleFileSystemProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Simple File System is present without Block I/O, so assume media is fixed.
+ //
+ return IMAGE_FROM_FIXED_MEDIA;
+ }
+
+ //
+ // File is not from an FV, Block I/O or Simple File System, so the only options
+ // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
+ //
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
+ while (!IsDevicePathEndType (TempDevicePath)) {
+ switch (DevicePathType (TempDevicePath)) {
+
+ case MEDIA_DEVICE_PATH:
+ if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
+ return IMAGE_FROM_OPTION_ROM;
+ }
+ break;
+
+ case MESSAGING_DEVICE_PATH:
+ if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
+ return IMAGE_FROM_PXE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+ return IMAGE_UNKNOWN;
+}
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootPeImage.h b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootPeImage.h
new file mode 100644
index 0000000..ff02d12
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootPeImage.h
@@ -0,0 +1,73 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SecureBootPeImage.h
+
+Abstract:
+
+ Header file for SecureBootPeImage.c.
+
+--*/
+
+#ifndef __SECUREBOOT_HELPER_PEIMAGE_HEADER_H_
+#define __SECUREBOOT_HELPER_PEIMAGE_HEADER_H_
+
+//
+// Worker functions for use within this component.
+//
+
+SECUREBOOT_PEIMAGE_LOAD_INFO *
+LoadPeImageWork (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST BOOLEAN CalcHash
+ );
+
+//
+// Services functions for export in protocols.
+//
+
+SECUREBOOT_PEIMAGE_LOAD_INFO *
+EFIAPI
+LoadPeImage (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST BOOLEAN CalcHash
+ );
+
+UINT32
+EFIAPI
+GetImageFromMask (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File
+ );
+
+#endif // __SECUREBOOT_HELPER_PEIMAGE_HEADER_H_
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootVariable.c b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootVariable.c
new file mode 100644
index 0000000..efa9868
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootVariable.c
@@ -0,0 +1,1694 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SecureBootVariable.c
+
+Abstract:
+
+ Secure boot variable services for Secure Boot Helper Protocol.
+
+--*/
+
+#include "CommonHeader.h"
+
+//
+// Routines local to this source module.
+//
+
+STATIC
+UINTN
+GetSecureBootCertVarStats (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINT32 *AttrPtr,
+ OUT UINTN *TotalCertCountPtr,
+ OUT UINTN *X509CertCountPtr OPTIONAL,
+ OUT UINTN *Rsa2048CertCountPtr OPTIONAL,
+ OUT UINTN *OtherCertCountPtr OPTIONAL,
+ OUT UINTN *Sha256CountPtr OPTIONAL,
+ OUT UINTN *Sha1CountPtr OPTIONAL
+ )
+{
+ VOID *FindContext;
+ EFI_SIGNATURE_LIST *CertList;
+ EFI_SIGNATURE_DATA *CertData;
+ FIND_CERT_STATS VarStats;
+
+ *AttrPtr = 0;
+ *TotalCertCountPtr = 0;
+ if (X509CertCountPtr) {
+ *X509CertCountPtr = 0;
+ }
+ if (Rsa2048CertCountPtr) {
+ *Rsa2048CertCountPtr = 0;
+ }
+ if (OtherCertCountPtr) {
+ *OtherCertCountPtr = 0;
+ }
+ if (Sha256CountPtr) {
+ *Sha256CountPtr = 0;
+ }
+ if (Sha1CountPtr) {
+ *Sha1CountPtr = 0;
+ }
+
+ FindContext = FindFirstCert (
+ This,
+ VariableName,
+ VendorGuid,
+ NULL,
+ &CertList,
+ &CertData,
+ &VarStats
+ );
+
+ if (FindContext == NULL) {
+ return 0;
+ }
+ ASSERT (VarStats.VariableSize > 0);
+ *AttrPtr = VarStats.VariableAttributes;
+
+ do {
+ *TotalCertCountPtr = *TotalCertCountPtr + 1;
+ if (CompareGuid (&gEfiCertSha256Guid, &CertList->SignatureType)) {
+ if (Sha256CountPtr) {
+ *Sha256CountPtr = *Sha256CountPtr + 1;
+ }
+ } else if (CompareGuid (&gEfiCertRsa2048Guid, &CertList->SignatureType)) {
+ if (Rsa2048CertCountPtr) {
+ *Rsa2048CertCountPtr = *Rsa2048CertCountPtr + 1;
+ }
+ } else if (CompareGuid (&gEfiCertX509Guid, &CertList->SignatureType)) {
+ if (X509CertCountPtr) {
+ *X509CertCountPtr = *X509CertCountPtr + 1;
+ }
+ } else if (CompareGuid (&gEfiCertSha1Guid, &CertList->SignatureType)) {
+ if (Sha1CountPtr) {
+ *Sha1CountPtr = *Sha1CountPtr + 1;
+ }
+ } else {
+ if (OtherCertCountPtr) {
+ *OtherCertCountPtr = *OtherCertCountPtr + 1;
+ }
+ }
+
+ CertList = FindNextCert (
+ FindContext,
+ NULL,
+ CertList,
+ &CertData
+ );
+ } while (CertList != NULL);
+ FindCertClose (FindContext);
+ return VarStats.VariableSize;
+}
+
+//
+// Routines exported by this source module.
+//
+
+/** Check if secure boot enabled.
+
+ @retval TRUE Secure Boot enabled.
+ @retval FALSE Secure Boot disabled.
+
+**/
+BOOLEAN
+EFIAPI
+IsSecureBootEnabledWork (
+ VOID
+ )
+{
+ UINT8 *SecureBootEnable;
+ BOOLEAN Result;
+
+ GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
+ if (SecureBootEnable == NULL) {
+ DEBUG ((EFI_D_INFO, "SecureBootHelper:IsSecureBootEnabled %s not found\n", EFI_SECURE_BOOT_ENABLE_NAME));
+ return FALSE;
+ }
+
+ Result = (*SecureBootEnable == SECURE_BOOT_ENABLE);
+ FreePool (SecureBootEnable);
+
+ return Result;
+}
+
+/** Check if secure boot enabled.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval TRUE Secure Boot enabled.
+ @retval FALSE Secure Boot disabled.
+
+**/
+BOOLEAN
+EFIAPI
+IsSecureBootEnabled (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+
+ ASSERT (This != NULL);
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ ASSERT (PrivateData->Signature == SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE);
+
+ return IsSecureBootEnabledWork ();;
+}
+
+/** Check if secure boot mode is in custom mode.
+
+ @retval TRUE Secure Boot mode is in custom mode.
+ @retval FALSE Secure Boot mode is NOT in custom mode.
+
+**/
+BOOLEAN
+EFIAPI
+IsSecureBootInCustomModeWork (
+ VOID
+ )
+{
+ UINT8 *Mode;
+ BOOLEAN Result;
+
+ GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&Mode, NULL);
+ if (Mode == NULL) {
+ return FALSE;
+ }
+
+ Result = (*Mode == CUSTOM_SECURE_BOOT_MODE);
+ FreePool (Mode);
+ return Result;
+}
+
+/** Check if secure boot mode is in custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval TRUE Secure Boot mode is in custom mode.
+ @retval FALSE Secure Boot mode is NOT in custom mode.
+
+**/
+BOOLEAN
+EFIAPI
+IsSecureBootInCustomMode (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+
+ ASSERT (This != NULL);
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ ASSERT (PrivateData->Signature == SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE);
+
+ return IsSecureBootInCustomModeWork ();
+}
+
+/** Set Secure Boot Mode to Custom Mode.
+
+ To be called when for SecureBoot in Setup or when the platform
+ is operating by a physically present user..
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval EFI_SUCCESS Set success.
+ @retval EFI_ACCESS_DENIED Can't set mode if Secure Boot enabled.
+ @retval EFI_INVALID_PARAMETER This pointer is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @return Other Unexpected error - unable to verify.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupSetSecureBootCustomMode (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+ UINT8 Mode;
+
+ //
+ // Verify This pointer.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Mode = CUSTOM_SECURE_BOOT_MODE;
+ return gRT->SetVariable (
+ EFI_CUSTOM_MODE_NAME,
+ &gEfiCustomModeEnableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (UINT8),
+ &Mode
+ );
+}
+
+/** Set Secure Boot Mode to default security Mode.
+
+ To be called when for SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval EFI_SUCCESS Set success.
+ @retval EFI_ACCESS_DENIED Can't set mode if Secure Boot enabled.
+ @retval EFI_INVALID_PARAMETER This pointer is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @return Other Unexpected error - unable to verify.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupSetSecureBootDefaultMode (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+ UINT8 Mode;
+
+ //
+ // Verify This pointer.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Mode = STANDARD_SECURE_BOOT_MODE;
+ return gRT->SetVariable (
+ EFI_CUSTOM_MODE_NAME,
+ &gEfiCustomModeEnableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (UINT8),
+ &Mode
+ );
+}
+
+/**
+ Create time based authenticated variable playload for SecureBoot Setup Mode.
+
+ Also work in SecureBoot Custom Mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in, out] DataSize On input, the size of Data buffer in bytes.
+ On output, the size of data returned in Data
+ buffer in bytes.
+ @param[in, out] Data On input, Pointer to data buffer to be wrapped or
+ pointer to NULL to wrap an empty payload.
+ On output, Pointer to the new payload date buffer allocated from pool,
+ it's caller's responsibility to free the memory when finish using it.
+
+ @retval EFI_SUCCESS Create time based payload successfully.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval Others Unexpected error happens.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupCreateTimeBasedAuthVarPayload (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT8 **Data
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *NewData;
+ UINT8 *Payload;
+ UINTN PayloadSize;
+ EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;
+ UINTN DescriptorSize;
+ EFI_TIME Time;
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+
+ //
+ // Verify This pointer.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Payload = *Data;
+ PayloadSize = *DataSize;
+
+ DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
+ NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
+ if (NewData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if ((Payload != NULL) && (PayloadSize != 0)) {
+ CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
+ }
+
+ //
+ // In Setup mode or Custom mode, the variable does not need to be signed but the
+ // parameters to the SetVariable() call still need to be prepared as authenticated
+ // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
+ // data in it.
+ //
+
+ DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
+
+ Status = gRT->GetTime (&Time, NULL);
+ if (EFI_ERROR (Status)) { // Don't fail if no time.
+ ZeroMem (&Time, sizeof (EFI_TIME));
+ DEBUG ((EFI_D_ERROR, "SecureBootHelper:CreateAuthVarPayload Auth Var With Zero Time\n"));
+ } else {
+ Time.Pad1 = 0;
+ Time.Nanosecond = 0;
+ Time.TimeZone = 0;
+ Time.Daylight = 0;
+ Time.Pad2 = 0;
+ }
+ CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
+
+ DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
+ DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;
+ DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
+ CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
+
+ *DataSize = DescriptorSize + PayloadSize;
+ *Data = NewData;
+ return EFI_SUCCESS;
+}
+
+/** Set authenticated variable for SecureBoot in Setup or Custom mode.
+
+ This code sets an authenticated variable in storage blocks
+ (Volatile or Non-Volatile).
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName Name of Variable to set.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] Attr Attribute value of the variable found
+ @param[in] DataSize Size of Data found. If size is less than the
+ data, this value contains the required size.
+ @param[in] Data Data pointer.
+ @param[in] AppendIfExists If TRUE then force append of data if var exists.
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_SUCCESS Set successfully.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_WRITE_PROTECTED Variable is read-only.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupSetTimeBasedAuthVariable (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attr,
+ IN UINTN DataSize,
+ IN UINT8 *Data,
+ IN BOOLEAN AppendIfExists
+ )
+{
+ EFI_STATUS Status;
+ IN UINT8 *DescAndData;
+ IN UINTN DescAndDataSize;
+ UINTN VarSize;
+
+ DescAndData = Data;
+ DescAndDataSize = DataSize;
+
+ Status = SetupCreateTimeBasedAuthVarPayload (This, &DescAndDataSize, &DescAndData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SecureBootHelper:CreateAuthVarPayload Failed %r", Status));
+ } else {
+ //
+ // Check if Auth variable has been already existed.
+ // If AppendIfExists, use EFI_VARIABLE_APPEND_WRITE attribute to append the
+ // new signature data to original variable
+ //
+ VarSize = 0;
+
+ Status = gRT->GetVariable(
+ VariableName,
+ VendorGuid,
+ NULL,
+ &VarSize,
+ NULL
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL || Status == EFI_NOT_FOUND) {
+ if (Status == EFI_BUFFER_TOO_SMALL && AppendIfExists) {
+ Attr |= EFI_VARIABLE_APPEND_WRITE;
+ }
+ //
+ // Set the variable.
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ VendorGuid,
+ Attr,
+ DescAndDataSize,
+ DescAndData
+ );
+ DEBUG ((EFI_D_INFO, "SecureBootHelper:SetAuthVar %r '%s':0x%08x:%g\n", Status, VariableName, Attr, VendorGuid));
+ }
+ }
+ if (DescAndData != Data) {
+ FreePool (DescAndData);
+ }
+ return Status;
+}
+
+/** Delete entry from secure boot database for SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName The variable name of the vendor's signature database.
+ @param[in] VendorGuid A unique identifier for the vendor.
+ @param[in] SignatureOwner Signature GUID to delete.
+
+ @retval EFI_SUCCESS Delete cert success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Can't find the cert item.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+
+ **/
+EFI_STATUS
+EFIAPI
+SetupDeleteCert (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST EFI_GUID *SignatureOwner
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+ UINTN DataSize;
+ UINT8 *Data;
+ UINT8 *OldData;
+ UINT32 Attr;
+ UINT32 Index;
+ EFI_SIGNATURE_LIST *CertList;
+ EFI_SIGNATURE_LIST *NewCertList;
+ EFI_SIGNATURE_DATA *Cert;
+ UINTN CertCount;
+ UINT32 Offset;
+ UINT32 FullDeleteOffset;
+ BOOLEAN IsItemFound;
+ UINT32 ItemDataSize;
+
+ //
+ // Verify This pointer.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SignatureOwner == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data = NULL;
+ OldData = NULL;
+ Cert = NULL;
+ Attr = 0;
+
+ //
+ // Get original signature list data.
+ //
+ DataSize = 0;
+ Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
+ if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+ return (Status);
+ }
+
+ OldData = (UINT8 *) AllocateZeroPool (DataSize);
+ if (OldData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
+ if (!EFI_ERROR(Status)) {
+ //
+ // Allocate space for new variable.
+ //
+ Data = (UINT8*) AllocateZeroPool (DataSize);
+ if (Data == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ if (Data != NULL) {
+ //
+ // Enumerate all signature data and erasing the target item.
+ //
+ IsItemFound = FALSE;
+ ItemDataSize = (UINT32) DataSize;
+ CertList = (EFI_SIGNATURE_LIST *) OldData;
+ Offset = 0;
+ while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+ FullDeleteOffset = Offset; // If we empty list then delete full record.
+ //
+ // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
+ //
+ CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
+ NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
+ Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+ for (Index = 0; Index < CertCount; Index++) {
+ if (CompareGuid (&Cert->SignatureOwner, SignatureOwner)) {
+ //
+ // Found it so skip it for updated variable.
+ //
+ NewCertList->SignatureListSize -= CertList->SignatureSize;
+ IsItemFound = TRUE;
+ } else {
+ //
+ // This item doesn't match. Copy it to the Data buffer.
+ //
+ CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
+ Offset += CertList->SignatureSize;
+ }
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+ }
+ if (NewCertList->SignatureListSize <= sizeof (EFI_SIGNATURE_LIST)) {
+ Offset = FullDeleteOffset;
+ }
+ ItemDataSize -= CertList->SignatureListSize;
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+ }
+
+ if (!IsItemFound) {
+ //
+ // Doesn't find the signature Item!
+ //
+ Status = EFI_NOT_FOUND;
+ } else {
+
+ //
+ // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
+ //
+ ItemDataSize = Offset;
+ CertList = (EFI_SIGNATURE_LIST *) Data;
+ Offset = 0;
+ ZeroMem (OldData, ItemDataSize);
+ while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+ if (CertCount != 0) {
+ CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
+ Offset += CertList->SignatureListSize;
+ }
+ ItemDataSize -= CertList->SignatureListSize;
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+ }
+
+ DataSize = Offset;
+ if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
+ Status = SetupCreateTimeBasedAuthVarPayload (This, &DataSize, &OldData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SecureBootHelper:DeleteCert:CreateAuthVarPayload Failed %r", Status));
+ DataSize = 0;
+ }
+ }
+ if (DataSize > 0) {
+ Status = gRT->SetVariable(
+ VariableName,
+ VendorGuid,
+ Attr,
+ DataSize,
+ OldData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SecureBootHelper:DeleteCert:SetVariable Failed %r\n", Status));
+ }
+ }
+ }
+ }
+ if (Data != NULL) {
+ FreePool(Data);
+ }
+
+ if (OldData != NULL) {
+ FreePool(OldData);
+ }
+
+ return Status;
+}
+
+/** Append cert to KEK, DB or DBX vars for SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName Variable name of signature database.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] CertType Signature hash type.
+ @param[in] SignatureOwner GUID to identify signature.
+ @param[in] SigDataSize Signature data size.
+ @param[in] SigData Signature data.
+
+ @retval EFI_SUCCESS The variable has been appended successfully.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupAppendCert (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST EFI_GUID *CertType,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL,
+ IN CONST UINTN SigDataSize OPTIONAL,
+ IN CONST UINT8 *SigData OPTIONAL
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+ EFI_SIGNATURE_LIST *SigDBCert;
+ EFI_SIGNATURE_DATA *SigDBCertData;
+ UINT8 *SetData;
+ UINTN SigDBSize;
+ UINT32 Attr;
+ WIN_CERTIFICATE_UEFI_GUID *GuidCertData;
+
+ //
+ // Verify params.
+ //
+ if (This == NULL || CertType == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (SigDataSize > 0 && SigData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SetData = NULL;
+ GuidCertData = NULL;
+
+ //
+ // Create a new SigDB entry.
+ //
+ SigDBSize = sizeof(EFI_SIGNATURE_LIST)
+ + sizeof(EFI_SIGNATURE_DATA) - 1
+ + (UINT32) SigDataSize;
+
+ SetData = (UINT8*) AllocateZeroPool (SigDBSize);
+ if (SetData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Adjust the Certificate Database parameters.
+ //
+ SigDBCert = (EFI_SIGNATURE_LIST*) SetData;
+ SigDBCert->SignatureListSize = (UINT32) SigDBSize;
+ SigDBCert->SignatureHeaderSize = 0;
+ SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) SigDataSize;
+ CopyGuid (&SigDBCert->SignatureType, CertType);
+
+ SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));
+ if (SignatureOwner != NULL) {
+ CopyGuid (&SigDBCertData->SignatureOwner, SignatureOwner);
+ }
+ if (SigDataSize > 0) {
+ CopyMem (SigDBCertData->SignatureData, SigData, SigDataSize);
+ }
+ Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
+ | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+
+ Status = SetupSetTimeBasedAuthVariable (
+ This,
+ VariableName,
+ VendorGuid,
+ Attr,
+ SigDBSize,
+ SetData,
+ TRUE
+ );
+
+ if (SetData != NULL) {
+ FreePool (SetData);
+ }
+ return Status;
+}
+
+/** Check if certificate list matchs filter criteria.
+
+ Filter criteria are :-
+ CertList->SignatureType GUID matches Filter->SignatureType.
+ Payload size of CertList == Filter->SignatureDataPayloadSize.
+ The SignatureOwner GUID of any certificate in list matches Filter->SignatureOwner.
+
+ @param[in] CertList Certificate list to check.
+ @param[in] Filter Filter criteria.
+ @param[out] CallerCertData Pointer to update with address of EFI_SIGNATURE_DATA.
+
+ @return 0 if no match or the number of certificates in CertList if a match found.
+ @return Optionally update CallerCertData with address of EFI_SIGNATURE_DATA.
+
+**/
+UINTN
+EFIAPI
+CertMatch (
+ IN EFI_SIGNATURE_LIST *CertList,
+ IN FIND_CERT_FILTER *Filter OPTIONAL,
+ OUT EFI_SIGNATURE_DATA **CallerCertData OPTIONAL
+ )
+{
+ EFI_SIGNATURE_DATA *Cert;
+ UINTN CertCount;
+ UINTN Index;
+
+ Cert =
+ (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ CertCount =
+ (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+
+ if (Filter) {
+ if (Filter->SignatureType) {
+ if (CompareGuid (&CertList->SignatureType, Filter->SignatureType) == FALSE) {
+ return 0;
+ }
+ }
+ if (Filter->SignatureDataPayloadSize != 0) {
+ if (CertList->SignatureSize != sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) Filter->SignatureDataPayloadSize) {
+ return 0;
+ }
+ }
+
+ if (Filter->SignatureOwner) {
+ for (Index = 0; Index < CertCount; Index++) {
+ if (CompareGuid (&Cert->SignatureOwner, Filter->SignatureOwner) == TRUE) {
+ break;
+ }
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+ }
+ if (Index == CertCount) {
+ return 0;
+ }
+ }
+ }
+ if (CallerCertData) {
+ *CallerCertData = Cert;
+ }
+ return CertCount;
+}
+
+/** Find first cert. list in security database that matches filter criteria.
+
+ If Filter == NULL then return first cert list in database.
+
+ Caller must call Find Cert Close to free resources allocated by this find.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName Security database variable name.
+ @param[in] VendorGuid Security database variable vendor GUID.
+ @param[in] Filter Filter criteria.
+ @param[out] CertList Pointer to update with address of EFI_SIGNATURE_LIST.
+ @param[out] CertData Pointer to update with address of EFI_SIGNATURE_DATA.
+
+ @retval NULL Nothing found in database.
+ @retval other Pointer to this found context to be passed to Find Next Cert
+ and Find Cert Close.
+ @return Updated CertList with address of EFI_SIGNATURE_LIST structure of the
+ found certificate list.
+ @return Optionally update CertData with address of EFI_SIGNATURE_DATA of the
+ found certificate list.
+
+**/
+VOID *
+EFIAPI
+FindFirstCert (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN FIND_CERT_FILTER *Filter OPTIONAL,
+ OUT EFI_SIGNATURE_LIST **CertList,
+ OUT EFI_SIGNATURE_DATA **CertData OPTIONAL,
+ OUT FIND_CERT_STATS *Stats OPTIONAL
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+ UINT8 *FindContext;
+ UINTN DataSize;
+ UINTN AllocSize;
+ EFI_SIGNATURE_LIST *MatchList;
+ UINT32 Attr;
+
+ if (Stats != NULL) {
+ Stats->VariableSize = 0;
+ Stats->VariableAttributes = 0;
+ }
+
+ //
+ // Verify This pointer.
+ //
+ if (This == NULL) {
+ return NULL;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return NULL;
+ }
+
+ MatchList = NULL;
+ DataSize = 0;
+
+ if (CertList == NULL) {
+ return NULL;
+ }
+
+ Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return NULL;
+ }
+ AllocSize = DataSize + sizeof(VOID *);
+ FindContext = (UINT8 *) AllocateZeroPool (AllocSize);
+ if (FindContext == NULL) {
+ return NULL;
+ }
+ *((UINT8 **) FindContext) = FindContext + AllocSize;
+
+ Status = gRT->GetVariable (
+ VariableName,
+ VendorGuid,
+ &Attr,
+ &DataSize,
+ (VOID *) (FindContext + sizeof(UINT8 *))
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (Stats != NULL) {
+ Stats->VariableSize = DataSize;
+ Stats->VariableAttributes = Attr;
+ }
+ MatchList = (EFI_SIGNATURE_LIST *) (FindContext + sizeof(UINT8 *));
+ if (CertMatch (MatchList, Filter, CertData) == 0) {
+ MatchList = FindNextCert (
+ FindContext,
+ Filter,
+ MatchList,
+ CertData);
+ }
+ }
+
+ if (MatchList == NULL) {
+ FreePool (FindContext);
+ return NULL;
+ }
+
+ *CertList = MatchList;
+
+ return (VOID *) FindContext;
+}
+
+/** Find next cert. list in security database that matches filter criteria.
+
+ If Filter == NULL then return next cert list in database.
+
+ @param[in] FindContext Return from previous call to Find First Cert.
+ @param[in] Filter Filter criteria.
+ @param[out] CurrCertList Current position in security database.
+ @param[out] CertData Pointer to update with address of EFI_SIGNATURE_DATA.
+
+ @retval NULL Reached end of database.
+ @retval other Pointer to EFI_SIGNATURE_LIST structure of the
+ next certificate list.
+ @return Optionally update CertData with address of EFI_SIGNATURE_DATA of the
+ next certificate list.
+
+**/
+EFI_SIGNATURE_LIST *
+EFIAPI
+FindNextCert (
+ IN VOID *FindContext,
+ IN FIND_CERT_FILTER *Filter,
+ IN EFI_SIGNATURE_LIST *CurrCertList,
+ OUT EFI_SIGNATURE_DATA **CertData
+ )
+{
+ UINT8 *Limit;
+ EFI_SIGNATURE_LIST *Next;
+
+ if (FindContext == NULL || CurrCertList == NULL) {
+ return NULL;
+ }
+ Limit = *((UINT8 **) FindContext);
+ Next = CurrCertList;
+ do {
+ Next = (EFI_SIGNATURE_LIST *) (((UINT8 *) Next) + Next->SignatureListSize);
+ if (((UINT8 *) Next) >= Limit) {
+ return NULL;
+ }
+ } while (CertMatch (Next, Filter, CertData) == 0);
+ return Next;
+}
+
+/** Free resources allocated by Find First Cert.
+
+ @param[in] FindContext Return from previous call to Find First Cert.
+
+**/
+VOID
+EFIAPI
+FindCertClose (
+ IN VOID *FindContext
+ )
+{
+ if (FindContext) {
+ FreePool (FindContext);
+ }
+}
+
+/** Check if Platform Key is enrolled.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[out] Optional return of size of 'pk' variable.
+ @param[out] Optional return of attributes of 'pk' variable.
+
+ @retval TRUE Platform Key is enrolled.
+ @retval FALSE System has no Platform Key or Error with key var.
+
+**/
+BOOLEAN
+EFIAPI
+IsPkEnrolled (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ OUT UINTN *PkVarSize OPTIONAL,
+ OUT UINT32 *PkVarAttr OPTIONAL
+ )
+{
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+ UINTN VarSize;
+ UINT8 *Data;
+
+ ASSERT (This != NULL);
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ ASSERT (PrivateData->Signature == SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE);
+
+ VarSize = 0;
+
+ Status = gRT->GetVariable (
+ EFI_PLATFORM_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &VarSize,
+ NULL
+ );
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return FALSE;
+ }
+
+ if (PkVarSize) {
+ *PkVarSize = VarSize;
+ }
+
+ if (PkVarAttr) {
+ Data = (UINT8 *) AllocatePool (VarSize);
+ if (Data == NULL) {
+ return 0;
+ }
+
+ Status = gRT->GetVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, PkVarAttr, &VarSize, Data);
+ FreePool (Data);
+ if (EFI_ERROR(Status)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/** Enroll X509 Cert file into PK, KEK, DB or DBX database.
+
+ For use with SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] StoreType PKStore, KEKStore, DBStore or DBXStore.
+ @param[in] FileDevicePath Device Path of X509 certificate file (.der /.cer / .crt)
+ in format using ASN.1 DER encoding.
+ @param[in] SourceBuffer If not NULL, a pointer to the memory location containing a copy
+ of the certificate, overrides FileDevicePath.
+ @param[in] SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL.
+ @param[in] SignatureOwner Identifier for this enrollment.
+
+ @retval EFI_SUCCESS Enroll success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @retval EFI_WRITE_PROTECTED Resource is read-only.
+ @retval EFI_NOT_FOUND File not found.
+ @retval EFI_SECURITY_VIOLATION System in invalid mode for operation.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupEnrollX509 (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *X509Data;
+ UINTN X509Size;
+ UINT32 AStat;
+ BOOLEAN FreeX509Data;
+ UINT32 Attr;
+ UINTN DataSize;
+ EFI_SIGNATURE_LIST *PkCert;
+ EFI_SIGNATURE_DATA *PkCertData;
+
+ if (SourceBuffer != NULL) {
+ X509Data = (UINT8 *) SourceBuffer;
+ X509Size = SourceSize;
+ FreeX509Data = FALSE;
+ } else {
+ X509Data = MyGetFileBufferByFilePath (FileDevicePath, &X509Size, &AStat);
+
+ if (X509Data == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ FreeX509Data = TRUE;
+ }
+
+ if (StoreType == DBStore) {
+ Status = SetupAppendCert (
+ This,
+ EFI_IMAGE_SECURITY_DATABASE,
+ &gEfiImageSecurityDatabaseGuid,
+ &gEfiCertX509Guid,
+ SignatureOwner,
+ X509Size,
+ X509Data
+ );
+ } else if (StoreType == DBXStore) {
+ Status = SetupAppendCert (
+ This,
+ EFI_IMAGE_SECURITY_DATABASE1,
+ &gEfiImageSecurityDatabaseGuid,
+ &gEfiCertX509Guid,
+ SignatureOwner,
+ X509Size,
+ X509Data
+ );
+ } else if (StoreType == KEKStore) {
+ Status = SetupAppendCert (
+ This,
+ EFI_KEY_EXCHANGE_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ &gEfiCertX509Guid,
+ SignatureOwner,
+ X509Size,
+ X509Data
+ );
+ } else if (StoreType == PKStore) {
+ //
+ // Allocate space for PK certificate list and initialize it.
+ // Create PK database entry with SignatureHeaderSize equals 0.
+ //
+ DataSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1
+ + X509Size;
+
+ PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool (DataSize);
+ if (PkCert == NULL) {
+ FreePool (X509Data);
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+
+ //
+ // Enroll pk X509 cert.
+ //
+ PkCert->SignatureListSize = (UINT32) DataSize;
+ PkCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509Size);
+ PkCert->SignatureHeaderSize = 0;
+ CopyGuid (&PkCert->SignatureType, &gEfiCertX509Guid);
+ PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(PkCert)
+ + sizeof(EFI_SIGNATURE_LIST)
+ + PkCert->SignatureHeaderSize);
+ CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);
+ //
+ // Fill the PK database with PKpub data from X509 certificate file.
+ //
+ CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509Size);
+
+ Attr = EFI_VARIABLE_NON_VOLATILE
+ | EFI_VARIABLE_RUNTIME_ACCESS
+ | EFI_VARIABLE_BOOTSERVICE_ACCESS
+ | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+
+ Status = SetupSetTimeBasedAuthVariable (
+ This,
+ EFI_PLATFORM_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ Attr,
+ DataSize,
+ (UINT8 *) PkCert,
+ FALSE
+ );
+
+ FreePool (PkCert);
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ if (FreeX509Data) {
+ FreePool (X509Data);
+ }
+ DEBUG ((EFI_D_INFO, "SecureBootHelper:EnrollX509 %r Store = 0x%02x Owner = %g\n", Status, (UINTN) StoreType, SignatureOwner));
+
+ return Status;
+}
+
+/** Enroll Rsa2048 storing file (*.pbk) into KEK database.
+
+ SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] FileDevicePath Device Path of Rsa2048 storing file (*.pbk).
+ @param[in] SourceBuffer If not NULL, a pointer to the memory location containing a copy
+ of the pbk file, overrides FileDevicePath.
+ @param[in] SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL.
+ @param[in] SignatureOwner Identifier for this enrollment.
+
+ @retval EFI_SUCCESS Enroll success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @retval EFI_WRITE_PROTECTED Resource is read-only.
+ @retval EFI_UNSUPPORTED Unsupported file.
+ @retval EFI_NOT_FOUND File not found.
+ @retval EFI_SECURITY_VIOLATION System in invalid mode for operation.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupEnrollKekRsa2048 (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN KeyBlobSize;
+ UINT8 *KeyBlob;
+ CPL_KEY_INFO *KeyInfo;
+ UINT32 AStat;
+ UINTN KeyLenInBytes;
+ UINT8 *KeyBuffer;
+ BOOLEAN FreeBlob;
+
+ if (SourceBuffer != NULL) {
+ KeyBlob = (UINT8 *) SourceBuffer;
+ KeyBlobSize = SourceSize;
+ FreeBlob = FALSE;
+ } else {
+ KeyBlob = MyGetFileBufferByFilePath (FileDevicePath, &KeyBlobSize, &AStat);
+
+ if (KeyBlob == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ FreeBlob = TRUE;
+ }
+ KeyBuffer = NULL;
+
+ KeyInfo = (CPL_KEY_INFO *) KeyBlob;
+ if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {
+ DEBUG ((EFI_D_ERROR, "SecureBootHelper:EnrollKekRsa2048 Unsupported key length, Only RSA2048 is supported.\n"));
+ Status = EFI_UNSUPPORTED;
+ } else {
+
+ //
+ // Convert the Public key to fix octet string format represented in RSA PKCS#1.
+ //
+ KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;
+ KeyBuffer = AllocateZeroPool (KeyLenInBytes);
+ if (KeyBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ MyInt2OctStr (
+ (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)),
+ KeyLenInBytes / sizeof (UINTN),
+ KeyBuffer,
+ KeyLenInBytes
+ );
+ CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);
+
+ Status = SetupAppendCert (
+ This,
+ EFI_KEY_EXCHANGE_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ &gEfiCertRsa2048Guid,
+ SignatureOwner,
+ WIN_CERT_UEFI_RSA2048_SIZE,
+ KeyBlob + sizeof(CPL_KEY_INFO)
+ );
+ }
+ }
+
+ if (KeyBuffer) {
+ FreePool (KeyBuffer);
+ }
+
+ if (FreeBlob) {
+ FreePool (KeyBlob);
+ }
+ DEBUG ((EFI_D_INFO, "SecureBootHelper:EnrollKekRsa2048 %r Owner = %g\n", Status, SignatureOwner));
+ return Status;
+}
+
+/** Enroll Image Signature into secure boot database.
+
+ SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] StoreType PKStore, KEKStore, DBStore or DBXStore.
+ @param[in] FileDevicePath Device Path of image to enroll.
+ @param[in] SourceBuffer If not NULL, a pointer to the memory location containing SHA256
+ 32 byte image digest. Assumed to match &gEfiCertSha256Guid.
+ @param[in] SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL.
+ @param[in] SignatureOwner Identifier for this enrollment.
+
+ @retval EFI_SUCCESS Enroll success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @retval EFI_WRITE_PROTECTED Resource is read-only.
+ @retval EFI_UNSUPPORTED Unsupported image type.
+ @retval EFI_NOT_FOUND File not found.
+ @retval EFI_SECURITY_VIOLATION System in invalid mode for operation.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupEnrollImageSignature (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ SECUREBOOT_PEIMAGE_LOAD_INFO *LoadInfo;
+ CHAR16 *VariableName;
+ EFI_GUID *VendorGuid;
+
+ if (StoreType == DBStore) {
+ VariableName = EFI_IMAGE_SECURITY_DATABASE;
+ } else if (StoreType == DBXStore) {
+ VariableName = EFI_IMAGE_SECURITY_DATABASE1;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ VendorGuid = &gEfiImageSecurityDatabaseGuid;
+
+ if (SourceBuffer != NULL) {
+ Status = SetupAppendCert (
+ This,
+ VariableName,
+ VendorGuid,
+ &gEfiCertSha256Guid,
+ SignatureOwner,
+ SourceSize,
+ (UINT8 *) SourceBuffer
+ );
+ } else {
+ LoadInfo = LoadPeImageWork (FileDevicePath, TRUE);
+ if (LoadInfo == NULL) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ if (LoadInfo->ImageDigestSize == 0) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ Status =SetupAppendCert (
+ This,
+ VariableName,
+ VendorGuid,
+ &LoadInfo->ImageCertType,
+ SignatureOwner,
+ LoadInfo->ImageDigestSize,
+ LoadInfo->ImageDigest
+ );
+ }
+ FreePool (LoadInfo);
+ }
+ }
+ DEBUG ((EFI_D_INFO, "SecureBootHelper:EnrollImageSignature %r Store = 0x%02x Owner = %g\n", Status, (UINTN) StoreType, SignatureOwner));
+ return Status;
+}
+
+/** Delete record in SecureBoot PK, KEK, DB or DBX or delete a complete store.
+
+ SecureBoot in Setup/Custom mode.
+
+ if CompleteStore then reset StoreType with all certs deleted.
+ CompleteStore param ignored if StoreType == PKStore ie complete PK always reset.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] StoreType PKStore, KEKStore, DBStore or DBXStore.
+ @param[in] CompleteStore If true reset complete secure boot store (StoreType).
+ @param[in] SignatureOwner Specific record in store to delete.
+
+ @retval EFI_SUCCESS Delete success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Resource not enough to do operation.
+ @retval EFI_WRITE_PROTECTED Resource is read-only.
+ @retval EFI_SECURITY_VIOLATION System in invalid mode for operation.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupDeleteStoreRecord (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST BOOLEAN CompleteStore,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ )
+{
+ CHAR16 *VariableName;
+ EFI_GUID *VendorGuid;
+
+ if (StoreType == DBStore) {
+ VariableName = EFI_IMAGE_SECURITY_DATABASE;
+ VendorGuid = &gEfiImageSecurityDatabaseGuid;
+ } else if (StoreType == DBXStore) {
+ VariableName = EFI_IMAGE_SECURITY_DATABASE1;
+ VendorGuid = &gEfiImageSecurityDatabaseGuid;
+ } else if (StoreType == KEKStore) {
+ VariableName = EFI_KEY_EXCHANGE_KEY_NAME;
+ VendorGuid = &gEfiGlobalVariableGuid;
+ } else if (StoreType == PKStore) {
+ return SetupCreateTimeBasedAuthVar (
+ This,
+ EFI_PLATFORM_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ FALSE
+ );
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (CompleteStore) {
+ return SetupCreateTimeBasedAuthVar (
+ This,
+ VariableName,
+ VendorGuid,
+ FALSE
+ );
+ }
+ return SetupDeleteCert (
+ This,
+ VariableName,
+ VendorGuid,
+ SignatureOwner
+ );
+}
+
+/** Get statistics for SecureBoot PK, KEK, DB and DBX variables.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[out] Stats Caller allocated SECUREBOOT_VARIABLE_STATS
+ struct filled out by this routine.
+
+ @retval EFI_SUCCESS Operation success with Stats filled out.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+GetSecureBootVarStats (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ OUT SECUREBOOT_VARIABLE_STATS *Stats
+ )
+{
+ UINTN LastSize;
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+
+ //
+ // Verify This & Stats pointers.
+ //
+ if (This == NULL || Stats == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ZeroMem (Stats, sizeof (SECUREBOOT_VARIABLE_STATS));
+ Stats->PkEnrolled = IsPkEnrolled (
+ This,
+ &Stats->MaxVarSize,
+ &Stats->PkAttributes
+ );
+
+ LastSize = GetSecureBootCertVarStats (
+ This,
+ EFI_KEY_EXCHANGE_KEY_NAME,
+ &gEfiGlobalVariableGuid,
+ &Stats->KekAttributes,
+ &Stats->KekTotalCertCount,
+ &Stats->KekX509CertCount,
+ &Stats->KekRsa2048CertCount,
+ &Stats->KekOtherCertCount,
+ NULL,
+ NULL
+ );
+ Stats->KekEnrolled = (LastSize > 0);
+ Stats->MaxVarSize = MAX(Stats->MaxVarSize, LastSize);
+
+ LastSize = GetSecureBootCertVarStats (
+ This,
+ EFI_IMAGE_SECURITY_DATABASE,
+ &gEfiImageSecurityDatabaseGuid,
+ &Stats->DbAttributes,
+ &Stats->DbTotalCertCount,
+ &Stats->DbX509CertCount,
+ NULL,
+ &Stats->DbOtherCertCount,
+ &Stats->DbSha256Count,
+ &Stats->DbSha1Count
+ );
+ Stats->DbEnrolled = (LastSize > 0);
+ Stats->MaxVarSize = MAX(Stats->MaxVarSize, LastSize);
+
+ LastSize = GetSecureBootCertVarStats (
+ This,
+ EFI_IMAGE_SECURITY_DATABASE1,
+ &gEfiImageSecurityDatabaseGuid,
+ &Stats->DbxAttributes,
+ &Stats->DbxTotalCertCount,
+ &Stats->DbxX509CertCount,
+ NULL,
+ &Stats->DbxOtherCertCount,
+ &Stats->DbxSha256Count,
+ &Stats->DbxSha1Count
+ );
+ Stats->DbxEnrolled = (LastSize > 0);
+ Stats->MaxVarSize = MAX(Stats->MaxVarSize, LastSize);
+
+ return EFI_SUCCESS;
+}
+
+/** Create Time based authenticated variable for SecureBoot Setup/Custom Mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+ @param[in] VariableName Name of Variable to set.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] LeaveIfExists If variable already exists do nothing.
+
+ @retval EFI_SUCCESS The variable has been appended successfully.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @retval EFI_WRITE_PROTECTED Variable is read-only.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupCreateTimeBasedAuthVar (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST BOOLEAN LeaveIfExists
+ )
+{
+ EFI_STATUS Status;
+ VOID* Variable;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINT32 Attr;
+
+ GetVariable2 (VariableName, VendorGuid, &Variable, NULL);
+ if (Variable != NULL) {
+ FreePool (Variable);
+ if (LeaveIfExists) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ Data = NULL;
+ DataSize = 0;
+ Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
+ | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE;
+
+ Status = SetupCreateTimeBasedAuthVarPayload (This, &DataSize, &Data);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SecureBootHelper:CreateAuthVariable:CreateAuthVarPayload failed %r", Status));
+ return Status;
+ }
+
+ Status = gRT->SetVariable (
+ VariableName,
+ VendorGuid,
+ Attr,
+ DataSize,
+ Data
+ );
+ if (Data != NULL) {
+ FreePool (Data);
+ }
+ return Status;
+}
+
+/** Create Empty DB & DBX if they do not exist.
+
+ SecureBoot in Setup/Custom mode.
+
+ @param[in] This Pointer to SECUREBOOT_HELPER_PROTOCOL located by caller.
+
+ @retval EFI_SUCCESS The variable has been appended successfully.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupCreateEmptyDbDbxIfNotExist (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *VariableNames[2];
+ EFI_GUID ZeroGuid;
+ UINTN Index;
+ UINTN VarSize;
+ SECUREBOOT_HELPER_PRIVATE_DATA *PrivateData;
+
+ //
+ // Verify This pointer.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = SECUREBOOT_HELPER_PRIVATE_FROM_SBHP (This);
+ if (PrivateData->Signature != SECUREBOOT_HELPER_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
+
+ VariableNames[0] = EFI_IMAGE_SECURITY_DATABASE;
+ VariableNames[1] = EFI_IMAGE_SECURITY_DATABASE1;
+ Status = EFI_SUCCESS;
+
+ for (Index=0;Index < sizeof(VariableNames) / sizeof(VariableNames[0]);Index++) {
+ VarSize = 0;
+
+ Status = gRT->GetVariable(
+ VariableNames[Index],
+ &gEfiImageSecurityDatabaseGuid,
+ NULL,
+ &VarSize,
+ NULL
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Status = EFI_SUCCESS;
+ continue; // Already setup do nothing.
+ } else if (Status == EFI_NOT_FOUND) {
+
+ //
+ // Create an empty version with a dummy Signature if required.
+ // Use null guid for SignatureType in dummy signature so it is ignored
+ // by image verifier.
+ //
+ Status = SetupAppendCert (
+ This,
+ VariableNames[Index],
+ &gEfiImageSecurityDatabaseGuid,
+ &ZeroGuid,
+ NULL,
+ 0,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ //
+ // Always expect error Status if Status != EFI_BUFFER_TOO_SMALL
+ // and Status != EFI_NOT_FOUND.
+ //
+ ASSERT (EFI_ERROR (Status));
+ ASSERT (FALSE);
+ }
+ }
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootVariable.h b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootVariable.h
new file mode 100644
index 0000000..350cf22
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootVariable.h
@@ -0,0 +1,233 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SecureBootVariable.h
+
+Abstract:
+
+ Header file for SecureBootVariable.c.
+
+--*/
+
+#ifndef __SECUREBOOT_HELPER_VARIABLE_HEADER_H_
+#define __SECUREBOOT_HELPER_VARIABLE_HEADER_H_
+
+//
+// Cryptograhpic Key Information
+//
+#pragma pack(1)
+typedef struct _CPL_KEY_INFO {
+ UINT32 KeyLengthInBits; // Key Length In Bits
+ UINT32 BlockSize; // Operation Block Size in Bytes
+ UINT32 CipherBlockSize; // Output Cipher Block Size in Bytes
+ UINT32 KeyType; // Key Type
+ UINT32 CipherMode; // Cipher Mode for Symmetric Algorithm
+ UINT32 Flags; // Additional Key Property Flags
+} CPL_KEY_INFO;
+#pragma pack()
+
+BOOLEAN
+EFIAPI
+IsSecureBootEnabledWork (
+ VOID
+ );
+
+BOOLEAN
+EFIAPI
+IsSecureBootEnabled (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+BOOLEAN
+EFIAPI
+IsSecureBootInCustomModeWork (
+ VOID
+ );
+
+BOOLEAN
+EFIAPI
+IsSecureBootInCustomMode (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+SetupSetSecureBootCustomMode (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+SetupSetSecureBootDefaultMode (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+SetupCreateTimeBasedAuthVarPayload (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT8 **Data
+ );
+
+EFI_STATUS
+EFIAPI
+SetupSetTimeBasedAuthVariable (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attr,
+ IN UINTN DataSize,
+ IN UINT8 *Data,
+ IN BOOLEAN AppendIfExists
+ );
+
+EFI_STATUS
+EFIAPI
+SetupDeleteCert (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST EFI_GUID *SignatureOwner
+ );
+
+EFI_STATUS
+EFIAPI
+SetupAppendCert (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST EFI_GUID *CertType,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL,
+ IN CONST UINTN SigDataSize,
+ IN CONST UINT8 *SigData
+ );
+
+VOID *
+EFIAPI
+FindFirstCert (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN FIND_CERT_FILTER *Filter OPTIONAL,
+ OUT EFI_SIGNATURE_LIST **CertList,
+ OUT EFI_SIGNATURE_DATA **CertData OPTIONAL,
+ OUT FIND_CERT_STATS *Stats OPTIONAL
+ );
+
+EFI_SIGNATURE_LIST *
+EFIAPI
+FindNextCert (
+ IN VOID *FindContext,
+ IN FIND_CERT_FILTER *Filter,
+ IN EFI_SIGNATURE_LIST *CurrCertList,
+ OUT EFI_SIGNATURE_DATA **CertData
+ );
+
+VOID
+EFIAPI
+FindCertClose (
+ IN VOID *FindContext
+ );
+
+BOOLEAN
+EFIAPI
+IsPkEnrolled (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ OUT UINTN *PkVarSize OPTIONAL,
+ OUT UINT32 *PkVarAttr OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+SetupEnrollX509 (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+SetupEnrollKekRsa2048 (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+SetupEnrollImageSignature (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FileDevicePath,
+ IN CONST VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+SetupDeleteStoreRecord (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CONST SECUREBOOT_STORE_TYPE StoreType,
+ IN CONST BOOLEAN CompleteStore,
+ IN CONST EFI_GUID *SignatureOwner OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+GetSecureBootVarStats (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ OUT SECUREBOOT_VARIABLE_STATS *Stats
+ );
+
+EFI_STATUS
+EFIAPI
+SetupCreateTimeBasedAuthVar (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN CONST BOOLEAN LeaveIfExists
+ );
+
+EFI_STATUS
+EFIAPI
+SetupCreateEmptyDbDbxIfNotExist (
+ IN CONST SECUREBOOT_HELPER_PROTOCOL *This
+ );
+
+#endif // __SECUREBOOT_HELPER_VARIABLE_HEADER_H_
diff --git a/QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.c b/QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.c
new file mode 100644
index 0000000..bb3da07
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.c
@@ -0,0 +1,149 @@
+/** @file
+
+ CPU Configuration Library.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include <Uefi.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/SmmCpuPlatformHookLib.h>
+
+/**
+ Checks if platform produces a valid SMI.
+
+ This function checks if platform produces a valid SMI. This function is
+ called at SMM entry to detect if this is a spurious SMI. This function
+ must be implemented in an MP safe way because it is called by multiple CPU
+ threads.
+
+ @retval TRUE There is a valid SMI
+ @retval FALSE There is no valid SMI
+
+**/
+BOOLEAN
+EFIAPI
+PlatformValidSmi (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Clears platform top level SMI status bit.
+
+ This function clears platform top level SMI status bit.
+
+ @retval TRUE The platform top level SMI status is cleared.
+ @retval FALSE The paltform top level SMI status cannot be cleared.
+
+**/
+BOOLEAN
+EFIAPI
+ClearTopLevelSmiStatus (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Performs platform specific way of SMM BSP election.
+
+ This function performs platform specific way of SMM BSP election.
+
+ @param IsBsp Output parameter. TRUE: the CPU this function executes
+ on is elected to be the SMM BSP. FALSE: the CPU this
+ function executes on is to be SMM AP.
+
+ @retval EFI_SUCCESS The function executes successfully.
+ @retval EFI_NOT_READY The function does not determine whether this CPU should be
+ BSP or AP. This may occur if hardware init sequence to
+ enable the determination is yet to be done, or the function
+ chooses not to do BSP election and will let SMM CPU driver to
+ use its default BSP election process.
+ @retval EFI_DEVICE_ERROR The function cannot determine whether this CPU should be
+ BSP or AP due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSmmBspElection (
+ OUT BOOLEAN *IsBsp
+ )
+{
+ return EFI_NOT_READY;
+}
+
+/**
+ Get platform page table attribute.
+
+ This function gets page table attribute of platform.
+
+ @param Address Input parameter. Obtain the page table entries attribute on this address.
+ @param PageSize Output parameter. The size of the page.
+ @param NumOfPages Output parameter. Number of page.
+ @param PageAttribute Output parameter. Paging Attributes (WB, UC, etc).
+
+ @retval EFI_SUCCESS The platform page table attribute from the address is determined.
+ @retval EFI_UNSUPPORTED The paltform not supoort to get page table attribute from the address.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformPageTableAttribute (
+ IN UINT64 Address,
+ IN OUT SMM_PAGE_SIZE_TYPE *PageSize,
+ IN OUT UINTN *NumOfPages,
+ IN OUT UINTN *PageAttribute
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Platform hook called when exiting SMM.
+
+**/
+VOID
+EFIAPI
+PlatformSmmExitProcessing (
+ VOID
+ )
+{
+ UINT32 NewValue;
+
+ //
+ // Ensure that SMI signal pin indicator is clear at the end of SMM handling.
+ //
+ NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HLEGACY_REG);
+ NewValue &= ~(HLEGACY_SMI_PIN_VALUE);
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HLEGACY_REG, NewValue);
+}
diff --git a/QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.inf b/QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.inf
new file mode 100644
index 0000000..871ffce
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.inf
@@ -0,0 +1,66 @@
+## @file
+# Component description file for CPU Configuration Library.
+#
+# CPU Configuration Library implementation that retrieves data in Processor
+# Configuration Context Buffer.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmCpuPlatformHookLibNull
+ FILE_GUID = 0A1458CA-9619-4368-960C-6BF764F8EB1D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SmmCpuPlatformHookLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SmmCpuPlatformHookLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ QNCAccessLib
diff --git a/QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.c b/QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.c
new file mode 100644
index 0000000..fc27eb8
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.c
@@ -0,0 +1,446 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmmScriptLib.c
+
+Abstract:
+
+ ScriptTableSave module at run time
+
+--*/
+
+#include <Uefi.h>
+#include <Guid/AcpiVariableCompatibility.h>
+#include "Library/SmmScriptLib.h"
+
+//
+// internal functions
+//
+EFI_STATUS
+BootScriptIoWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ );
+
+EFI_STATUS
+BootScriptPciCfgWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ );
+
+EFI_STATUS
+BootScriptMemWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ );
+
+VOID
+SmmCopyMem (
+ IN UINT8 *Destination,
+ IN UINT8 *Source,
+ IN UINTN ByteCount
+ );
+
+//
+// Function implementations
+//
+EFI_STATUS
+EFIAPI
+SmmBootScriptWrite (
+ IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN UINTN Type,
+ IN UINT16 OpCode,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Write to boot script table. Format is defined in AcpiScritSave Protocol.
+ Currently it supports MemWrite, IoWrite, PciCfgWrite.
+
+Arguments:
+
+ ScriptTable - Pointer to the script table to write to.
+ Type - Not used.
+ OpCode - Table write's Opcode.
+ ... - Parameter of the OpCode.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter passed in detected.
+ EFI_SUCCESS - Function completed successfully.
+ Other - Error occurred during execution.
+
+--*/
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+
+ if (ScriptTable == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Build script according to opcode
+ //
+ switch (OpCode) {
+
+ case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptIoWrite (ScriptTable, Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptPciCfgWrite (ScriptTable, Marker);
+ VA_END (Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
+ VA_START (Marker, OpCode);
+ Status = BootScriptMemWrite (ScriptTable, Marker);
+ VA_END (Marker);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ };
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+InitializeSmmScriptLib (
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINTN SmmScriptTablePages,
+ OUT EFI_PHYSICAL_ADDRESS *SmmScriptTableBase
+ )
+/*++
+
+Routine Description:
+
+ Intialize Boot Script table.
+
+Arguments:
+
+ SystemTable - Pointer to the EFI sytem table
+ SmmScriptTablePages - The expected ScriptTable page number
+ SmmScriptTableBase - The returned ScriptTable base address
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No resource to do the initialization.
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ ACPI_VARIABLE_SET_COMPATIBILITY *AcpiVariableBase;
+ UINTN VarSize;
+ UINT32 VarAttrib;
+
+ //
+ // Allocate runtime ACPI script table space. We need it to save some
+ // settings done by CSM, which runs after normal script table closed
+ //
+ *SmmScriptTableBase = 0xFFFFFFFF;
+ Status = SystemTable->BootServices->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ SmmScriptTablePages,
+ SmmScriptTableBase
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Save runtime script table base into global ACPI variable
+ //
+ VarAttrib = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
+ VarSize = sizeof (UINTN);
+ Status = SystemTable->RuntimeServices->GetVariable (
+ ACPI_GLOBAL_VARIABLE,
+ &gEfiAcpiVariableCompatiblityGuid,
+ &VarAttrib,
+ &VarSize,
+ &AcpiVariableBase
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ AcpiVariableBase->RuntimeScriptTableBase = *SmmScriptTableBase;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SmmBootScriptCreateTable (
+ IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN UINTN Type
+ )
+/*++
+
+Routine Description:
+
+ Create Boot Script table.
+
+Arguments:
+
+ ScriptTable - Pointer to the boot script table to create.
+ Type - The type of table to creat.
+
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter detected.
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+{
+ BOOT_SCRIPT_POINTERS Script;
+ UINT8 *Buffer;
+
+ if (ScriptTable == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = (UINT8 *) ((UINTN) (*ScriptTable));
+
+ //
+ // Fill Table Header
+ //
+ Script.Raw = Buffer;
+ Script.TableInfo->OpCode = EFI_BOOT_SCRIPT_TABLE_OPCODE;
+ Script.TableInfo->Length = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
+ Script.TableInfo->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
+
+ //
+ // Update current table pointer
+ //
+ *ScriptTable = *ScriptTable + sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SmmBootScriptCloseTable (
+ IN EFI_SMM_SCRIPT_TABLE ScriptTableBase,
+ IN EFI_SMM_SCRIPT_TABLE ScriptTablePtr,
+ IN UINTN Type
+ )
+/*++
+
+Routine Description:
+
+ Close Boot Script table.
+
+Arguments:
+
+ ScriptTableBase - Pointer to the boot script table to create.
+ ScriptTablePtr - Pointer to the script table to write to.
+ Type - The type of table to creat.
+
+
+Returns:
+
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+{
+ BOOT_SCRIPT_POINTERS Script;
+
+ //
+ // Add final "termination" node to script table
+ //
+ Script.Raw = (UINT8 *) ((UINTN) ScriptTablePtr);
+ Script.Terminate->OpCode = EFI_BOOT_SCRIPT_TERMINATE_OPCODE;
+ Script.Terminate->Length = sizeof (EFI_BOOT_SCRIPT_TERMINATE);
+ ScriptTablePtr += sizeof (EFI_BOOT_SCRIPT_TERMINATE);
+
+ //
+ // Update Table Header
+ //
+ Script.Raw = (UINT8 *) ((UINTN) ScriptTableBase);
+ Script.TableInfo->OpCode = EFI_BOOT_SCRIPT_TABLE_OPCODE;
+ Script.TableInfo->Length = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
+ Script.TableInfo->TableLength = (UINT32) (ScriptTablePtr - ScriptTableBase);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+BootScriptIoWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ )
+{
+ BOOT_SCRIPT_POINTERS Script;
+ EFI_BOOT_SCRIPT_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+ UINTN NodeLength;
+ UINT8 WidthInByte;
+
+ Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ WidthInByte = (UINT8) (0x01 << (Width & 0x03));
+ Script.Raw = (UINT8 *) ((UINTN) (*ScriptTable));
+ NodeLength = sizeof (EFI_BOOT_SCRIPT_IO_WRITE) + (WidthInByte * Count);
+
+ //
+ // Build script data
+ //
+ Script.IoWrite->OpCode = EFI_BOOT_SCRIPT_IO_WRITE_OPCODE;
+ Script.IoWrite->Length = (UINT8) (NodeLength);
+ Script.IoWrite->Width = Width;
+ Script.IoWrite->Address = Address;
+ Script.IoWrite->Count = (UINT32)Count;
+ SmmCopyMem (
+ (UINT8 *) (Script.Raw + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)),
+ Buffer,
+ WidthInByte * Count
+ );
+
+ //
+ // Update Script table pointer
+ //
+ *ScriptTable = *ScriptTable + NodeLength;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+BootScriptPciCfgWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ )
+{
+ BOOT_SCRIPT_POINTERS Script;
+ EFI_BOOT_SCRIPT_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+ UINTN NodeLength;
+ UINT8 WidthInByte;
+
+ Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ WidthInByte = (UINT8) (0x01 << (Width & 0x03));
+ Script.Raw = (UINT8 *) ((UINTN) (*ScriptTable));
+ NodeLength = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count);
+
+ //
+ // Build script data
+ //
+ Script.PciWrite->OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE;
+ Script.PciWrite->Length = (UINT8) (NodeLength);
+ Script.PciWrite->Width = Width;
+ Script.PciWrite->Address = Address;
+ Script.PciWrite->Count = (UINT32)Count;
+ SmmCopyMem (
+ (UINT8 *) (Script.Raw + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)),
+ Buffer,
+ WidthInByte * Count
+ );
+
+ //
+ // Update Script table pointer
+ //
+ *ScriptTable = *ScriptTable + NodeLength;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+BootScriptMemWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ )
+{
+ BOOT_SCRIPT_POINTERS Script;
+ EFI_BOOT_SCRIPT_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+ UINTN NodeLength;
+ UINT8 WidthInByte;
+
+ Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
+ Address = VA_ARG (Marker, UINT64);
+ Count = VA_ARG (Marker, UINTN);
+ Buffer = VA_ARG (Marker, UINT8 *);
+
+ WidthInByte = (UINT8) (0x01 << (Width & 0x03));
+ Script.Raw = (UINT8 *) ((UINTN) (*ScriptTable));
+ NodeLength = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count);
+
+ //
+ // Build script data
+ //
+ Script.MemWrite->OpCode = EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE;
+ Script.MemWrite->Length = (UINT8) (sizeof (EFI_BOOT_SCRIPT_MEM_WRITE) + (WidthInByte * Count));
+ Script.MemWrite->Width = Width;
+ Script.MemWrite->Address = Address;
+ Script.MemWrite->Count = (UINT32)Count;
+ SmmCopyMem ((UINT8 *) (Script.Raw + sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)), Buffer, WidthInByte * Count);
+
+ *ScriptTable = *ScriptTable + NodeLength;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+SmmCopyMem (
+ IN UINT8 *Destination,
+ IN UINT8 *Source,
+ IN UINTN ByteCount
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < ByteCount; Index++, Destination++, Source++) {
+ *Destination = *Source;
+ }
+}
diff --git a/QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.inf b/QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.inf
new file mode 100644
index 0000000..6d1f716
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.inf
@@ -0,0 +1,51 @@
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmScriptLib
+ FILE_GUID = F5AC7057-5650-466e-B692-76A47223EFB0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ LIBRARY_CLASS = InitializeSmmScriptLib
+
+[Sources]
+ SmmScriptLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[Guids]
+ gEfiAcpiVariableGuid
+
+
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/CommonHeader.h b/QuarkPlatformPkg/Library/SwBpeLib/CommonHeader.h
new file mode 100644
index 0000000..b65d168
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/CommonHeader.h
@@ -0,0 +1,52 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ CommonHeader.h
+
+Abstract:
+
+ This file provides required header files to build the Software
+ Breakpoint Event library.
+
+--*/
+
+#ifndef _COMMON_HEADER_H_
+#define _COMMON_HEADER_H_
+
+#include <FrameworkPei.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Ppi/MemoryDiscovered.h>
+#include "SwBpe.h"
+#include "DsConfig.h"
+
+#endif \ No newline at end of file
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/DsConfig.c b/QuarkPlatformPkg/Library/SwBpeLib/DsConfig.c
new file mode 100644
index 0000000..75d7105
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/DsConfig.c
@@ -0,0 +1,101 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ DsConfig.c
+
+Abstract:
+
+ This file implements DS debug feature configuration functionality as defined by
+ the "Enabling DS for External Debugger" feature documentation.
+
+--*/
+
+#include "CommonHeader.h"
+
+VOID
+DsBreakpointEvent (
+ DS_CONFIG_SWBPE_ID Id,
+ EFI_PHYSICAL_ADDRESS BaseAddress,
+ UINTN Size,
+ EFI_STATUS *Status
+ )
+/*++
+
+Routine Description:
+
+ This function generates a SWBPE event. It will create a DS_CONFIG_SWBPE_MAILBOX structure
+ with the DS_CONFIG_SWBPE_GUID and the input arguments and trigger an implementation specific
+ SWBPE.
+
+Arguments:
+
+ Id -
+ BaseAddress -
+ Size -
+
+Returns:
+
+ EFI_SUCCESS - The function event was intercepted by the debugger and handled successfully
+ EFI_UNSUPPORTED - The function event was not intercepted by the debugger and no
+
+--*/
+{
+ SWBPE_MAILBOX Mailbox = {0, 0, 0, 0, 0, 0};
+ DS_CONFIG_SWBPE_MAILBOX DsMailbox = {DS_CONFIG_SWBPE_GUID, 0, 0, 0, 0};
+
+ //
+ // Setup DS-specific data for the debugger
+ //
+ DsMailbox.Id = Id;
+ DsMailbox.BaseAddress = BaseAddress;
+ DsMailbox.Size = Size;
+
+ //
+ // Setup generic SWBPE data for a DS event
+ //
+ Mailbox.EventType = DS_CONFIG_SWBPE_TYPE;
+ Mailbox.EventAddress = DS_CONFIG_SWBPE_ADDRESS;
+ Mailbox.EventData = DS_CONFIG_SWBPE_DATA;
+ Mailbox.EventDataWidth = DS_CONFIG_SWBPE_DATA_WIDTH ;
+ Mailbox.DebuggerArgs = (EFI_PHYSICAL_ADDRESS) (UINTN) (&DsMailbox);
+
+ //
+ // Invoke a DS SWBPE
+ //
+ SoftwareBreakpointEvent (&Mailbox);
+
+ //
+ // Return the debuggers status to the caller
+ //
+ *Status = Mailbox.DebuggerStatus;
+}
+
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/DsConfig.h b/QuarkPlatformPkg/Library/SwBpeLib/DsConfig.h
new file mode 100644
index 0000000..0e8a41e
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/DsConfig.h
@@ -0,0 +1,112 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ DsConfig.h
+
+Abstract:
+
+ This header provides Debug Store configuration using Software Breakpoint Events.
+
+--*/
+
+
+#ifndef _DS_CONFIG_H_
+#define _DS_CONFIG_H_
+
+//
+// This is the GUID that is used to uniquely identify DS Config SWBPEs
+// to the debugger
+//
+#define DS_CONFIG_SWBPE_GUID \
+ { 0x1a237f6e, 0xfa50, 0x4338, 0xae, 0x36, 0x6c, 0x89, 0x38, 0xa7, 0xf2, 0xc2 }
+
+//
+// These are the ID values for DS SWBPEs
+//
+typedef enum {
+ DsConfigSwbpeIdUndefined = 0,
+ DsConfigSwBpeIdCheck = 1,
+ DsConfigSwBpeIdNemStart = 2,
+ DsConfigSwBpeIdNemStop = 3,
+ DsConfigSwBpeIdDramStart = 4,
+ DsConfigSwBpeIdDramStop = 5,
+ DsConfigSwBpeIdMax = 6
+} DS_CONFIG_SWBPE_ID;
+
+
+//
+// This is the DS-specific data that firmware will
+// pass to the debugger via the DebuggerArgs field of
+// SWBPE_MAILBOX.
+//
+#pragma pack (push, 1)
+typedef struct {
+ EFI_GUID Guid;
+ UINT64 Id;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Size;
+ EFI_STATUS *Status;
+} DS_CONFIG_SWBPE_MAILBOX;
+#pragma pack (pop)
+
+
+VOID
+DsBreakpointEvent (
+ IN DS_CONFIG_SWBPE_ID Id,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress, OPTIONAL
+ IN UINTN Size, OPTIONAL
+ OUT EFI_STATUS *Status
+ )
+/*++
+
+Routine Description:
+
+ This function generates a SWBPE event. It will create a DS_CONFIG_SWBPE_MAILBOX structure
+ with the DS_CONFIG_SWBPE_GUID and the input arguments and trigger an implementation specific
+ SWBPE.
+
+Arguments:
+
+ Id - The event being signalled to the debugger
+ BaseAddress - The address of the buffer. This is not used for some ID.
+ Size - The size of the buffer. This is not used for some ID.
+ Status - The status returned by the debugger.
+
+Returns:
+
+ EFI_SUCCESS - The function event was intercepted by the debugger and handled successfully
+ EFI_UNSUPPORTED - The function event was not intercepted by the debugger and not handled
+
+--*/
+;
+
+#endif // _DS_CONFIG_H_
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/Ia32/SwBpeAccess.S b/QuarkPlatformPkg/Library/SwBpeLib/Ia32/SwBpeAccess.S
new file mode 100644
index 0000000..94e4e59
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/Ia32/SwBpeAccess.S
@@ -0,0 +1,234 @@
+#++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+# Module Name:
+#
+# SwbpeLibAccess.S
+#
+# Abstract:
+#
+# This file provides low level I/O access functions to trigger
+# breakpoint events.
+#
+#--
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Procedure: DoSwbpeTypeIoOut
+#
+# Input: PortAddress - Port Address for doing IO Write
+# PortData - Data value for doing IO Write
+# PortDataWidth - Data Width (Byte=1/Word=2/Dword=4) for doing IO Write
+# Mailbox - Data structure contains Data Store informations
+#
+# Output: Debuggers can update structure pointed by %edi via this IO Write Break.
+#
+# Registers: All are preserved
+#
+# Description: Function to do an IO Write and set %edi %edi pointer to Mailbox structure,
+# so Debuggers can recognize the GUID and update status in the structure.
+#
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(DoSwbpeTypeIoOut)
+ASM_PFX(DoSwbpeTypeIoOut):
+ pushl %edi
+ movl 8(%esp), %edx # PortAddress
+ movl 12(%esp), %eax # PortData
+ movl 16(%esp), %ecx # PortDataWidth
+ movl 20(%esp), %edi # Mailbox
+ cmpl $1, %ecx
+ jne TryIoOutWord
+ outb %al, %dx
+ jmp IoOutReturn
+TryIoOutWord:
+ cmpl $2, %ecx
+ jne TryIoOutDword
+ outw %ax, %dx
+ jmp IoOutReturn
+TryIoOutDword:
+ cmpl $4, %ecx
+ jne IoOutReturn
+ outl %eax, %dx
+IoOutReturn:
+ popl %edi
+ ret
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Procedure: DoSwbpeTypeIoIn
+#
+# Input: PortAddress - Port Address for doing IO Read
+# PortDataWidth - Port data width for doing IO Read
+# Mailbox - Data structure contains Data Store informations
+#
+# Output: Debuggers can update structure pointed by %edi via this IO Read Break,
+# %eax contains IO Read byte/word/dword value depends on PortDataWidth.
+#
+# Registers: All are preserved
+#
+# Description: Function to do an IO Read and set %edi pointer to Mailbox structure,
+# so Debuggers can recognize the GUID and update status in the structure.
+#
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(DoSwbpeTypeIoIn)
+ASM_PFX(DoSwbpeTypeIoIn):
+ pushl %edi
+ xor %eax, %eax
+ movl 8(%esp), %edx # PortAddress
+ movl 12(%esp), %ecx # PortDataWidth
+ movl 16(%esp), %edi # Mailbox
+ cmp $1, %ecx
+ jne TryIoInWord
+ inb %dx, %al
+ jmp IoInReturn
+TryIoInWord:
+ cmpl $2, %ecx
+ jne TryIoInDword
+ inw %dx, %ax
+ jmp IoInReturn
+TryIoInDword:
+ cmpl $4, %ecx
+ jne IoInReturn
+ inl %dx, %eax
+IoInReturn:
+ popl %edi
+ ret
+
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Procedure: DoSwbpeTypeMemWrite
+#
+# Input: MemAddress - Memory Address for doing MEM Write
+# MemData - Data for doing Memory Write
+# MemDataWidth - Write Data Width (Byte=1/Word=2/DWord=4)
+# Mailbox - Data structure contains Data Store info
+#
+# Output: Debuggers can update structure pointed by %edi via this MEM Write Break
+#
+# Registers: All are preserved
+#
+# Description: Function to do Memory Write and set %edi pointer to Mailbox structure,
+# so Debuggers can recognize the GUID and update status in the structure.
+#
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(DoSwbpeTypeMemWrite)
+ASM_PFX(DoSwbpeTypeMemWrite):
+ pushl %edi
+ movl 8(%esp), %edx # MemAddress
+ movl 12(%esp),%eax # MemData
+ movl 16(%esp),%ecx # MemDataWidth
+ movl 20(%esp),%edi # Mailbox
+ cmpl $1, %ecx
+ jne TryMemWriteWord
+ movb %al, (%edx)
+ jmp MemWriteReturn
+TryMemWriteWord:
+ cmpl $2, %ecx
+ jne TryMemWriteDword
+ movw %ax, (%edx)
+ jmp MemWriteReturn
+TryMemWriteDword:
+ cmpl $4, %ecx
+ jne MemWriteReturn
+ movl %eax, (%edx)
+MemWriteReturn:
+ popl %edi
+ ret
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Procedure: DoSwbpeTypeMemRead
+#
+# Input: MemAddress - Memory Address for doing MEM Write
+# MemDataWidth - Write Data Width (Byte=1/Word=2/DWord=4)
+# Mailbox - Data structure contains Data Store info
+#
+# Output: Debuggers can update structure pointed by %edi via this MEM Read Break,
+# %eax contains MEM Read byte/word/dword value depends on PortDataWidth.
+#
+# Registers: All are preserved
+#
+# Description: Function to do Memory Read and set %edi pointer to Mailbox structure,
+# so Debuggers can recognize the GUID and update status in the structure.
+#
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(DoSwbpeTypeMemRead)
+ASM_PFX(DoSwbpeTypeMemRead):
+ pushl %edi
+ xorl %eax, %eax
+ movl 8(%esp), %edx # MemAddress
+ movl 12(%esp), %ecx # MemDataWidth
+ movl 16(%esp), %edi # Mailbox
+ cmpl $1, %ecx
+ jne TryMemReadWord
+ movb (%edx), %al
+ jmp MemReadReturn
+TryMemReadWord:
+ cmpl $2, %ecx
+ jne TryMemReadDword
+ movw (%edx), %ax
+ jmp MemReadReturn
+TryMemReadDword:
+ cmpl $4, %ecx
+ jne MemReadReturn
+ movl (%edx), %eax
+MemReadReturn:
+ popl %edi
+ ret
+
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Procedure: DoSwbpeTypeInt3
+#
+# Input: Mailbox - Data structure contains Data Store informations
+#
+# Output: Debuggers can update structure pointed by %edi via this Interrupt Break
+#
+# Registers: All are preserved
+#
+# Description: Function to do Interrupt 3 and set %edi pointer to Mailbox structure,
+# so Debuggers can recognize the GUID and update status in the structure.
+#
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(DoSwbpeTypeInt3)
+ASM_PFX(DoSwbpeTypeInt3):
+ pushl %edi
+ movl 8(%esp), %edi
+ int $3
+ popl %edi
+ ret
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/Ia32/SwBpeAccess.asm b/QuarkPlatformPkg/Library/SwBpeLib/Ia32/SwBpeAccess.asm
new file mode 100644
index 0000000..7f575fc
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/Ia32/SwBpeAccess.asm
@@ -0,0 +1,261 @@
+;++
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+; Module Name:
+;
+; SwBpeLibIa32.asm
+;
+; Abstract:
+;
+; This file provides low level I/O access functions to trigger
+; breakpoint events.
+;
+;--
+ .686P
+ .MODEL FLAT,C
+ .CODE
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: DoSwbpeTypeIoOut
+;
+; Input: PortAddress - Port Address for doing IO Write
+; PortData - Data value for doing IO Write
+; PortDataWidth - Data Width (Byte=1/Word=2/Dword=4) for doing IO Write
+; Mailbox - Data structure contains Data Store informations
+;
+; Output: Debuggers can update structure pointed by EDI via this IO Write Break.
+;
+; Registers: All are preserved
+;
+; Description: Function to do an IO Write and set EDI EDI pointer to Mailbox structure,
+; so Debuggers can recognize the GUID and update status in the structure.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+DoSwbpeTypeIoOut PROC C USES ECX EDX EDI PortAddress:DWORD, PortData:DWORD, PortDataWidth:DWORD, Mailbox:DWORD
+ ;
+ mov edi, Mailbox
+ mov edx, PortAddress
+ mov eax, PortData
+ mov ecx, PortDataWidth
+ ;
+ cmp ecx, 1
+ jne TryIoOutWord
+ out dx, al
+ jmp IoOutReturn
+ ;
+TryIoOutWord:
+ cmp ecx, 2
+ jne TryIoOutDword
+ out dx, ax
+ jmp IoOutReturn
+ ;
+TryIoOutDword:
+ cmp ecx, 4
+ jne IoOutReturn
+ out dx, eax
+ ;
+IoOutReturn:
+ ret
+ ;
+DoSwbpeTypeIoOut ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: DoSwbpeTypeIoIn
+;
+; Input: PortAddress - Port Address for doing IO Read
+; PortDataWidth - Port data width for doing IO Read
+; Mailbox - Data structure contains Data Store informations
+;
+; Output: Debuggers can update structure pointed by EDI via this IO Read Break,
+; EAX contains IO Read byte/word/dword value depends on PortDataWidth.
+;
+; Registers: All are preserved
+;
+; Description: Function to do an IO Read and set EDI pointer to Mailbox structure,
+; so Debuggers can recognize the GUID and update status in the structure.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+DoSwbpeTypeIoIn PROC C USES ECX EDX EDI PortAddress:DWORD, PortDataWidth:DWORD, Mailbox:DWORD
+ ;
+ xor eax, eax
+ mov edi, Mailbox
+ mov edx, PortAddress
+ mov ecx, PortDataWidth
+ ;
+ cmp ecx, 1
+ jne TryIoInWord
+ in al, dx
+ jmp IoInReturn
+ ;
+TryIoInWord:
+ cmp ecx, 2
+ jne TryIoInDword
+ in ax, dx
+ jmp IoInReturn
+ ;
+TryIoInDword:
+ cmp ecx, 4
+ jne IoInReturn
+ in eax, dx
+ ;
+IoInReturn:
+ ret
+ ;
+DoSwbpeTypeIoIn ENDP
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: DoSwbpeTypeMemWrite
+;
+; Input: MemAddress - Memory Address for doing MEM Write
+; MemData - Data for doing Memory Write
+; MemDataWidth - Write Data Width (Byte=1/Word=2/DWord=4)
+; Mailbox - Data structure contains Data Store info
+;
+; Output: Debuggers can update structure pointed by EDI via this MEM Write Break
+;
+; Registers: All are preserved
+;
+; Description: Function to do Memory Write and set EDI pointer to Mailbox structure,
+; so Debuggers can recognize the GUID and update status in the structure.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+DoSwbpeTypeMemWrite PROC C USES ECX EDX EDI MemAddress:DWORD, MemData:DWORD, MemDataWidth:DWORD, Mailbox:DWORD
+ ;
+ mov edi, Mailbox
+ mov edx, MemAddress
+ mov eax, MemData
+ mov ecx, MemDataWidth
+ ;
+ cmp ecx, 1
+ jne TryMemWriteWord
+ mov BYTE PTR [edx], al
+ jmp MemWriteReturn
+ ;
+TryMemWriteWord:
+ cmp ecx, 2
+ jne TryMemWriteDword
+ mov WORD PTR [edx], ax
+ jmp MemWriteReturn
+ ;
+TryMemWriteDword:
+ cmp ecx, 4
+ jne MemWriteReturn
+ mov DWORD PTR [edx], eax
+ ;
+MemWriteReturn:
+ ret
+ ;
+DoSwbpeTypeMemWrite ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: DoSwbpeTypeMemRead
+;
+; Input: MemAddress - Memory Address for doing MEM Write
+; MemDataWidth - Write Data Width (Byte=1/Word=2/DWord=4)
+; Mailbox - Data structure contains Data Store info
+;
+; Output: Debuggers can update structure pointed by EDI via this MEM Read Break,
+; EAX contains MEM Read byte/word/dword value depends on PortDataWidth.
+;
+; Registers: All are preserved
+;
+; Description: Function to do Memory Read and set EDI pointer to Mailbox structure,
+; so Debuggers can recognize the GUID and update status in the structure.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+DoSwbpeTypeMemRead PROC C USES ECX EDX EDI MemAddress:DWORD, MemDataWidth:DWORD, Mailbox:DWORD
+ ;
+ xor eax, eax
+ mov edi, Mailbox
+ mov edx, MemAddress
+ mov ecx, MemDataWidth
+ ;
+ cmp ecx, 1
+ jne TryMemReadWord
+ mov al, BYTE PTR [edx]
+ jmp MemReadReturn
+ ;
+TryMemReadWord:
+ cmp ecx, 2
+ jne TryMemReadDword
+ mov ax, WORD PTR [edx]
+ jmp MemReadReturn
+ ;
+TryMemReadDword:
+ cmp ecx, 4
+ jne MemReadReturn
+ mov eax, DWORD PTR [edx]
+ ;
+MemReadReturn:
+ ret
+ ;
+DoSwbpeTypeMemRead ENDP
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: DoSwbpeTypeInt3
+;
+; Input: Mailbox - Data structure contains Data Store informations
+;
+; Output: Debuggers can update structure pointed by EDI via this Interrupt Break
+;
+; Registers: All are preserved
+;
+; Description: Function to do Interrupt 3 and set EDI pointer to Mailbox structure,
+; so Debuggers can recognize the GUID and update status in the structure.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+DoSwbpeTypeInt3 PROC C USES EDI Mailbox:DWORD
+ ;
+ mov edi, Mailbox
+ int 3
+ ret
+ ;
+DoSwbpeTypeInt3 ENDP
+
+
+END
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/PeiDsAlloc.c b/QuarkPlatformPkg/Library/SwBpeLib/PeiDsAlloc.c
new file mode 100644
index 0000000..aafc35c
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/PeiDsAlloc.c
@@ -0,0 +1,183 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PeiDsAlloc.c
+
+Abstract:
+
+ This file implements DS debug feature NEM and RAM buffers allocations in PEI phase,
+ see "Enabling DS for External Debugger" feature documentation for more details.
+
+--*/
+
+#include "CommonHeader.h"
+
+EFI_STATUS
+EFIAPI
+DsRamAllocationCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mDsRamNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ DsRamAllocationCallback
+};
+
+//
+// Function Implementations
+//
+VOID
+BpeDsAllocation (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Allocate NEM buffer for Data Store function and set callback for DRAM allocation in PEI phase
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS *DsNemAddress;
+
+ //
+ // Check for Debugger
+ //
+ DsBreakpointEvent (DsConfigSwBpeIdCheck, 0, 0, &Status);
+
+ //
+ // If Debugger is present, ...
+ //
+ if (Status == EFI_SUCCESS) {
+ //
+ // ...allocate DS buffer in NEM
+ //
+ Status = PeiServicesAllocatePool (DS_CONFIG_NEM_SIZE, (VOID **)&DsNemAddress);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Notify Debugger
+ //
+ DsBreakpointEvent (
+ DsConfigSwBpeIdNemStart,
+ (EFI_PHYSICAL_ADDRESS) (UINTN) DsNemAddress,
+ DS_CONFIG_NEM_SIZE,
+ &Status
+ );
+
+ //
+ // Register Notify callback for doing RAM buffer allocation
+ //
+ Status = PeiServicesNotifyPpi (&mDsRamNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+EFI_STATUS
+EFIAPI
+DsRamAllocationCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+/*++
+
+Routine Description:
+
+ Internal function to allocate RAM buffer for DS function in PEI phase
+
+Arguments:
+
+ PeiServices General purpose services available to every PEIM.
+ NotifyDescriptor The notification structure this PEIM registered on install.
+ Ppi The memory discovered PPI. Not used.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS DsDramAddress;
+ UINTN SizeInByte;
+
+ //
+ // Disable DS Cache As Ram buffer
+ //
+ DsBreakpointEvent (DsConfigSwBpeIdNemStop, 0, 0, &Status);
+
+ //
+ // Check for Debugger
+ //
+ DsBreakpointEvent (DsConfigSwBpeIdCheck, 0, 0, &Status);
+
+ //
+ // If Debugger is present, ...
+ //
+ if (Status == EFI_SUCCESS) {
+ SizeInByte = DS_CONFIG_DRAM_SIZE;
+ //
+ // ...allocate DS buffer from DRAM
+ //
+ Status = PeiServicesAllocatePages (
+ EfiRuntimeServicesData,
+ SizeInByte / EFI_PAGE_SIZE,
+ &DsDramAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Notify Debugger
+ //
+ DsBreakpointEvent (
+ DsConfigSwBpeIdDramStart,
+ DsDramAddress,
+ DS_CONFIG_DRAM_SIZE,
+ &Status
+ );
+ }
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/SwBpe.h b/QuarkPlatformPkg/Library/SwBpeLib/SwBpe.h
new file mode 100644
index 0000000..15e5a44
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/SwBpe.h
@@ -0,0 +1,103 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SwBpe.h
+
+Abstract:
+
+ This library provides Software Breakpoint Event interface with Debugger.
+
+--*/
+
+
+#ifndef _SW_BPE_H_
+#define _SW_BPE_H_
+
+//
+// These values represent events types the SWBPE interface supports.
+//
+typedef enum {
+ SwbpeTypeUndefined = 0,
+ SwbpeTypeIoIn = 1,
+ SwbpeTypeIoOut = 2,
+ SwbpeTypeMemRead = 3,
+ SwbpeTypeMemWrite = 4,
+ SwbpeTypeIntXX = 5,
+ SwbpeTypeMax = 6
+} SWBPE_EVENT_TYPE;
+
+typedef enum {
+ SwbpeWidthByte = 1,
+ SwbpeWidthWord = 2,
+ SwbpeWidthDword = 4
+} SWBPE_EVENT_DATA_WIDTH;
+
+
+//
+// This is the data structure the SWBPE interface uses
+// to communicate with a debugger.
+//
+#pragma pack (push, 1)
+typedef struct {
+ UINT64 EventType;
+ EFI_PHYSICAL_ADDRESS EventAddress;
+ UINT64 EventData;
+ UINT64 EventDataWidth;
+ EFI_PHYSICAL_ADDRESS DebuggerArgs;
+ EFI_STATUS DebuggerStatus;
+} SWBPE_MAILBOX;
+#pragma pack (pop)
+
+
+VOID
+SoftwareBreakpointEvent (
+ IN OUT SWBPE_MAILBOX *Mailbox
+ )
+/*++
+
+Routine Description:
+
+ This function generates an action that can be trapped by an debugger.
+
+Arguments:
+
+ Mailbox - A pointer to a data structure that contains information about the event and data payload.
+
+Returns:
+
+ EFI_SUCCESS - The function event was intercepted by the debugger and handled successfully
+ EFI_UNSUPPORTED - The function event was not intercepted by the debugger
+
+--*/
+;
+
+#endif // _SW_BPE_H_
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.c b/QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.c
new file mode 100644
index 0000000..5c0cae3
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.c
@@ -0,0 +1,154 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ SwBpeLib.c
+
+Abstract:
+
+ This library provides Software Breakpoint Event interface with Debugger.
+
+--*/
+
+#include "CommonHeader.h"
+
+VOID
+DoSwbpeTypeIoOut (
+ UINTN PortAddress,
+ UINTN PortData,
+ UINTN PortDataWidth,
+ UINTN MailboxAddress
+ );
+
+UINTN
+DoSwbpeTypeIoIn (
+ UINTN PortAddress,
+ UINTN PortDataWidth,
+ UINTN MailboxAddress
+ );
+
+UINTN
+DoSwbpeTypeMemRead (
+ UINTN MemAddress,
+ UINTN MemDataWidth,
+ UINTN MailboxAddress
+ );
+
+VOID
+DoSwbpeTypeMemWrite (
+ UINTN MemAddress,
+ UINTN MemData,
+ UINTN MemDataWidth,
+ UINTN MailboxAddress
+ );
+
+VOID
+DoSwbpeTypeInt3 (
+ UINTN MailboxAddress
+ );
+
+VOID
+SoftwareBreakpointEvent (
+ SWBPE_MAILBOX *Mailbox
+ )
+/*++
+
+Routine Description:
+
+ This function generates an action that can be trapped by an debugger.
+
+Arguments:
+
+ Mailbox - A pointer to a data structure that contains information about the event and data payload.
+
+Returns:
+
+ EFI_SUCCESS - The function event was intercepted by the debugger and handled successfully
+ EFI_UNSUPPORTED - The function event was not intercepted by the debugger
+
+--*/
+{
+ //
+ // Initialize the mailbox to check for debugger presence
+ //
+ Mailbox->DebuggerStatus = EFI_UNSUPPORTED;
+
+ //
+ // Determine the type of event, and invoke it
+ //
+ switch (Mailbox->EventType) {
+
+ case SwbpeTypeIoOut:
+ DoSwbpeTypeIoOut (
+ (UINTN) Mailbox->EventAddress,
+ (UINTN) Mailbox->EventData,
+ (UINTN) Mailbox->EventDataWidth,
+ (UINTN) Mailbox
+ );
+ break;
+
+ case SwbpeTypeIoIn:
+ Mailbox->EventData = DoSwbpeTypeIoIn (
+ (UINTN) Mailbox->EventAddress,
+ (UINTN) Mailbox->EventDataWidth,
+ (UINTN) Mailbox
+ );
+ break;
+
+ case SwbpeTypeMemWrite:
+ DoSwbpeTypeMemWrite (
+ (UINTN) Mailbox->EventAddress,
+ (UINTN) Mailbox->EventData,
+ (UINTN) Mailbox->EventDataWidth,
+ (UINTN) Mailbox
+ );
+ break;
+
+ case SwbpeTypeMemRead:
+ Mailbox->EventData = DoSwbpeTypeMemRead (
+ (UINTN) Mailbox->EventAddress,
+ (UINTN) Mailbox->EventDataWidth,
+ (UINTN) Mailbox
+ );
+ break;
+
+ case SwbpeTypeIntXX:
+ DoSwbpeTypeInt3 ((UINTN) Mailbox);
+ break;
+
+ default:
+ //
+ // If type not recognized then just leave EFI_UNSUPPORTED
+ //
+ break;
+ }
+}
+
diff --git a/QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.inf b/QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.inf
new file mode 100644
index 0000000..8c09718
--- /dev/null
+++ b/QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.inf
@@ -0,0 +1,80 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# SwBpelib.inf
+#
+# Abstract:
+#
+# Library producing a SW Break event PEI functionality.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SwBpeLib
+ FILE_GUID = 07B80139-BD4A-4be4-AE81-A10E8754BDEB
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SwBpeLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+[BuildOptions]
+ MSFT:*_*_IA32_CC_FLAGS = /D DS_CONFIG_NEM_SIZE=0x1000 /D DS_CONFIG_DRAM_SIZE=0x100000 /D DS_CONFIG_SWBPE_TYPE=2 /D DS_CONFIG_SWBPE_ADDRESS=0x99 /D DS_CONFIG_SWBPE_DATA=0x0 /D DS_CONFIG_SWBPE_DATA_WIDTH=2
+ GCC:*_*_IA32_CC_FLAGS = -D DS_CONFIG_NEM_SIZE=0x1000 -D DS_CONFIG_DRAM_SIZE=0x100000 -D DS_CONFIG_SWBPE_TYPE=2 -D DS_CONFIG_SWBPE_ADDRESS=0x99 -D DS_CONFIG_SWBPE_DATA=0x0 -D DS_CONFIG_SWBPE_DATA_WIDTH=2
+
+[Sources]
+ CommonHeader.h
+ SwBpe.h
+ SwBpeLib.c
+ DsConfig.h
+ DsConfig.c
+ PeiDsAlloc.c
+ Ia32/SwBpeAccess.asm
+ Ia32/SwBpeAccess.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ PeiServicesLib
+
+[FeaturePcd]
+
+[Pcd]
diff --git a/QuarkPlatformPkg/Override/BaseTools/Conf/build_rule.template b/QuarkPlatformPkg/Override/BaseTools/Conf/build_rule.template
new file mode 100644
index 0000000..92a207d
--- /dev/null
+++ b/QuarkPlatformPkg/Override/BaseTools/Conf/build_rule.template
@@ -0,0 +1,559 @@
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+## Syntax
+#
+# "*" is used to indicate that the source files will be processed at the same time.
+# "?" is used to indicate that the source files will be processed one by one.
+#
+# "[" <File-Type>[.<Build-Type>][.<Arch>][, <File-Type>[.<Build-Type>][.<Arch>]] "]" <EOL>
+# <InputFile[.<ToolChainFamily>]> <EOL>
+# (?|*).<File-Extension> [(\n|,) (?|*).<File-Extension>]
+#
+# <OutputFile[.<ToolChainFamily>]> <EOL>
+# <FileFullPath>
+#
+# <ExtraDependency>
+# <FileFullPath>
+#
+# <Command[.<ToolChainFamily>]> <EOL>
+# <Command1>
+# [<Command2>]
+#
+# <Build-Type> is the MODULE_TYPE in EDK2 or COMPONENT_TYPE in EDK.
+# Missing <InputFile> will cause an exception and break build.
+# Missing <Command> will cause that related build target won't be generated but
+# won't break build.
+#
+
+## Placeholders for string substitution
+#
+# ${src} Source file(s) to be built (full path)
+# ${s_path} Source file directory (absolute path)
+# ${s_dir} Source file relative directory within a module
+# (Note: ${s_dir} is always equals to "." if source file is given in absolute path.)
+# ${s_name} Source file name without path
+# ${s_base} Source file name without extension and path
+# ${s_ext} Source file extension
+#
+# ${dst} Destination file(s) built from ${src} (full path)
+# ${d_path} Destination file directory (absolute path)
+# ${d_name} Destination file name without path
+# ${d_base} Destination file name without extension and path
+# ${d_ext} Destination file extension
+#
+# (+) Directory separator
+#
+
+## Macro
+# $(WORKSPACE) Workspace directory
+# $(OUTPUT_DIR) Directory for intermediate files for building a module
+# $(DEBUG_DIR) Directory for files used to debug a module
+# $(BUILD_DIR) All files for building a platform will be put in this directory
+# $(BIN_DIR) Common directory for executable files
+# $(FV_DIR) Directory to store flash image files
+# $(INC) Search path of current module
+# $(INC_LIST) A file containing search pathes of current module
+# $(LIBS) Static library files of current module
+# $(<tool>_FLAGS) Tools flags of current module
+# $(MODULE_NAME) Current module name
+# $(MODULE_TYPE) Current module type
+# $(MODULE_GUID) Current module guid
+# $(ARCH) Architecture of current module
+# $(TOOLCHAIN) Toolchain used to build current module
+# $(TARGET) Target of current module (DEBUG/RELEASE)
+# $(<tool>) Path of tool
+# $(EDK_TOOLS_PATH) Path of build tools
+# $(<FILE_TYPES>) File list of each file type
+# (Note: The macro name is derived from file type name. For example,
+# C-Code-File will have C_CODE_FILES macro.)
+# $(<FILE_TYPES_LIST>) Macro point to a file containing list of files of a file type
+# (
+# Note: The macro and file name are derived from file type name.
+# For example, C-Code-File will have C_CODE_FILES_LIST macro pointing
+# to $(OUTPUT_DIR)/c_code_files.lst. The list file and macro name
+# will be generated only when this macro is used in command line.
+# This is intended to get over the long command line limitation.
+# )
+#
+# $(CP) copy command
+# $(MV) move command
+# $(RM) delete command
+# $(MD) create dir command
+# $(RD) remove dir command
+#
+
+## Reserved File-Type
+#
+# Don't change following names of file types and their associated files,
+# which are also used in tools' code
+#
+# C-Code-File
+# C-Header-File
+# Dynamic-Library-File
+# Static-Library-File
+# Visual-Form-Representation-File
+# Unicode-Text-File
+#
+
+## Build Rule Version Number
+# build_rule_version=0.1
+#
+
+[C-Code-File]
+ <InputFile>
+ ?.c
+ ?.C
+ ?.cc
+ ?.CC
+ ?.cpp
+ ?.Cpp
+ ?.CPP
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+
+ <Command.MSFT, Command.INTEL>
+ "$(CC)" /Fo${dst} $(CC_FLAGS) $(INC) ${src}
+
+ <Command.GCC, Command.RVCT>
+ # For RVCTCYGWIN CC_FLAGS must be first to work around pathing issues
+ "$(CC)" $(CC_FLAGS) -o ${dst} $(INC) ${src}
+ "$(SYMRENAME)" $(SYMRENAME_FLAGS) ${dst}
+
+ <Command.ARMGCC, Command.ARMLINUXGCC>
+ "$(CC)" $(CC_FLAGS) -o ${dst} $(INC) ${src}
+
+
+[C-Header-File]
+ <InputFile>
+ *.h, *.H
+
+ <OutputFile>
+
+ <Command>
+
+
+[Assembly-Code-File.COMMON.COMMON]
+ <InputFile.MSFT, InputFile.INTEL, InputFile.RVCT>
+ ?.asm, ?.Asm, ?.ASM
+
+ <InputFile.GCC>
+ ?.S, ?.s
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+
+ <Command.MSFT, Command.INTEL>
+ "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i
+ Trim --source-code --convert-hex -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i
+ "$(ASM)" /Fo${dst} $(ASM_FLAGS) /I${s_path} $(INC) ${d_path}(+)${s_base}.iii
+
+ <Command.GCC, Command.RVCT>
+ "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i
+ Trim --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i
+ # For RVCTCYGWIN ASM_FLAGS must be first to work around pathing issues
+ "$(ASM)" $(ASM_FLAGS) -o ${dst} $(INC) ${d_path}(+)${s_base}.iii
+
+[Assembly-Code-File.COMMON.IPF]
+ <InputFile>
+ ?.s
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+
+ <Command.MSFT, Command.INTEL>
+ "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i
+ Trim --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i
+ # For RVCTCYGWIN ASM_FLAGS must be first to work around pathing issues
+ "$(ASM)" $(ASM_FLAGS) -o ${dst} ${d_path}(+)${s_base}.iii
+
+[Visual-Form-Representation-File]
+ <InputFile>
+ ?.vfr
+ ?.Vfr
+ ?.VFR
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(DEBUG_DIR)(+)${s_dir}(+)${s_base}.c
+
+ <Command>
+ "$(VFRPP)" $(VFRPP_FLAGS) $(INC) ${src} > $(OUTPUT_DIR)(+)${s_base}.i
+ "$(VFR)" $(VFR_FLAGS) --string-db $(OUTPUT_DIR)(+)$(MODULE_NAME)StrDefs.hpk --output-directory ${d_path} $(OUTPUT_DIR)(+)${s_base}.i
+
+[Object-File]
+ <InputFile>
+ *.obj
+ *.o
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)$(MODULE_NAME).lib
+
+ <Command.MSFT, Command.INTEL>
+ "$(SLINK)" $(SLINK_FLAGS) /OUT:${dst} @$(OBJECT_FILES_LIST)
+
+ <Command.GCC>
+ "$(SLINK)" -cr ${dst} $(SLINK_FLAGS) @$(OBJECT_FILES_LIST)
+
+ <Command.RVCT>
+ "$(SLINK)" $(SLINK_FLAGS) ${dst} --via $(OBJECT_FILES_LIST)
+
+ <Command.RVCTCYGWIN, Command.ARMGCC, Command.ARMLINUXGCC>
+ # $(OBJECT_FILES_LIST) has wrong paths for cygwin
+ "$(SLINK)" $(SLINK_FLAGS) ${dst} $(OBJECT_FILES)
+
+ <Command.XCODE>
+ "$(SLINK)" $(SLINK_FLAGS) ${dst} -filelist $(OBJECT_FILES_LIST)
+
+[Static-Library-File]
+ <InputFile>
+ *.lib
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(DEBUG_DIR)(+)$(MODULE_NAME).dll
+
+ <Command.MSFT, Command.INTEL>
+ "$(DLINK)" /OUT:${dst} $(DLINK_FLAGS) $(DLINK_SPATH) @$(STATIC_LIBRARY_FILES_LIST)
+
+ <Command.GCC>
+ "$(DLINK)" -o ${dst} $(DLINK_FLAGS) -\( $(DLINK_SPATH) @$(STATIC_LIBRARY_FILES_LIST) -\) $(DLINK2_FLAGS)
+ "$(OBJCOPY)" $(OBJCOPY_FLAGS) ${dst}
+
+ <Command.ARMGCC, Command.ARMLINUXGCC>
+ "$(DLINK)" -o ${dst} $(DLINK_FLAGS) -\( $(DLINK_SPATH) $(STATIC_LIBRARY_FILES) -\) $(DLINK2_FLAGS)
+
+ <Command.RVCT>
+ "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) --via $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
+
+ <Command.RVCTCYGWIN>
+ #$(STATIC_LIBRARY_FILES_LIST) has wrong paths for cygwin
+ "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) $(STATIC_LIBRARY_FILES) $(DLINK2_FLAGS)
+
+ <Command.XCODE>
+ "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
+
+
+[Static-Library-File.USER_DEFINED]
+ <InputFile>
+ *.lib
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(DEBUG_DIR)(+)$(MODULE_NAME)
+
+ <Command.MSFT, Command.INTEL>
+ "$(DLINK)" $(DLINK_FLAGS) $(DLINK_SPATH) @$(STATIC_LIBRARY_FILES_LIST)
+
+ <Command.GCC>
+ "$(DLINK)" $(DLINK_FLAGS) -\( $(DLINK_SPATH) @$(STATIC_LIBRARY_FILES_LIST) -\) $(DLINK2_FLAGS)
+
+ <Command.ARMGCC, Command.ARMLINUXGCC>
+ "$(DLINK)" $(DLINK_FLAGS) -\( $(DLINK_SPATH) $(STATIC_LIBRARY_FILES) -\) $(DLINK2_FLAGS)
+
+ <Command.RVCT>
+ "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) --via $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
+
+ <Command.RVCTCYGWIN>
+ #$(STATIC_LIBRARY_FILES_LIST) has the wrong paths for cygwin
+ "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) $(STATIC_LIBRARY_FILES) $(DLINK2_FLAGS)
+
+ <Command.XCODE>
+ "$(DLINK)" -o ${dst} $(DLINK_FLAGS) $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
+
+
+[Dynamic-Library-File]
+ <InputFile>
+ ?.dll
+
+ <OutputFile>
+ $(DEBUG_DIR)(+)$(MODULE_NAME).efi
+
+ <Command.MSFT, Command.INTEL, Command.RVCT, Command.ARMGCC, Command.ARMLINUXGCC>
+ "$(GENFW)" -e $(MODULE_TYPE) -o ${dst} ${src} $(GENFW_FLAGS)
+ $(CP) ${dst} $(OUTPUT_DIR)
+ $(CP) ${dst} $(BIN_DIR)
+ -$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
+
+ <Command.GCC>
+ $(OBJCOPY) --only-keep-debug ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).debug
+ $(OBJCOPY) --strip-unneeded ${src}
+
+ #
+ #The below 2 lines are only needed for UNIXGCC tool chain, which genereates PE image directly
+ #
+ -$(OBJCOPY) $(OBJCOPY_ADDDEBUGFLAG) ${src}
+ -$(CP) $(DEBUG_DIR)(+)$(MODULE_NAME).debug $(BIN_DIR)
+
+ "$(GENFW)" -e $(MODULE_TYPE) -o ${dst} ${src} $(GENFW_FLAGS)
+ $(CP) ${dst} $(OUTPUT_DIR)
+ $(CP) ${dst} $(BIN_DIR)
+ -$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
+
+ <Command.XCODE>
+ # tool to convert Mach-O to PE/COFF
+ "$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff
+ # create symbol file for GDB debug
+ -$(DSYMUTIL) ${src}
+ "$(GENFW)" -e $(MODULE_TYPE) -o ${dst} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff $(GENFW_FLAGS)
+ $(CP) ${dst} $(OUTPUT_DIR)
+ $(CP) ${dst} $(BIN_DIR)
+ -$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
+
+[Dependency-Expression-File]
+ <InputFile>
+ ?.dxs, ?.Dxs, ?.DXS
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)$(MODULE_NAME).depex
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <Command>
+ "$(PP)" $(APP_FLAGS) $(INC) ${src} > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i
+ Trim --source-code -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i
+ GenDepex -t $(MODULE_TYPE) -o ${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
+
+[Acpi-Source-Language-File]
+ <InputFile>
+ ?.asl, ?.Asl, ?.ASL
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <Command.MSFT, Command.INTEL>
+ Trim --asl-file -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i -i $(INC_LIST) ${src}
+ "$(ASLPP)" $(ASLPP_FLAGS) $(INC) /I${s_path} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
+ Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
+ "$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii
+
+ <Command.GCC>
+ Trim --asl-file -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i -i $(INC_LIST) ${src}
+ "$(ASLPP)" $(ASLPP_FLAGS) $(INC) -I${s_path} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
+ "$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
+
+[C-Code-File.AcpiTable]
+ <InputFile>
+ ?.c
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.acpi
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <Command.MSFT, Command.INTEL>
+ "$(ASLCC)" /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(INC) ${src}
+ "$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+ "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
+
+ <Command.GCC>
+ "$(ASLCC)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(INC) ${src}
+ "$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+ "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
+
+[Acpi-Table-Code-File]
+ <InputFile>
+ ?.aslc, ?.act
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.acpi
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <Command.MSFT, Command.INTEL>
+ "$(ASLCC)" /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(INC) ${src}
+ "$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+ "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
+
+ <Command.GCC>
+ "$(ASLCC)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(INC) ${src}
+ "$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+ "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
+
+ <Command.XCODE>
+ "$(ASLCC)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(INC) ${src}
+ "$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+ "$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.efi
+ "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.efi $(GENFW_FLAGS)
+
+
+[Masm16-Code-File]
+ <InputFile>
+ ?.asm16, ?.Asm16, ?.ASM16 ?.s16 ?.S16
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.com
+
+ <Command.MSFT, Command.INTEL>
+ "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i
+ Trim --source-code --convert-hex -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i
+ "$(ASM16)" /nologo /c /omf $(INC) /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj ${d_path}(+)${s_base}.iii
+ "$(ASMLINK)" $(ASMLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj,${dst},,,,
+
+ <Command.GCC>
+ "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i
+ Trim --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i
+ "$(ASM)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASM_FLAGS) $(INC) ${d_path}(+)${s_base}.iii
+ "$(OBJCOPY)" -O binary $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj ${dst}
+
+ <Command.XCODE>
+ "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i
+ Trim --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i
+ "$(ASM)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASM_FLAGS) $(INC) ${d_path}(+)${s_base}.iii
+ "$(SLINK)" $(SLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.slib $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
+ otool -t $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.slib | hex2bin.py ${dst}
+
+
+[Microcode-File.USER_DEFINED, Microcode-File.Microcode]
+ <InputFile>
+ ?.txt, ?.TXT, ?.Txt, ?.mut, ?.inc
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_base}.mcb
+
+ <Command>
+ "$(GENFW)" -o ${dst} -m ${src} $(GENFW_FLAGS)
+
+[Microcode-Binary-File]
+ <InputFile>
+ *.mcb
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)$(MODULE_NAME).bin
+
+ <Command>
+ "$(GENFW)" -o ${dst} -j $(MICROCODE_BINARY_FILES) $(GENFW_FLAGS)
+ -$(CP) ${dst} $(BIN_DIR)
+
+[EFI-Image-File]
+ <InputFile>
+ ?.efi, ?.Efi, ?.EFI
+
+ <OutputFile>
+
+ <Command>
+
+[Unicode-Text-File]
+ <InputFile>
+ *.uni, *.Uni, *.UNI
+
+ <OutputFile>
+ $(DEBUG_DIR)(+)AutoGen.c
+ $(DEBUG_DIR)(+)$(MODULE_NAME)StrDefs.h
+ $(OUTPUT_DIR)(+)$(MODULE_NAME)StrDefs.hpk
+
+ <Command>
+
+[Efi-Image.UEFI_OPTIONROM]
+ <InputFile>
+ ?.efi, ?.EFI, ?.Efi
+
+ <OutputFile>
+ $(BIN_DIR)(+)$(MODULE_NAME).rom
+
+ <Command>
+ $(OPTROM) -i $(PCI_DEVICE_ID) -f $(PCI_VENDOR_ID) -l $(PCI_CLASS_CODE) -r $(PCI_REVISION) -o $dst $(OPTROM_FLAGS) $src
+
+[Unicode-Text-File.UEFI_HII]
+ <InputFile>
+ *.uni, *.Uni, *.UNI
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)$(MODULE_NAME)StrDefs.hpk
+ $(DEBUG_DIR)(+)$(MODULE_NAME)StrDefs.h
+
+ <Command>
+
+[Visual-Form-Representation-File.UEFI_HII]
+ <InputFile>
+ ?.vfr
+ ?.Vfr
+ ?.VFR
+
+ <ExtraDependency>
+ $(MAKE_FILE)
+
+ <OutputFile>
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.hpk
+
+ <Command>
+ "$(VFRPP)" $(VFRPP_FLAGS) $(INC) ${src} > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i
+ "$(VFR)" $(VFR_FLAGS) --create-ifr-package --string-db $(OUTPUT_DIR)(+)$(MODULE_NAME)StrDefs.hpk --output-directory $(OUTPUT_DIR)(+)${s_dir} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i
+
+[Hii-Binary-Package.UEFI_HII]
+ <InputFile>
+ *.hpk
+
+ <OutputFile.MSFT, OutputFile.INTEL, OutputFile.GCC>
+ $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.lib
+
+ <OutputFile.XCODE, OutputFile.RVCT, OutputFile.ARMGCC>
+ $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc
+
+ <Command.MSFT, Command.INTEL>
+ "$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiipackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS)
+ "$(RC)" /Fo${dst} $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc
+
+ <Command.GCC>
+ "$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiibinpackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS)
+ "$(RC)" $(RC_FLAGS) $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc ${dst}
+
+ <Command.XCODE, Command.RVCT, Command.ARMGCC, Command.ARMLINUXGCC>
+ GenFw -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiibinpackage $(HII_BINARY_PACKAGES)
+
+
diff --git a/QuarkPlatformPkg/Override/BaseTools/Conf/tools_def.template b/QuarkPlatformPkg/Override/BaseTools/Conf/tools_def.template
new file mode 100755
index 0000000..ff702d9
--- /dev/null
+++ b/QuarkPlatformPkg/Override/BaseTools/Conf/tools_def.template
@@ -0,0 +1,5123 @@
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+IDENTIFIER = Default TOOL_CHAIN_CONF
+
+# common path macros
+DEFINE VS2003_BIN = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin
+DEFINE VS2003_DLL = C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE
+
+DEFINE VS2005_BIN = C:\Program Files\Microsoft Visual Studio 8\Vc\bin
+DEFINE VS2005_DLL = C:\Program Files\Microsoft Visual Studio 8\Common7\IDE;DEF(VS2005_BIN)
+DEFINE VS2005_BINX64 = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\x86_amd64
+DEFINE VS2005_BIN64 = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\x86_ia64
+
+DEFINE VS2005x86_BIN = C:\Program Files (x86)\Microsoft Visual Studio 8\Vc\bin
+DEFINE VS2005x86_DLL = C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE;DEF(VS2005x86_BIN)
+DEFINE VS2005x86_BINX64 = DEF(VS2005x86_BIN)\x86_amd64
+DEFINE VS2005x86_BIN64 = DEF(VS2005x86_BIN)\x86_ia64
+
+DEFINE VS2008_BIN = C:\Program Files\Microsoft Visual Studio 9.0\Vc\bin
+DEFINE VS2008_DLL = C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE;DEF(VS2008_BIN)
+DEFINE VS2008_BINX64 = DEF(VS2008_BIN)\x86_amd64
+DEFINE VS2008_BIN64 = DEF(VS2008_BIN)\x86_ia64
+
+DEFINE VS2008x86_BIN = C:\Program Files (x86)\Microsoft Visual Studio 9.0\Vc\bin
+DEFINE VS2008x86_DLL = C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE;DEF(VS2008x86_BIN)
+DEFINE VS2008x86_BINX64 = DEF(VS2008x86_BIN)\x86_amd64
+DEFINE VS2008x86_BIN64 = DEF(VS2008x86_BIN)\x86_ia64
+
+DEFINE VS2010_BIN = C:\Program Files\Microsoft Visual Studio 10.0\Vc\bin
+DEFINE VS2010_DLL = C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE;DEF(VS2010_BIN)
+DEFINE VS2010_BINX64 = DEF(VS2010_BIN)\x86_amd64
+DEFINE VS2010_BIN64 = DEF(VS2010_BIN)\x86_ia64
+
+DEFINE VS2010x86_BIN = C:\Program Files (x86)\Microsoft Visual Studio 10.0\Vc\bin
+DEFINE VS2010x86_DLL = C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE;DEF(VS2010x86_BIN)
+DEFINE VS2010x86_BINX64 = DEF(VS2010x86_BIN)\x86_amd64
+DEFINE VS2010x86_BIN64 = DEF(VS2010x86_BIN)\x86_ia64
+
+DEFINE WINSDK_VERSION = v6.0A
+DEFINE WINSDK_BIN = c:\Program Files\Microsoft SDKs\Windows\DEF(WINSDK_VERSION)\bin
+DEFINE WINSDKx86_BIN = c:\Program Files (x86)\Microsoft SDKs\Windows\DEF(WINSDK_VERSION)\bin
+
+# These defines are needed for certain Microsoft Visual Studio tools that
+# are used by other toolchains. An example is that ICC on Windows normally
+# uses Microsoft's nmake.exe.
+
+# Some MS_VS_BIN options: DEF(VS2003_BIN), DEF(VS2005_BIN), DEF(VS2005x86_BIN), DEF(VS2008_BIN), DEF(VS2008x86_BIN)
+DEFINE MS_VS_BIN = DEF(VS2005_BIN)
+# Some MS_VS_DLL options: DEF(VS2003_DLL), DEF(VS2005_DLL), DEF(VS2005x86_DLL), DEF(VS2008_DLL), DEF(VS2008x86_DLL)
+DEFINE MS_VS_DLL = DEF(VS2005_DLL)
+
+DEFINE WINDDK_BIN16 = C:\WINDDK\3790.1830\bin\bin16
+DEFINE WINDDK_BIN32 = C:\WINDDK\3790.1830\bin\x86
+DEFINE WINDDK_BINX64 = C:\WINDDK\3790.1830\bin\win64\x86\amd64
+DEFINE WINDDK_BIN64 = C:\WINDDK\3790.1830\bin\win64\x86
+
+# NOTE: The Intel C++ Compiler for Windows requires one of the Microsoft C compiler
+# tool chains for the linker and nmake commands.
+# This configuration assumes a Windows 2003 Server DDK installation.
+DEFINE ICC_VERSION = 9.1
+#DEFINE ICC_VERSION = 10.1.021
+DEFINE ICC_BIN32 = C:\Program Files\Intel\Compiler\C++\DEF(ICC_VERSION)\IA32\Bin
+DEFINE ICC_ASM32 = C:\Program Files\Intel\Compiler\C++\DEF(ICC_VERSION)\IA32\Bin
+DEFINE ICC_BIN32x86 = C:\Program Files (x86)\Intel\Compiler\C++\DEF(ICC_VERSION)\IA32\Bin
+DEFINE ICC_ASM32x86 = C:\Program Files (x86)\Intel\Compiler\C++\DEF(ICC_VERSION)\IA32\Bin
+
+DEFINE ICC_BINX64 = C:\Program Files\Intel\Compiler\C++\DEF(ICC_VERSION)\EM64T\Bin
+DEFINE ICC_ASMX64 = C:\Program Files\Intel\Compiler\C++\DEF(ICC_VERSION)\EM64T\Bin
+DEFINE ICC_BINX64x86 = C:\Program Files (x86)\Intel\Compiler\C++\DEF(ICC_VERSION)\EM64T\Bin
+DEFINE ICC_ASMX64x86 = C:\Program Files (x86)\Intel\Compiler\C++\DEF(ICC_VERSION)\EM64T\Bin
+
+DEFINE ICC_BIN64 = C:\Program Files\Intel\Compiler\C++\DEF(ICC_VERSION)\Itanium\Bin
+DEFINE ICC_BIN64x86 = C:\Program Files (x86)\Intel\Compiler\C++\DEF(ICC_VERSION)\Itanium\Bin
+
+
+# Note: The Intel C++ Compiler 11.1 uses different installation path from previous versions
+# We use "ICC11" tag for ICC 11.1 while "ICC" tag is dedicated for eariler versions
+#
+DEFINE ICC11_VERSION = 11.1
+DEFINE ICC11_BUILD = 072
+DEFINE ICC11_BIN32 = C:\Program Files\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\ia32
+DEFINE ICC11_ASM32 = C:\Program Files\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\ia32
+DEFINE ICC11_BIN32x86 = C:\Program Files (x86)\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\ia32
+DEFINE ICC11_ASM32x86 = C:\Program Files (x86)\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\ia32
+
+DEFINE ICC11_BINX64 = C:\Program Files\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\ia32_intel64
+DEFINE ICC11_ASMX64 = C:\Program Files\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\ia32_intel64
+DEFINE ICC11_BINX64x86 = C:\Program Files (x86)\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\intel64
+DEFINE ICC11_ASMX64x86 = C:\Program Files (x86)\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\intel64
+
+DEFINE ICC11_BIN64 = C:\Program Files\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\ia32_ia64
+DEFINE ICC11_BIN64x86 = C:\Program Files (x86)\Intel\Compiler\DEF(ICC11_VERSION)\DEF(ICC11_BUILD)\bin\ia32_ia64
+
+DEFINE EBC_BIN = C:\Program Files\Intel\EBC\Bin
+DEFINE EBC_BINx86 = C:\Program Files (x86)\Intel\EBC\Bin
+
+DEFINE ELFGCC_BIN = /usr/bin
+
+#
+# Option 1: Hard coded full path to compiler suite
+DEFINE UNIXGCC_IA32_PETOOLS_PREFIX = /opt/tiano/i386-tiano-pe/i386-tiano-pe/bin/
+DEFINE UNIXGCC_X64_PETOOLS_PREFIX = /opt/tiano/x86_64-pc-mingw64/x86_64-pc-mingw64/bin/
+DEFINE UNIXGCC_IPF_PETOOLS_PREFIX = /opt/tiano/ia64-pc-elf/ia64-pc-elf/bin/
+#
+# Option 2: Use an environment variable
+#DEFINE UNIXGCC_IA32_PETOOLS_PREFIX = ENV(IA32_PETOOLS_PREFIX)
+#DEFINE UNIXGCC_X64_PETOOLS_PREFIX = ENV(X64_PETOOLS_PREFIX)
+#
+# Option 3: Install the compiler suite into your default paths
+#DEFINE UNIXGCC_IA32_PETOOLS_PREFIX = i386-pc-mingw32-
+#DEFINE UNIXGCC_X64_PETOOLS_PREFIX = x86_64-pc-mingw32-
+#
+# Option 4: Create links under the BaseTools/Bin/gcc/ARCH directory
+# Links needed: gcc, ar & ld
+#DEFINE UNIXGCC_IA32_PETOOLS_PREFIX = ENV(WORKSPACE)/BaseTools/Bin/gcc/Ia32/
+#DEFINE UNIXGCC_X64_PETOOLS_PREFIX = ENV(WORKSPACE)/BaseTools/Bin/gcc/X64/
+#
+# Option 5: Install programs under user's home directory
+#DEFINE UNIXGCC_IA32_PETOOLS_PREFIX = ENV(HOME)/programs/gcc/ia32/bin/i686-pc-mingw32-
+#DEFINE UNIXGCC_X64_PETOOLS_PREFIX = ENV(HOME)/programs/gcc/x64/bin/x86_64-pc-mingw32-
+#
+
+DEFINE CYGWIN_BIN = c:/cygwin/bin
+DEFINE CYGWIN_BINIA32 = c:/cygwin/opt/tiano/i386-tiano-pe/i386-tiano-pe/bin/
+DEFINE CYGWIN_BINX64 = c:/cygwin/opt/tiano/x86_64-pc-mingw64/x86_64-pc-mingw64/bin/
+DEFINE CYGWIN_BINIPF = c:/cygwin/opt/tiano/gcc/ipf/bin/ia64-pc-elf-
+
+DEFINE GCC43_IA32_PREFIX = /usr/bin/
+DEFINE GCC43_X64_PREFIX = /usr/bin/
+
+DEFINE GCC44_IA32_PREFIX = /usr/bin/
+#DEFINE GCC44_IA32_PREFIX = ENV(HOME)/programs/gcc/4.4/ia32/
+DEFINE GCC44_X64_PREFIX = /usr/bin/
+#DEFINE GCC44_X64_PREFIX = ENV(HOME)/programs/gcc/4.4/x64/
+
+DEFINE GCC45_IA32_PREFIX = /usr/bin/
+DEFINE GCC45_X64_PREFIX = /usr/bin/
+
+DEFINE GCC46_IA32_PREFIX = /usr/bin/
+DEFINE GCC46_X64_PREFIX = /usr/bin/
+
+DEFINE GCC47_IA32_PREFIX = /usr/bin/
+DEFINE GCC47_X64_PREFIX = /usr/bin/
+
+DEFINE UNIX_IASL_BIN = /usr/bin/iasl
+#DEFINE UNIX_IASL_BIN = $(HOME)/programs/iasl
+DEFINE WIN_ASL_BIN_DIR = C:\ASL
+DEFINE WIN_IASL_BIN = DEF(WIN_ASL_BIN_DIR)\iasl.exe
+DEFINE WIN_ASL_BIN = DEF(WIN_ASL_BIN_DIR)\asl.exe
+
+DEFINE IASL_FLAGS =
+DEFINE IASL_OUTFLAGS = -p
+DEFINE MS_ASL_OUTFLAGS = /Fo=
+DEFINE MS_ASL_FLAGS =
+
+DEFINE DEFAULT_WIN_ASL_BIN = DEF(WIN_IASL_BIN)
+DEFINE DEFAULT_WIN_ASL_FLAGS = DEF(IASL_FLAGS)
+DEFINE DEFAULT_WIN_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+#DEFINE DEFAULT_WIN_ASL_BIN = DEF(WIN_ASL_BIN)
+#DEFINE DEFAULT_WIN_ASL_FLAGS = DEF(MS_ASL_FLAGS)
+#DEFINE DEFAULT_WIN_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+
+DEFINE MSFT_ASLPP_FLAGS = /nologo /E /C /FIAutoGen.h
+DEFINE MSFT_ASLCC_FLAGS = /nologo /c /FIAutoGen.h /TC /Dmain=ReferenceAcpiTable
+DEFINE MSFT_ASLDLINK_FLAGS = /NODEFAULTLIB /ENTRY:ReferenceAcpiTable /SUBSYSTEM:CONSOLE
+
+DEFINE ICC_WIN_ASLPP_FLAGS = /nologo /E /C /FIAutoGen.h
+DEFINE ICC_WIN_ASLCC_FLAGS = /nologo /c /FIAutoGen.h /TC /Dmain=ReferenceAcpiTable
+DEFINE ICC_WIN_ASLDLINK_FLAGS = /NODEFAULTLIB /ENTRY:ReferenceAcpiTable /SUBSYSTEM:CONSOLE /NODEFAULTLIB:libmmt /NODEFAULTLIB:libirc
+
+DEFINE IPHONE_TOOLS = /Developer/Platforms/iPhoneOS.platform/Developer
+
+DEFINE SOURCERY_CYGWIN_TOOLS = /cygdrive/c/Program Files/CodeSourcery/Sourcery G++ Lite/bin
+
+#
+# Change to the location clang was built
+#
+DEFINE CLANG_BIN = /usr/bin/
+
+####################################################################################
+#
+# format: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE = <string>
+# priority:
+# TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
+# ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
+# TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
+# ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
+# TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
+# ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
+# TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
+# ******_*********_****_COMMANDTYPE_ATTRIBUTE
+# TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
+# ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
+# TARGET_*********_ARCH_***********_ATTRIBUTE
+# ******_*********_ARCH_***********_ATTRIBUTE
+# TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
+# ******_TOOLCHAIN_****_***********_ATTRIBUTE
+# TARGET_*********_****_***********_ATTRIBUTE
+# ******_*********_****_***********_ATTRIBUTE (Lowest)
+#
+####################################################################################
+####################################################################################
+#
+# Supported Tool Chains
+# =====================
+# VS2003 -win32- Requires:
+# Microsoft Visual Studio .NET 2003
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# VS2005 -win32- Requires:
+# Microsoft Visual Studio 2005 Team Suite Edition
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# VS2008 -win32- Requires:
+# Microsoft Visual Studio 2008 Team Suite Edition
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# VS2010 -win32- Requires:
+# Microsoft Visual Studio 2010 Premium Edition
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# DDK3790 -win32- Requires:
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# UNIXGCC -UNIX- Requires:
+# GCC 4.3.0
+# binutils 2.20.51.0.5
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# GCC43 -Linux- Requires:
+# GCC 4.3 (Native)
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# GCC44 -Linux- Requires:
+# GCC 4.4 (Native)
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# GCC45 -Linux- Requires:
+# GCC 4.5 (Native)
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# GCC46 -Linux- Requires:
+# GCC 4.6 (Native)
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# GCC47 -Linux- Requires:
+# GCC 4.7 (Native)
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# ELFGCC -Linux- Requires:
+# GCC(this tool chain uses whatever version of gcc and binutils that is installed in /usr/bin)
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# CYGGCC -win32- Requires:
+# CygWin, GCC 4.3.0, binutils 2.20.51.0.5
+# Microsoft Visual Studio 2005 or 2008
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# ICC -win32- Requires:
+# Intel C Compiler V9.1
+# Dependencies:
+# Microsoft Visual Studio 2003 or 2005
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK)
+# version 3790.1830 for X64 target architectures
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# ICC11 -win32- Requires:
+# Intel C Compiler V11.1
+# Dependencies:
+# Microsoft Visual Studio 2005 or 2008
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK)
+# version 3790.1830 for X64 target architectures
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# MYTOOLS -win32- Requires:
+# Microsoft Visual Studio 2008 for IA32/X64
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830 for IPF
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# VS2003xASL -win32- Requires:
+# Microsoft Visual Studio .NET 2003
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# VS2005xASL -win32- Requires:
+# Microsoft Visual Studio 2005 Team Suite Edition
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# VS2008xASL -win32- Requires:
+# Microsoft Visual Studio 2008 Team Suite
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# VS2010xASL -win32- Requires:
+# Microsoft Visual Studio 2010 Premium Edition
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# DDK3790xASL -win32- Requires:
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# CYGGCCxASL -win32- Requires:
+# CygWin, GCC 4.3.0, binutils 2.20.51.0.5
+# Microsoft Visual Studio 2005 or 2008
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# ICCxASL -win32- Requires:
+# Intel C Compiler V9.1
+# Dependencies:
+# Microsoft Visual Studio 2003 or 2005
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK)
+# version 3790.1830 for X64 target architectures
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# ICC11xASL -win32- Requires:
+# Intel C Compiler V11.1
+# Dependencies:
+# Microsoft Visual Studio 2005 or 2008
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK)
+# version 3790.1830 for X64 target architectures
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# VS2005x86 -win64- Requires:
+# Microsoft Visual Studio 2005 Team Suite Edition (x86)
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# VS2008x86 -win64- Requires:
+# Microsoft Visual Studio 2008 (x86)
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# VS2010x86 -win64- Requires:
+# Microsoft Visual Studio 2010 (x86) Premium Edition
+# Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# ICCx86 -win64- Requires:
+# Intel C Compiler V9.1(x86)
+# Dependencies:
+# Microsoft Visual Studio 2003 or 2005
+# Microsoft Windows Server 2003 Driver Development Kit
+# (Microsoft WINDDK) version 3790.1830 for X64 target architectures
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# ICC11x86 -win64- Requires:
+# Intel C Compiler V11.1(x86)
+# Dependencies:
+# Microsoft Visual Studio 2005 or 2008
+# Microsoft Windows Server 2003 Driver Development Kit
+# (Microsoft WINDDK) version 3790.1830 for X64 target architectures
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# VS2005x86xASL -win64- Requires:
+# Microsoft Visual Studio 2005 Team Suite Edition (x86)
+# Microsoft Windows Server 2003 Driver Development Kit(Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# VS2008x86xASL -win64- Requires:
+# Microsoft Visual Studio 2008 (x86)
+# Microsoft Windows Server 2003 Driver Development Kit(Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# VS2010x86xASL -win64- Requires:
+# Microsoft Visual Studio 2010 (x86) Premium Edition
+# Microsoft Windows Server 2003 Driver Development Kit(Microsoft WINDDK) version 3790.1830
+# Optional:
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# ICCx86xASL -win64- Requires:
+# Intel C Compiler V9.1 (x86)
+# Dependencies:
+# Microsoft Visual Studio 2003 or 2005
+# Microsoft Windows Server 2003 Driver Development Kit
+# (Microsoft WINDDK) version 3790.1830 for X64 target architectures
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# ICC11x86xASL -win64- Requires:
+# Intel C Compiler V11.1 (x86)
+# Dependencies:
+# Microsoft Visual Studio 2005 or 2008
+# Microsoft Windows Server 2003 Driver Development Kit
+# (Microsoft WINDDK) version 3790.1830 for X64 target architectures
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# CYGGCCx86 -win64- Requires:
+# CygWin, GCC 4.3.0, binutils 2.20.51.0.5
+# Microsoft Visual Studio 2005 or 2008
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler (iasl.exe) v20101013 from
+# http://www.acpica.org/downloads/previous_releases.php
+# CYGGCCx86xASL -win64- Requires:
+# CygWin, GCC 4.3.0, binutils 2.20.51.0.5
+# Microsoft Visual Studio 2005 or 2008
+# Optional:
+# Required to build EBC drivers:
+# Intel(r) Compiler for Efi Byte Code (Intel(r) EBC Compiler)
+# Required to build platforms or ACPI tables:
+# Microsoft ASL ACPI Compiler (asl.exe) v4.0.0 from
+# http://download.microsoft.com/download/2/c/1/2c16c7e0-96c1-40f5-81fc-3e4bf7b65496/microsoft_asl_compiler-v4-0-0.msi
+# * Commented out - All versions of VS2005 use the same standard install directory
+#
+####################################################################################
+####################################################################################
+#
+# Supported Tool Chain Family
+# ===========================
+# MSFT - Microsoft
+# GCC - GNU GCC
+# INTEL - INTEL
+# RVCT - ARM RealView Toolchain
+####################################################################################
+####################################################################################
+#
+# Intel EFI Byte Code Compiler (Template)
+#
+####################################################################################
+# *_*_EBC_*_FAMILY = INTEL
+#
+# *_*_EBC_PP_PATH = C:\Program Files\Intel\EBC\Bin\iec.exe
+# *_*_EBC_CC_PATH = C:\Program Files\Intel\EBC\Bin\iec.exe
+# *_*_EBC_SLINK_PATH = C:\Program Files\Intel\EBC\Bin\link.exe
+#
+# *_*_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+# *_*_EBC_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h
+# *_*_EBC_CC_FLAGS = /nologo /FAcs /c /W3 /WX /FI$(DEST_DIR_DEBUG)/AutoGen.h
+# *_*_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /MACHINE:EBC /OPT:REF /NODEFAULTLIB /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /ALIGN:32 /DRIVER
+#
+####################################################################################
+#
+# Intel ACPI Source Language Compiler (Template)
+#
+####################################################################################
+# *_*_*_ASL_FAMILY = INTEL
+#
+# *_*_*_ASL_PATH = C:\ASL\iasl.exe
+#
+####################################################################################
+#
+# Microsoft ACPI Source Language Compiler (Template)
+#
+####################################################################################
+# *_*_*_ASL_FAMILY = MSFT
+#
+# *_*_*_ASL_PATH = C:\ASL\asl.exe
+#
+####################################################################################
+
+
+####################################################################################
+#
+# Microsoft Visual Studio .NET 2003 (IA-32 only, with Link Time Code Generation)
+# And Intel ACPI Compiler
+#
+####################################################################################
+# VS2003 - Microsoft Visual Studio .NET 2003 and Intel ACPI Source Language Compiler (iasl.exe)
+*_VS2003_*_*_FAMILY = MSFT
+
+##################
+# ASL definitions
+##################
+*_VS2003_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_VS2003_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_VS2003_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_VS2003_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2003_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2003_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2003_IA32_*_DLL = DEF(VS2003_DLL)
+
+*_VS2003_IA32_MAKE_PATH = DEF(VS2003_BIN)\nmake.exe
+*_VS2003_IA32_CC_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003_IA32_VFRPP_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003_IA32_SLINK_PATH = DEF(VS2003_BIN)\lib.exe
+*_VS2003_IA32_DLINK_PATH = DEF(VS2003_BIN)\link.exe
+*_VS2003_IA32_APP_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003_IA32_PP_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003_IA32_ASM_PATH = DEF(VS2003_BIN)\ml.exe
+*_VS2003_IA32_ASM16_PATH = DEF(VS2003_BIN)\ml.exe
+*_VS2003_IA32_ASLCC_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003_IA32_ASLPP_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003_IA32_ASLDLINK_PATH = DEF(VS2003_BIN)\link.exe
+*_VS2003_IA32_RC_PATH = DEF(VS2003_BIN)\rc.exe
+
+ *_VS2003_IA32_MAKE_FLAGS = /nologo
+ *_VS2003_IA32_APP_FLAGS = /nologo /E /TC
+ *_VS2003_IA32_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+ *_VS2003_IA32_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+ DEBUG_VS2003_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /GX- /Zi /Gm
+RELEASE_VS2003_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /GX-
+NOOPT_VS2003_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /GX- /Zi /Gm /Od
+
+ DEBUG_VS2003_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+RELEASE_VS2003_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd
+NOOPT_VS2003_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+
+ *_VS2003_IA32_SLINK_FLAGS = /nologo /LTCG
+ DEBUG_VS2003_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2003_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4078 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2003_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2003_EBC_*_FAMILY = INTEL
+
+*_VS2003_EBC_MAKE_PATH = DEF(VS2003_BIN)\nmake.exe
+*_VS2003_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2003_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2003_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2003_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2003_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2003_EBC_RC_PATH = DEF(VS2003_BIN)\rc.exe
+
+*_VS2003_EBC_MAKE_FLAGS = /nologo
+*_VS2003_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2003_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2003_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2003_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2003_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Microsoft Visual Studio .NET 2003 and Microsoft ACPI compiler
+#
+####################################################################################
+# VS2003xASL - Microsoft Visual Studio .NET 2003 and Microsoft ACPI Source Language Compiler (asl.exe)
+*_VS2003xASL_*_*_FAMILY = MSFT
+
+##################
+# ASL definitions
+##################
+*_VS2003xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_VS2003xASL_*_ASL_FLAGS =
+*_VS2003xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_VS2003xASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2003xASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2003xASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2003xASL_IA32_*_DLL = DEF(VS2003_DLL)
+
+*_VS2003xASL_IA32_MAKE_PATH = DEF(VS2003_BIN)\nmake.exe
+*_VS2003xASL_IA32_CC_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003xASL_IA32_VFRPP_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003xASL_IA32_SLINK_PATH = DEF(VS2003_BIN)\lib.exe
+*_VS2003xASL_IA32_DLINK_PATH = DEF(VS2003_BIN)\link.exe
+*_VS2003xASL_IA32_APP_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003xASL_IA32_PP_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003xASL_IA32_ASM_PATH = DEF(VS2003_BIN)\ml.exe
+*_VS2003xASL_IA32_ASLCC_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003xASL_IA32_ASLPP_PATH = DEF(VS2003_BIN)\cl.exe
+*_VS2003xASL_IA32_ASLDLINK_PATH = DEF(VS2003_BIN)\link.exe
+*_VS2003xASL_IA32_RC_PATH = DEF(VS2003_BIN)\rc.exe
+
+
+ *_VS2003xASL_IA32_MAKE_FLAGS = /nologo
+ *_VS2003xASL_IA32_APP_FLAGS = /nologo /E /TC
+ *_VS2003xASL_IA32_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+ *_VS2003xASL_IA32_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+ DEBUG_VS2003xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /GX- /Zi /Gm
+RELEASE_VS2003xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /GX-
+NOOPT_VS2003xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /GX- /Zi /Gm /Od
+
+ DEBUG_VS2003xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+RELEASE_VS2003xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd
+NOOPT_VS2003xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+
+ *_VS2003xASL_IA32_SLINK_FLAGS = /nologo /LTCG
+ DEBUG_VS2003xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2003xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4078 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2003xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2003xASL_EBC_*_FAMILY = INTEL
+
+*_VS2003xASL_EBC_MAKE_PATH = DEF(VS2003_BIN)\nmake.exe
+*_VS2003xASL_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2003xASL_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2003xASL_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2003xASL_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2003xASL_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2003xASL_EBC_RC_PATH = DEF(VS2003_BIN)\rc.exe
+
+*_VS2003xASL_EBC_MAKE_FLAGS = /nologo
+*_VS2003xASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2003xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2003xASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2003xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2003xASL_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Microsoft Visual Studio 2005
+#
+# VS2005 - Microsoft Visual Studio 2005 All Edition, including Standard, Professional, Express, TeamSuite
+# ASL - Intel ACPI Source Language Compiler
+####################################################################################
+# VS2005 - Microsoft Visual Studio 2005 ALL Edition, including Standard, Professional, Express, TeamSuite
+*_VS2005_*_*_FAMILY = MSFT
+
+*_VS2005_*_MAKE_PATH = DEF(VS2005_BIN)\nmake.exe
+*_VS2005_*_MAKE_FLAGS = /nologo
+*_VS2005_*_RC_PATH = DEF(VS2005_BIN)\rc.exe
+
+*_VS2005_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2005_*_APP_FLAGS = /nologo /E /TC
+*_VS2005_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2005_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2005_*_ASM16_PATH = DEF(VS2005_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2005_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_VS2005_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_VS2005_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_VS2005_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2005_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2005_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2005_IA32_*_DLL = DEF(VS2005_DLL)
+
+*_VS2005_IA32_MAKE_PATH = DEF(VS2005_BIN)\nmake.exe
+*_VS2005_IA32_CC_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005_IA32_VFRPP_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005_IA32_SLINK_PATH = DEF(VS2005_BIN)\lib.exe
+*_VS2005_IA32_DLINK_PATH = DEF(VS2005_BIN)\link.exe
+*_VS2005_IA32_APP_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005_IA32_PP_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005_IA32_ASM_PATH = DEF(VS2005_BIN)\ml.exe
+*_VS2005_IA32_ASLCC_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005_IA32_ASLPP_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005_IA32_ASLDLINK_PATH = DEF(VS2005_BIN)\link.exe
+
+ *_VS2005_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2005_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2005_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2005_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2005_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2005_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2005_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2005_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2005_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2005_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2005_X64_*_DLL = DEF(VS2005_DLL)
+
+*_VS2005_X64_CC_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005_X64_PP_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005_X64_APP_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005_X64_VFRPP_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005_X64_ASM_PATH = DEF(VS2005_BINX64)\ml64.exe
+*_VS2005_X64_SLINK_PATH = DEF(VS2005_BINX64)\lib.exe
+*_VS2005_X64_DLINK_PATH = DEF(VS2005_BINX64)\link.exe
+*_VS2005_X64_ASLCC_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005_X64_ASLPP_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005_X64_ASLDLINK_PATH = DEF(VS2005_BINX64)\link.exe
+
+
+ DEBUG_VS2005_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2005_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2005_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2005_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2005_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2005_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2005_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2005_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2005_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2005_IPF_*_DLL = DEF(VS2005_DLL)
+
+*_VS2005_IPF_PP_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005_IPF_APP_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005_IPF_VFRPP_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005_IPF_CC_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005_IPF_ASM_PATH = DEF(VS2005_BIN64)\ias.exe
+*_VS2005_IPF_SLINK_PATH = DEF(VS2005_BIN64)\lib.exe
+*_VS2005_IPF_DLINK_PATH = DEF(VS2005_BIN64)\link.exe
+*_VS2005_IPF_ASLCC_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005_IPF_ASLPP_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005_IPF_ASLDLINK_PATH = DEF(VS2005_BIN64)\link.exe
+
+ DEBUG_VS2005_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2005_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2005_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2005_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2005_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2005_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2005_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2005_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2005_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2005_EBC_*_FAMILY = INTEL
+
+*_VS2005_EBC_MAKE_PATH = DEF(VS2005_BIN)\nmake.exe
+*_VS2005_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2005_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2005_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2005_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2005_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_VS2005_EBC_MAKE_FLAGS = /nologo
+*_VS2005_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2005_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2005_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2005_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2005_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Microsoft Visual Studio 2005
+#
+# VS2005 - Microsoft Visual Studio 2005 All Edition, including Standard, Professional, Express, TeamSuite
+# ASL - Microsoft ACPI Source Language Compiler (asl.exe)
+####################################################################################
+# VS2005xASL - Microsoft Visual Studio 2005 ALL Edition, including Standard, Professional, Express, TeamSuite
+*_VS2005xASL_*_*_FAMILY = MSFT
+
+*_VS2005xASL_*_MAKE_PATH = DEF(VS2005_BIN)\nmake.exe
+*_VS2005xASL_*_MAKE_FLAG = /nologo
+*_VS2005xASL_*_RC_PATH = DEF(VS2005_BIN)\rc.exe
+
+*_VS2005xASL_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2005xASL_*_APP_FLAGS = /nologo /E /TC
+*_VS2005xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2005xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2005xASL_*_ASM16_PATH = DEF(VS2005_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2005xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_VS2005xASL_*_ASL_FLAGS =
+*_VS2005xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_VS2005xASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2005xASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2005xASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2005xASL_IA32_*_DLL = DEF(VS2005_DLL)
+
+*_VS2005xASL_IA32_MAKE_PATH = DEF(VS2005_BIN)\nmake.exe
+*_VS2005xASL_IA32_CC_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005xASL_IA32_VFRPP_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005xASL_IA32_SLINK_PATH = DEF(VS2005_BIN)\lib.exe
+*_VS2005xASL_IA32_DLINK_PATH = DEF(VS2005_BIN)\link.exe
+*_VS2005xASL_IA32_APP_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005xASL_IA32_PP_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005xASL_IA32_ASM_PATH = DEF(VS2005_BIN)\ml.exe
+*_VS2005xASL_IA32_ASLCC_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005xASL_IA32_ASLPP_PATH = DEF(VS2005_BIN)\cl.exe
+*_VS2005xASL_IA32_ASLDLINK_PATH = DEF(VS2005_BIN)\link.exe
+
+ *_VS2005xASL_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2005xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2005xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2005xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2005xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2005xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2005xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2005xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2005xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2005xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2005xASL_X64_*_DLL = DEF(VS2005_DLL)
+
+*_VS2005xASL_X64_CC_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005xASL_X64_PP_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005xASL_X64_APP_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005xASL_X64_VFRPP_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005xASL_X64_ASM_PATH = DEF(VS2005_BINX64)\ml64.exe
+*_VS2005xASL_X64_SLINK_PATH = DEF(VS2005_BINX64)\lib.exe
+*_VS2005xASL_X64_DLINK_PATH = DEF(VS2005_BINX64)\link.exe
+*_VS2005xASL_X64_ASLCC_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005xASL_X64_ASLPP_PATH = DEF(VS2005_BINX64)\cl.exe
+*_VS2005xASL_X64_ASLDLINK_PATH = DEF(VS2005_BINX64)\link.exe
+
+
+ DEBUG_VS2005xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2005xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2005xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2005xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2005xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2005xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2005xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2005xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2005xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2005xASL_IPF_*_DLL = DEF(VS2005_DLL)
+
+*_VS2005xASL_IPF_PP_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005xASL_IPF_APP_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005xASL_IPF_VFRPP_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005xASL_IPF_CC_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005xASL_IPF_ASM_PATH = DEF(VS2005_BIN64)\ias.exe
+*_VS2005xASL_IPF_SLINK_PATH = DEF(VS2005_BIN64)\lib.exe
+*_VS2005xASL_IPF_DLINK_PATH = DEF(VS2005_BIN64)\link.exe
+*_VS2005xASL_IPF_ASLCC_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005xASL_IPF_ASLPP_PATH = DEF(VS2005_BIN64)\cl.exe
+*_VS2005xASL_IPF_ASLDLINK_PATH = DEF(VS2005_BIN64)\link.exe
+
+ DEBUG_VS2005xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2005xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2005xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2005xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2005xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2005xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2005xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2005xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2005xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2005xASL_EBC_*_FAMILY = INTEL
+
+*_VS2005xASL_EBC_MAKE_PATH = DEF(VS2005_BIN)\nmake.exe
+*_VS2005xASL_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2005xASL_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2005xASL_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2005xASL_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2005xASL_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_VS2005xASL_EBC_MAKE_FLAGS = /nologo
+*_VS2005xASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2005xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2005xASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2005xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2005xASL_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Microsoft Visual Studio 2005 (x86)
+#
+# VS2005 - Microsoft Visual Studio 2005 All Edition, including Standard, Professional, Express, TeamSuite
+# ASL - Intel ACPI Source Language Compiler
+####################################################################################
+# VS2005x86 - Microsoft Visual Studio 2005 ALL Edition, including Standard, Professional, Express, TeamSuite
+*_VS2005x86_*_*_FAMILY = MSFT
+
+*_VS2005x86_*_MAKE_PATH = DEF(VS2005x86_BIN)\nmake.exe
+*_VS2005x86_*_MAKE_FLAGS = /nologo
+*_VS2005x86_*_RC_PATH = DEF(VS2005x86_BIN)\rc.exe
+
+*_VS2005x86_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2005x86_*_APP_FLAGS = /nologo /E /TC
+*_VS2005x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2005x86_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2005x86_*_ASM16_PATH = DEF(VS2005x86_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2005x86_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_VS2005x86_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_VS2005x86_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_VS2005x86_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2005x86_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2005x86_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2005x86_IA32_*_DLL = DEF(VS2005x86_DLL)
+
+*_VS2005x86_IA32_MAKE_PATH = DEF(VS2005x86_BIN)\nmake.exe
+*_VS2005x86_IA32_CC_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86_IA32_VFRPP_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86_IA32_SLINK_PATH = DEF(VS2005x86_BIN)\lib.exe
+*_VS2005x86_IA32_DLINK_PATH = DEF(VS2005x86_BIN)\link.exe
+*_VS2005x86_IA32_APP_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86_IA32_PP_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86_IA32_ASM_PATH = DEF(VS2005x86_BIN)\ml.exe
+*_VS2005x86_IA32_ASLCC_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86_IA32_ASLPP_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86_IA32_ASLDLINK_PATH = DEF(VS2005x86_BIN)\link.exe
+
+ *_VS2005x86_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2005x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2005x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2005x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2005x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2005x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2005x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2005x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2005x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2005x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2005x86_X64_*_DLL = DEF(VS2005x86_DLL)
+
+*_VS2005x86_X64_CC_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86_X64_PP_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86_X64_APP_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86_X64_VFRPP_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86_X64_ASM_PATH = DEF(VS2005x86_BINX64)\ml64.exe
+*_VS2005x86_X64_SLINK_PATH = DEF(VS2005x86_BINX64)\lib.exe
+*_VS2005x86_X64_DLINK_PATH = DEF(VS2005x86_BINX64)\link.exe
+*_VS2005x86_X64_ASLCC_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86_X64_ASLPP_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86_X64_ASLDLINK_PATH = DEF(VS2005x86_BINX64)\link.exe
+
+
+ DEBUG_VS2005x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2005x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2005x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2005x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2005x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2005x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2005x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2005x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2005x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2005x86_IPF_*_DLL = DEF(VS2005x86_DLL)
+
+*_VS2005x86_IPF_PP_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86_IPF_APP_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86_IPF_VFRPP_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86_IPF_CC_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86_IPF_ASM_PATH = DEF(VS2005x86_BIN64)\ias.exe
+*_VS2005x86_IPF_SLINK_PATH = DEF(VS2005x86_BIN64)\lib.exe
+*_VS2005x86_IPF_DLINK_PATH = DEF(VS2005x86_BIN64)\link.exe
+*_VS2005x86_IPF_ASLCC_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86_IPF_ASLPP_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86_IPF_ASLDLINK_PATH = DEF(VS2005x86_BIN64)\link.exe
+
+ DEBUG_VS2005x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2005x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2005x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2005x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2005x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2005x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2005x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2005x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2005x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2005x86_EBC_*_FAMILY = INTEL
+
+*_VS2005x86_EBC_MAKE_PATH = DEF(VS2005x86_BIN)\nmake.exe
+*_VS2005x86_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
+*_VS2005x86_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
+*_VS2005x86_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
+*_VS2005x86_EBC_SLINK_PATH = DEF(EBC_BINx86)\link.exe
+*_VS2005x86_EBC_DLINK_PATH = DEF(EBC_BINx86)\link.exe
+
+*_VS2005x86_EBC_MAKE_FLAGS = /nologo
+*_VS2005x86_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2005x86_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2005x86_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2005x86_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2005x86_EBC_DLINK_FLAGS = "C:\Program Files (x86)\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Microsoft Visual Studio 2005 (x86)
+#
+# VS2005 - Microsoft Visual Studio 2005 All Edition, including Standard, Professional, Express, TeamSuite
+# ASL - Microsoft ACPI Source Language Compiler
+####################################################################################
+# VS2005x86xASL - Microsoft Visual Studio 2005 ALL Edition, including Standard, Professional, Express, TeamSuite
+*_VS2005x86xASL_*_*_FAMILY = MSFT
+
+*_VS2005x86xASL_*_MAKE_PATH = DEF(VS2005x86_BIN)\nmake.exe
+*_VS2005x86xASL_*_MAKE_FLAGS = /nologo
+*_VS2005x86xASL_*_RC_PATH = DEF(VS2005x86_BIN)\rc.exe
+
+*_VS2005x86xASL_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2005x86xASL_*_APP_FLAGS = /nologo /E /TC
+*_VS2005x86xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2005x86xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2005x86xASL_*_ASM16_PATH = DEF(VS2005x86_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2005x86xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_VS2005x86xASL_*_ASL_FLAGS =
+*_VS2005x86xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_VS2005x86xASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2005x86xASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2005x86xASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2005x86xASL_IA32_*_DLL = DEF(VS2005x86_DLL)
+
+*_VS2005x86xASL_IA32_MAKE_PATH = DEF(VS2005x86_BIN)\nmake.exe
+*_VS2005x86xASL_IA32_CC_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86xASL_IA32_VFRPP_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86xASL_IA32_SLINK_PATH = DEF(VS2005x86_BIN)\lib.exe
+*_VS2005x86xASL_IA32_DLINK_PATH = DEF(VS2005x86_BIN)\link.exe
+*_VS2005x86xASL_IA32_APP_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86xASL_IA32_PP_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86xASL_IA32_ASM_PATH = DEF(VS2005x86_BIN)\ml.exe
+*_VS2005x86xASL_IA32_ASLCC_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86xASL_IA32_ASLPP_PATH = DEF(VS2005x86_BIN)\cl.exe
+*_VS2005x86xASL_IA32_ASLDLINK_PATH = DEF(VS2005x86_BIN)\link.exe
+
+ *_VS2005x86xASL_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2005x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2005x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2005x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2005x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2005x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2005x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2005x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2005x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2005x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2005x86xASL_X64_*_DLL = DEF(VS2005x86_DLL)
+
+*_VS2005x86xASL_X64_CC_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86xASL_X64_PP_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86xASL_X64_APP_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86xASL_X64_VFRPP_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86xASL_X64_ASM_PATH = DEF(VS2005x86_BINX64)\ml64.exe
+*_VS2005x86xASL_X64_SLINK_PATH = DEF(VS2005x86_BINX64)\lib.exe
+*_VS2005x86xASL_X64_DLINK_PATH = DEF(VS2005x86_BINX64)\link.exe
+*_VS2005x86xASL_X64_ASLCC_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86xASL_X64_ASLPP_PATH = DEF(VS2005x86_BINX64)\cl.exe
+*_VS2005x86xASL_X64_ASLDLINK_PATH = DEF(VS2005x86_BINX64)\link.exe
+
+
+ DEBUG_VS2005x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2005x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2005x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2005x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2005x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2005x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2005x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2005x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2005x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2005x86xASL_IPF_*_DLL = DEF(VS2005x86_DLL)
+
+*_VS2005x86xASL_IPF_PP_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86xASL_IPF_APP_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86xASL_IPF_VFRPP_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86xASL_IPF_CC_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86xASL_IPF_ASM_PATH = DEF(VS2005x86_BIN64)\ias.exe
+*_VS2005x86xASL_IPF_SLINK_PATH = DEF(VS2005x86_BIN64)\lib.exe
+*_VS2005x86xASL_IPF_DLINK_PATH = DEF(VS2005x86_BIN64)\link.exe
+*_VS2005x86xASL_IPF_ASLCC_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86xASL_IPF_ASLPP_PATH = DEF(VS2005x86_BIN64)\cl.exe
+*_VS2005x86xASL_IPF_ASLDLINK_PATH = DEF(VS2005x86_BIN64)\link.exe
+
+ DEBUG_VS2005x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2005x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2005x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2005x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2005x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2005x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2005x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2005x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2005x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2005x86xASL_EBC_*_FAMILY = INTEL
+
+*_VS2005x86xASL_EBC_MAKE_PATH = DEF(VS2005x86_BIN)\nmake.exe
+*_VS2005x86xASL_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
+*_VS2005x86xASL_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
+*_VS2005x86xASL_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
+*_VS2005x86xASL_EBC_SLINK_PATH = DEF(EBC_BINx86)\link.exe
+*_VS2005x86xASL_EBC_DLINK_PATH = DEF(EBC_BINx86)\link.exe
+
+*_VS2005x86xASL_EBC_MAKE_FLAGS = /nologo
+*_VS2005x86xASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2005x86xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2005x86xASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2005x86xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2005x86xASL_EBC_DLINK_FLAGS = "C:\Program Files (x86)\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+
+####################################################################################
+#
+# Microsoft Visual Studio 2008
+#
+# VS2008 - Microsoft Visual Studio 2005 All Edition, including Standard, Professional, Express, TeamSuite
+# ASL - Intel ACPI Source Language Compiler
+####################################################################################
+# VS2008 - Microsoft Visual Studio 2008 ALL Edition, including Standard, Professional, Express, TeamSuite
+*_VS2008_*_*_FAMILY = MSFT
+
+*_VS2008_*_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
+*_VS2008_*_MAKE_FLAGS = /nologo
+*_VS2008_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+*_VS2008_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2008_*_APP_FLAGS = /nologo /E /TC
+*_VS2008_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2008_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2008_*_ASM16_PATH = DEF(VS2008_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2008_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_VS2008_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_VS2008_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_VS2008_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2008_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2008_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2008_IA32_*_DLL = DEF(VS2008_DLL)
+
+*_VS2008_IA32_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
+*_VS2008_IA32_CC_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008_IA32_VFRPP_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008_IA32_SLINK_PATH = DEF(VS2008_BIN)\lib.exe
+*_VS2008_IA32_DLINK_PATH = DEF(VS2008_BIN)\link.exe
+*_VS2008_IA32_APP_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008_IA32_PP_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008_IA32_ASM_PATH = DEF(VS2008_BIN)\ml.exe
+*_VS2008_IA32_ASLCC_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008_IA32_ASLPP_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008_IA32_ASLDLINK_PATH = DEF(VS2008_BIN)\link.exe
+
+ *_VS2008_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2008_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2008_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2008_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2008_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2008_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2008_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2008_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2008_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2008_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2008_X64_*_DLL = DEF(VS2008_DLL)
+
+*_VS2008_X64_CC_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008_X64_PP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008_X64_APP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008_X64_VFRPP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008_X64_ASM_PATH = DEF(VS2008_BINX64)\ml64.exe
+*_VS2008_X64_SLINK_PATH = DEF(VS2008_BINX64)\lib.exe
+*_VS2008_X64_DLINK_PATH = DEF(VS2008_BINX64)\link.exe
+*_VS2008_X64_ASLCC_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008_X64_ASLPP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008_X64_ASLDLINK_PATH = DEF(VS2008_BINX64)\link.exe
+
+
+ DEBUG_VS2008_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2008_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2008_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2008_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2008_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2008_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2008_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2008_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2008_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2008_IPF_*_DLL = DEF(VS2008_DLL)
+
+*_VS2008_IPF_PP_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008_IPF_APP_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008_IPF_VFRPP_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008_IPF_CC_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008_IPF_ASM_PATH = DEF(VS2008_BIN64)\ias.exe
+*_VS2008_IPF_SLINK_PATH = DEF(VS2008_BIN64)\lib.exe
+*_VS2008_IPF_DLINK_PATH = DEF(VS2008_BIN64)\link.exe
+*_VS2008_IPF_ASLCC_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008_IPF_ASLPP_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008_IPF_ASLDLINK_PATH = DEF(VS2008_BIN64)\link.exe
+
+ DEBUG_VS2008_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2008_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2008_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2008_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2008_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2008_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2008_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2008_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2008_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2008_EBC_*_FAMILY = INTEL
+
+*_VS2008_EBC_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
+*_VS2008_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2008_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2008_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2008_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2008_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_VS2008_EBC_MAKE_FLAGS = /nologo
+*_VS2008_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2008_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2008_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2008_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2008_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Microsoft Visual Studio 2008
+#
+# VS2008 - Microsoft Visual Studio 2008 All Edition, including Standard, Professional, Express, TeamSuite
+# ASL - Microsoft ACPI Source Language Compiler (asl.exe)
+####################################################################################
+# VS2008xASL - Microsoft Visual Studio 2008 ALL Edition, including Standard, Professional, Express, TeamSuite
+*_VS2008xASL_*_*_FAMILY = MSFT
+
+*_VS2008xASL_*_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
+*_VS2008xASL_*_MAKE_FLAG = /nologo
+*_VS2008xASL_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+*_VS2008xASL_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2008xASL_*_APP_FLAGS = /nologo /E /TC
+*_VS2008xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2008xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2008xASL_*_ASM16_PATH = DEF(VS2008_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2008xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_VS2008xASL_*_ASL_FLAGS =
+*_VS2008xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_VS2008xASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2008xASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2008xASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2008xASL_IA32_*_DLL = DEF(VS2008_DLL)
+
+*_VS2008xASL_IA32_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
+*_VS2008xASL_IA32_CC_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008xASL_IA32_VFRPP_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008xASL_IA32_SLINK_PATH = DEF(VS2008_BIN)\lib.exe
+*_VS2008xASL_IA32_DLINK_PATH = DEF(VS2008_BIN)\link.exe
+*_VS2008xASL_IA32_APP_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008xASL_IA32_PP_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008xASL_IA32_ASM_PATH = DEF(VS2008_BIN)\ml.exe
+*_VS2008xASL_IA32_ASLCC_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008xASL_IA32_ASLPP_PATH = DEF(VS2008_BIN)\cl.exe
+*_VS2008xASL_IA32_ASLDLINK_PATH = DEF(VS2008_BIN)\link.exe
+
+ *_VS2008xASL_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2008xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2008xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2008xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2008xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2008xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2008xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2008xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2008xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2008xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2008xASL_X64_*_DLL = DEF(VS2008_DLL)
+
+*_VS2008xASL_X64_CC_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008xASL_X64_PP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008xASL_X64_APP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008xASL_X64_VFRPP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008xASL_X64_ASM_PATH = DEF(VS2008_BINX64)\ml64.exe
+*_VS2008xASL_X64_SLINK_PATH = DEF(VS2008_BINX64)\lib.exe
+*_VS2008xASL_X64_DLINK_PATH = DEF(VS2008_BINX64)\link.exe
+*_VS2008xASL_X64_ASLCC_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008xASL_X64_ASLPP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_VS2008xASL_X64_ASLDLINK_PATH = DEF(VS2008_BINX64)\link.exe
+
+
+ DEBUG_VS2008xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2008xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2008xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2008xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2008xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2008xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2008xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2008xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2008xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2008xASL_IPF_*_DLL = DEF(VS2008_DLL)
+
+*_VS2008xASL_IPF_PP_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008xASL_IPF_APP_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008xASL_IPF_VFRPP_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008xASL_IPF_CC_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008xASL_IPF_ASM_PATH = DEF(VS2008_BIN64)\ias.exe
+*_VS2008xASL_IPF_SLINK_PATH = DEF(VS2008_BIN64)\lib.exe
+*_VS2008xASL_IPF_DLINK_PATH = DEF(VS2008_BIN64)\link.exe
+*_VS2008xASL_IPF_ASLCC_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008xASL_IPF_ASLPP_PATH = DEF(VS2008_BIN64)\cl.exe
+*_VS2008xASL_IPF_ASLDLINK_PATH = DEF(VS2008_BIN64)\link.exe
+
+ DEBUG_VS2008xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2008xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2008xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2008xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2008xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2008xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2008xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2008xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2008xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2008xASL_EBC_*_FAMILY = INTEL
+
+*_VS2008xASL_EBC_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
+*_VS2008xASL_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2008xASL_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2008xASL_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2008xASL_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2008xASL_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_VS2008xASL_EBC_MAKE_FLAGS = /nologo
+*_VS2008xASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2008xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2008xASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2008xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2008xASL_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+# VS2008x86 - Microsoft Visual Studio 2008 (x86) with Intel ASL
+# ASL - Intel ACPI Source Language Compiler (iasl.exe)
+####################################################################################
+# VS2008x86 - Microsoft Visual Studio 2008 (x86) ALL Edition with Intel ASL
+*_VS2008x86_*_*_FAMILY = MSFT
+
+*_VS2008x86_*_MAKE_PATH = DEF(VS2008x86_BIN)\nmake.exe
+*_VS2008x86_*_MAKE_FLAG = /nologo
+*_VS2008x86_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+*_VS2008x86_*_MAKE_FLAGS = /nologo
+*_VS2008x86_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2008x86_*_APP_FLAGS = /nologo /E /TC
+*_VS2008x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2008x86_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2008x86_*_ASM16_PATH = DEF(VS2008x86_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2008x86_*_ASL_PATH = DEF(WIN_IASL_BIN)
+*_VS2008x86_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_VS2008x86_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_VS2008x86_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2008x86_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2008x86_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2008x86_IA32_*_DLL = DEF(VS2008x86_DLL)
+
+*_VS2008x86_IA32_MAKE_PATH = DEF(VS2008x86_BIN)\nmake.exe
+*_VS2008x86_IA32_CC_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86_IA32_VFRPP_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86_IA32_ASLCC_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86_IA32_ASLPP_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86_IA32_SLINK_PATH = DEF(VS2008x86_BIN)\lib.exe
+*_VS2008x86_IA32_DLINK_PATH = DEF(VS2008x86_BIN)\link.exe
+*_VS2008x86_IA32_ASLDLINK_PATH= DEF(VS2008x86_BIN)\link.exe
+*_VS2008x86_IA32_APP_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86_IA32_PP_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86_IA32_ASM_PATH = DEF(VS2008x86_BIN)\ml.exe
+
+ *_VS2008x86_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2008x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2008x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2008x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2008x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2008x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2008x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2008x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2008x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2008x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2008x86_X64_*_DLL = DEF(VS2008x86_DLL)
+
+*_VS2008x86_X64_CC_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86_X64_PP_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86_X64_APP_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86_X64_VFRPP_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86_X64_ASLCC_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86_X64_ASLPP_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86_X64_ASM_PATH = DEF(VS2008x86_BINX64)\ml64.exe
+*_VS2008x86_X64_SLINK_PATH = DEF(VS2008x86_BINX64)\lib.exe
+*_VS2008x86_X64_DLINK_PATH = DEF(VS2008x86_BINX64)\link.exe
+*_VS2008x86_X64_ASLDLINK_PATH = DEF(VS2008x86_BINX64)\link.exe
+
+ DEBUG_VS2008x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2008x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2008x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2008x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2008x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2008x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2008x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2008x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2008x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2008x86_IPF_*_DLL = DEF(VS2008x86_DLL)
+
+*_VS2008x86_IPF_PP_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86_IPF_APP_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86_IPF_VFRPP_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86_IPF_ASLCC_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86_IPF_ASLPP_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86_IPF_CC_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86_IPF_ASM_PATH = DEF(VS2008x86_BIN64)\ias.exe
+*_VS2008x86_IPF_SLINK_PATH = DEF(VS2008x86_BIN64)\lib.exe
+*_VS2008x86_IPF_DLINK_PATH = DEF(VS2008x86_BIN64)\link.exe
+*_VS2008x86_IPF_ASLDLINK_PATH = DEF(VS2008x86_BIN64)\link.exe
+
+ DEBUG_VS2008x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2008x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2008x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2008x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2008x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2008x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2008x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2008x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2008x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+
+####################################################################################
+# VS2008x86xASL - Microsoft Visual Studio 2008 with Microsoft ASL
+# ASL - Microsoft ACPI Source Language Compiler (asl.exe)
+####################################################################################
+*_VS2008x86xASL_*_*_FAMILY = MSFT
+
+*_VS2008x86xASL_*_MAKE_PATH = DEF(VS2008x86_BIN)\nmake.exe
+*_VS2008x86xASL_*_MAKE_FLAG = /nologo
+*_VS2008x86xASL_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+*_VS2008x86xASL_*_MAKE_FLAGS = /nologo
+*_VS2008x86xASL_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2008x86xASL_*_APP_FLAGS = /nologo /E /TC
+*_VS2008x86xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2008x86xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2008x86xASL_*_ASM16_PATH = DEF(VS2008x86_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2008x86xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_VS2008x86xASL_*_ASL_FLAGS = DEF(MS_ASL_FLAGS)
+*_VS2008x86xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_VS2008x86xASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2008x86xASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2008x86xASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2008x86xASL_IA32_*_DLL = DEF(VS2008x86_DLL)
+
+*_VS2008x86xASL_IA32_MAKE_PATH = DEF(VS2008x86_BIN)\nmake.exe
+*_VS2008x86xASL_IA32_CC_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86xASL_IA32_VFRPP_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86xASL_IA32_ASLCC_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86xASL_IA32_ASLPP_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86xASL_IA32_SLINK_PATH = DEF(VS2008x86_BIN)\lib.exe
+*_VS2008x86xASL_IA32_DLINK_PATH = DEF(VS2008x86_BIN)\link.exe
+*_VS2008x86xASL_IA32_ASLDLINK_PATH= DEF(VS2008x86_BIN)\link.exe
+*_VS2008x86xASL_IA32_APP_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86xASL_IA32_PP_PATH = DEF(VS2008x86_BIN)\cl.exe
+*_VS2008x86xASL_IA32_ASM_PATH = DEF(VS2008x86_BIN)\ml.exe
+
+ *_VS2008x86xASL_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2008x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2008x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2008x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2008x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2008x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2008x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2008x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2008x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2008x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2008x86xASL_X64_*_DLL = DEF(VS2008x86_DLL)
+
+*_VS2008x86xASL_X64_CC_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86xASL_X64_PP_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86xASL_X64_APP_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86xASL_X64_VFRPP_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86xASL_X64_ASLCC_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86xASL_X64_ASLPP_PATH = DEF(VS2008x86_BINX64)\cl.exe
+*_VS2008x86xASL_X64_ASM_PATH = DEF(VS2008x86_BINX64)\ml64.exe
+*_VS2008x86xASL_X64_SLINK_PATH = DEF(VS2008x86_BINX64)\lib.exe
+*_VS2008x86xASL_X64_DLINK_PATH = DEF(VS2008x86_BINX64)\link.exe
+*_VS2008x86xASL_X64_ASLDLINK_PATH = DEF(VS2008x86_BINX64)\link.exe
+
+ DEBUG_VS2008x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2008x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2008x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2008x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2008x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2008x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2008x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2008x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2008x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2008x86xASL_IPF_*_DLL = DEF(VS2008x86_DLL)
+
+*_VS2008x86xASL_IPF_PP_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86xASL_IPF_APP_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86xASL_IPF_VFRPP_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86xASL_IPF_ASLCC_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86xASL_IPF_ASLPP_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86xASL_IPF_CC_PATH = DEF(VS2008x86_BIN64)\cl.exe
+*_VS2008x86xASL_IPF_ASM_PATH = DEF(VS2008x86_BIN64)\ias.exe
+*_VS2008x86xASL_IPF_SLINK_PATH = DEF(VS2008x86_BIN64)\lib.exe
+*_VS2008x86xASL_IPF_DLINK_PATH = DEF(VS2008x86_BIN64)\link.exe
+*_VS2008x86xASL_IPF_ASLDLINK_PATH = DEF(VS2008x86_BIN64)\link.exe
+
+ DEBUG_VS2008x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2008x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2008x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2008x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2008x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2008x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2008x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2008x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2008x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+
+####################################################################################
+#
+# Microsoft Visual Studio 2010
+#
+# VS2010 - Microsoft Visual Studio 2010 Premium Edition
+# ASL - Intel ACPI Source Language Compiler
+####################################################################################
+# VS2010 - Microsoft Visual Studio 2010 Premium Edition
+*_VS2010_*_*_FAMILY = MSFT
+
+*_VS2010_*_MAKE_PATH = DEF(VS2010_BIN)\nmake.exe
+*_VS2010_*_MAKE_FLAGS = /nologo
+*_VS2010_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+*_VS2010_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2010_*_APP_FLAGS = /nologo /E /TC
+*_VS2010_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2010_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2010_*_ASM16_PATH = DEF(VS2010_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2010_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_VS2010_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_VS2010_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_VS2010_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2010_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2010_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2010_IA32_*_DLL = DEF(VS2010_DLL)
+
+*_VS2010_IA32_MAKE_PATH = DEF(VS2010_BIN)\nmake.exe
+*_VS2010_IA32_CC_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010_IA32_VFRPP_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010_IA32_SLINK_PATH = DEF(VS2010_BIN)\lib.exe
+*_VS2010_IA32_DLINK_PATH = DEF(VS2010_BIN)\link.exe
+*_VS2010_IA32_APP_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010_IA32_PP_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010_IA32_ASM_PATH = DEF(VS2010_BIN)\ml.exe
+*_VS2010_IA32_ASLCC_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010_IA32_ASLPP_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010_IA32_ASLDLINK_PATH = DEF(VS2010_BIN)\link.exe
+
+ *_VS2010_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2010_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2010_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2010_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2010_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2010_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2010_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2010_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2010_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2010_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2010_X64_*_DLL = DEF(VS2010_DLL)
+
+*_VS2010_X64_CC_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010_X64_PP_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010_X64_APP_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010_X64_VFRPP_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010_X64_ASM_PATH = DEF(VS2010_BINX64)\ml64.exe
+*_VS2010_X64_SLINK_PATH = DEF(VS2010_BINX64)\lib.exe
+*_VS2010_X64_DLINK_PATH = DEF(VS2010_BINX64)\link.exe
+*_VS2010_X64_ASLCC_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010_X64_ASLPP_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010_X64_ASLDLINK_PATH = DEF(VS2010_BINX64)\link.exe
+
+
+ DEBUG_VS2010_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2010_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2010_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2010_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2010_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2010_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2010_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2010_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2010_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2010_IPF_*_DLL = DEF(VS2010_DLL)
+
+*_VS2010_IPF_PP_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010_IPF_APP_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010_IPF_VFRPP_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010_IPF_CC_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010_IPF_ASM_PATH = DEF(VS2010_BIN64)\ias.exe
+*_VS2010_IPF_SLINK_PATH = DEF(VS2010_BIN64)\lib.exe
+*_VS2010_IPF_DLINK_PATH = DEF(VS2010_BIN64)\link.exe
+*_VS2010_IPF_ASLCC_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010_IPF_ASLPP_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010_IPF_ASLDLINK_PATH = DEF(VS2010_BIN64)\link.exe
+
+ DEBUG_VS2010_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2010_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2010_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2010_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2010_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2010_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2010_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2010_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2010_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2010_EBC_*_FAMILY = INTEL
+
+*_VS2010_EBC_MAKE_PATH = DEF(VS2010_BIN)\nmake.exe
+*_VS2010_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2010_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2010_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2010_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2010_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_VS2010_EBC_MAKE_FLAGS = /nologo
+*_VS2010_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2010_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2010_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2010_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2010_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Microsoft Visual Studio 2010
+#
+# VS2010 - Microsoft Visual Studio 2010 Premium Edition
+# ASL - Microsoft ACPI Source Language Compiler (asl.exe)
+####################################################################################
+# VS2010xASL - Microsoft Visual Studio 2010 Premium Edition
+*_VS2010xASL_*_*_FAMILY = MSFT
+
+*_VS2010xASL_*_MAKE_PATH = DEF(VS2010_BIN)\nmake.exe
+*_VS2010xASL_*_MAKE_FLAG = /nologo
+*_VS2010xASL_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+*_VS2010xASL_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2010xASL_*_APP_FLAGS = /nologo /E /TC
+*_VS2010xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2010xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2010xASL_*_ASM16_PATH = DEF(VS2010_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2010xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_VS2010xASL_*_ASL_FLAGS =
+*_VS2010xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_VS2010xASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2010xASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2010xASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2010xASL_IA32_*_DLL = DEF(VS2010_DLL)
+
+*_VS2010xASL_IA32_MAKE_PATH = DEF(VS2010_BIN)\nmake.exe
+*_VS2010xASL_IA32_CC_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010xASL_IA32_VFRPP_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010xASL_IA32_SLINK_PATH = DEF(VS2010_BIN)\lib.exe
+*_VS2010xASL_IA32_DLINK_PATH = DEF(VS2010_BIN)\link.exe
+*_VS2010xASL_IA32_APP_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010xASL_IA32_PP_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010xASL_IA32_ASM_PATH = DEF(VS2010_BIN)\ml.exe
+*_VS2010xASL_IA32_ASLCC_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010xASL_IA32_ASLPP_PATH = DEF(VS2010_BIN)\cl.exe
+*_VS2010xASL_IA32_ASLDLINK_PATH = DEF(VS2010_BIN)\link.exe
+
+ *_VS2010xASL_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2010xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2010xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2010xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2010xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2010xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2010xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2010xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2010xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2010xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2010xASL_X64_*_DLL = DEF(VS2010_DLL)
+
+*_VS2010xASL_X64_CC_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010xASL_X64_PP_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010xASL_X64_APP_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010xASL_X64_VFRPP_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010xASL_X64_ASM_PATH = DEF(VS2010_BINX64)\ml64.exe
+*_VS2010xASL_X64_SLINK_PATH = DEF(VS2010_BINX64)\lib.exe
+*_VS2010xASL_X64_DLINK_PATH = DEF(VS2010_BINX64)\link.exe
+*_VS2010xASL_X64_ASLCC_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010xASL_X64_ASLPP_PATH = DEF(VS2010_BINX64)\cl.exe
+*_VS2010xASL_X64_ASLDLINK_PATH = DEF(VS2010_BINX64)\link.exe
+
+
+ DEBUG_VS2010xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2010xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2010xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2010xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2010xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2010xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2010xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2010xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2010xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2010xASL_IPF_*_DLL = DEF(VS2010_DLL)
+
+*_VS2010xASL_IPF_PP_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010xASL_IPF_APP_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010xASL_IPF_VFRPP_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010xASL_IPF_CC_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010xASL_IPF_ASM_PATH = DEF(VS2010_BIN64)\ias.exe
+*_VS2010xASL_IPF_SLINK_PATH = DEF(VS2010_BIN64)\lib.exe
+*_VS2010xASL_IPF_DLINK_PATH = DEF(VS2010_BIN64)\link.exe
+*_VS2010xASL_IPF_ASLCC_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010xASL_IPF_ASLPP_PATH = DEF(VS2010_BIN64)\cl.exe
+*_VS2010xASL_IPF_ASLDLINK_PATH = DEF(VS2010_BIN64)\link.exe
+
+ DEBUG_VS2010xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2010xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2010xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2010xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2010xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2010xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2010xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2010xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2010xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_VS2010xASL_EBC_*_FAMILY = INTEL
+
+*_VS2010xASL_EBC_MAKE_PATH = DEF(VS2010_BIN)\nmake.exe
+*_VS2010xASL_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2010xASL_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2010xASL_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_VS2010xASL_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_VS2010xASL_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_VS2010xASL_EBC_MAKE_FLAGS = /nologo
+*_VS2010xASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2010xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_VS2010xASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_VS2010xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_VS2010xASL_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+# VS2010x86 - Microsoft Visual Studio 2010 (x86) with Intel ASL
+# ASL - Intel ACPI Source Language Compiler (iasl.exe)
+####################################################################################
+# VS2010x86 - Microsoft Visual Studio 2010 (x86) ALL Edition with Intel ASL
+*_VS2010x86_*_*_FAMILY = MSFT
+
+*_VS2010x86_*_MAKE_PATH = DEF(VS2010x86_BIN)\nmake.exe
+*_VS2010x86_*_MAKE_FLAG = /nologo
+*_VS2010x86_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+*_VS2010x86_*_MAKE_FLAGS = /nologo
+*_VS2010x86_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2010x86_*_APP_FLAGS = /nologo /E /TC
+*_VS2010x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2010x86_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2010x86_*_ASM16_PATH = DEF(VS2010x86_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2010x86_*_ASL_PATH = DEF(WIN_IASL_BIN)
+*_VS2010x86_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_VS2010x86_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_VS2010x86_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2010x86_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2010x86_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2010x86_IA32_*_DLL = DEF(VS2010x86_DLL)
+
+*_VS2010x86_IA32_MAKE_PATH = DEF(VS2010x86_BIN)\nmake.exe
+*_VS2010x86_IA32_CC_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86_IA32_VFRPP_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86_IA32_ASLCC_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86_IA32_ASLPP_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86_IA32_SLINK_PATH = DEF(VS2010x86_BIN)\lib.exe
+*_VS2010x86_IA32_DLINK_PATH = DEF(VS2010x86_BIN)\link.exe
+*_VS2010x86_IA32_ASLDLINK_PATH= DEF(VS2010x86_BIN)\link.exe
+*_VS2010x86_IA32_APP_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86_IA32_PP_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86_IA32_ASM_PATH = DEF(VS2010x86_BIN)\ml.exe
+
+ *_VS2010x86_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2010x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2010x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2010x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2010x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2010x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2010x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2010x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2010x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2010x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2010x86_X64_*_DLL = DEF(VS2010x86_DLL)
+
+*_VS2010x86_X64_CC_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86_X64_PP_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86_X64_APP_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86_X64_VFRPP_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86_X64_ASLCC_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86_X64_ASLPP_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86_X64_ASM_PATH = DEF(VS2010x86_BINX64)\ml64.exe
+*_VS2010x86_X64_SLINK_PATH = DEF(VS2010x86_BINX64)\lib.exe
+*_VS2010x86_X64_DLINK_PATH = DEF(VS2010x86_BINX64)\link.exe
+*_VS2010x86_X64_ASLDLINK_PATH = DEF(VS2010x86_BINX64)\link.exe
+
+ DEBUG_VS2010x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2010x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2010x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2010x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2010x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2010x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2010x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2010x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2010x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+
+##################
+# IPF definitions
+##################
+*_VS2010x86_IPF_*_DLL = DEF(VS2010x86_DLL)
+
+*_VS2010x86_IPF_PP_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86_IPF_APP_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86_IPF_VFRPP_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86_IPF_ASLCC_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86_IPF_ASLPP_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86_IPF_CC_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86_IPF_ASM_PATH = DEF(VS2010x86_BIN64)\ias.exe
+*_VS2010x86_IPF_SLINK_PATH = DEF(VS2010x86_BIN64)\lib.exe
+*_VS2010x86_IPF_DLINK_PATH = DEF(VS2010x86_BIN64)\link.exe
+*_VS2010x86_IPF_ASLDLINK_PATH = DEF(VS2010x86_BIN64)\link.exe
+
+ DEBUG_VS2010x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2010x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2010x86_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2010x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2010x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2010x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2010x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2010x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2010x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+
+####################################################################################
+# VS2010x86xASL - Microsoft Visual Studio 2010 with Microsoft ASL
+# ASL - Microsoft ACPI Source Language Compiler (asl.exe)
+####################################################################################
+*_VS2010x86xASL_*_*_FAMILY = MSFT
+
+*_VS2010x86xASL_*_MAKE_PATH = DEF(VS2010x86_BIN)\nmake.exe
+*_VS2010x86xASL_*_MAKE_FLAG = /nologo
+*_VS2010x86xASL_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+*_VS2010x86xASL_*_MAKE_FLAGS = /nologo
+*_VS2010x86xASL_*_SLINK_FLAGS = /NOLOGO /LTCG
+*_VS2010x86xASL_*_APP_FLAGS = /nologo /E /TC
+*_VS2010x86xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_VS2010x86xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_VS2010x86xASL_*_ASM16_PATH = DEF(VS2010x86_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_VS2010x86xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_VS2010x86xASL_*_ASL_FLAGS = DEF(MS_ASL_FLAGS)
+*_VS2010x86xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_VS2010x86xASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_VS2010x86xASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_VS2010x86xASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_VS2010x86xASL_IA32_*_DLL = DEF(VS2010x86_DLL)
+
+*_VS2010x86xASL_IA32_MAKE_PATH = DEF(VS2010x86_BIN)\nmake.exe
+*_VS2010x86xASL_IA32_CC_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86xASL_IA32_VFRPP_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86xASL_IA32_ASLCC_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86xASL_IA32_ASLPP_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86xASL_IA32_SLINK_PATH = DEF(VS2010x86_BIN)\lib.exe
+*_VS2010x86xASL_IA32_DLINK_PATH = DEF(VS2010x86_BIN)\link.exe
+*_VS2010x86xASL_IA32_ASLDLINK_PATH= DEF(VS2010x86_BIN)\link.exe
+*_VS2010x86xASL_IA32_APP_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86xASL_IA32_PP_PATH = DEF(VS2010x86_BIN)\cl.exe
+*_VS2010x86xASL_IA32_ASM_PATH = DEF(VS2010x86_BIN)\ml.exe
+
+ *_VS2010x86xASL_IA32_MAKE_FLAGS = /nologo
+ DEBUG_VS2010x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
+RELEASE_VS2010x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2010x86xASL_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
+
+ DEBUG_VS2010x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+RELEASE_VS2010x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd
+NOOPT_VS2010x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Cx /coff /Zd /Zi
+
+ DEBUG_VS2010x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2010x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2010x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_VS2010x86xASL_X64_*_DLL = DEF(VS2010x86_DLL)
+
+*_VS2010x86xASL_X64_CC_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86xASL_X64_PP_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86xASL_X64_APP_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86xASL_X64_VFRPP_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86xASL_X64_ASLCC_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86xASL_X64_ASLPP_PATH = DEF(VS2010x86_BINX64)\cl.exe
+*_VS2010x86xASL_X64_ASM_PATH = DEF(VS2010x86_BINX64)\ml64.exe
+*_VS2010x86xASL_X64_SLINK_PATH = DEF(VS2010x86_BINX64)\lib.exe
+*_VS2010x86xASL_X64_DLINK_PATH = DEF(VS2010x86_BINX64)\link.exe
+*_VS2010x86xASL_X64_ASLDLINK_PATH = DEF(VS2010x86_BINX64)\link.exe
+
+ DEBUG_VS2010x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_VS2010x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_VS2010x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_VS2010x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_VS2010x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_VS2010x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_VS2010x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_VS2010x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_VS2010x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_VS2010x86xASL_IPF_*_DLL = DEF(VS2010x86_DLL)
+
+*_VS2010x86xASL_IPF_PP_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86xASL_IPF_APP_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86xASL_IPF_VFRPP_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86xASL_IPF_ASLCC_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86xASL_IPF_ASLPP_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86xASL_IPF_CC_PATH = DEF(VS2010x86_BIN64)\cl.exe
+*_VS2010x86xASL_IPF_ASM_PATH = DEF(VS2010x86_BIN64)\ias.exe
+*_VS2010x86xASL_IPF_SLINK_PATH = DEF(VS2010x86_BIN64)\lib.exe
+*_VS2010x86xASL_IPF_DLINK_PATH = DEF(VS2010x86_BIN64)\link.exe
+*_VS2010x86xASL_IPF_ASLDLINK_PATH = DEF(VS2010x86_BIN64)\link.exe
+
+ DEBUG_VS2010x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_VS2010x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_VS2010x86xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_VS2010x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_VS2010x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_VS2010x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_VS2010x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_VS2010x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_VS2010x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEBUG_DIR)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+
+
+####################################################################################
+#
+# Microsoft Device Driver Kit 3790.1830 (IA-32, X64, Itanium, with Link Time Code Generation)
+# And Intel ACPI Compiler
+#
+####################################################################################
+# DDK3790 - Microsoft Windows DDK 3790.1830
+# ASL - Intel ACPI Source Language Compiler (iasl.exe)
+*_DDK3790_*_*_FAMILY = MSFT
+
+*_DDK3790_*_MAKE_PATH = DEF(WINDDK_BIN32)\nmake.exe
+*_DDK3790_*_MAKE_FLAGS = /nologo
+*_DDK3790_*_RC_PATH = DEF(WINDDK_BIN32)\rc.exe
+
+*_DDK3790_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_DDK3790_*_APP_FLAGS = /nologo /E /TC
+*_DDK3790_*_SLINK_FLAGS = /nologo /LTCG
+*_DDK3790_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_DDK3790_*_ASM16_PATH = DEF(WINDDK_BIN32)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_DDK3790_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_DDK3790_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_DDK3790_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_DDK3790_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_DDK3790_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_DDK3790_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_DDK3790_IA32_CC_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790_IA32_SLINK_PATH = DEF(WINDDK_BIN32)\lib.exe
+*_DDK3790_IA32_DLINK_PATH = DEF(WINDDK_BIN32)\link.exe
+*_DDK3790_IA32_PP_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790_IA32_VFRPP_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790_IA32_APP_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790_IA32_ASM_PATH = DEF(WINDDK_BIN32)\ml.exe
+*_DDK3790_IA32_ASLCC_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790_IA32_ASLPP_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790_IA32_ASLDLINK_PATH = DEF(WINDDK_BIN32)\link.exe
+
+ DEBUG_DDK3790_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_DDK3790_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_DDK3790_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_DDK3790_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+RELEASE_DDK3790_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd
+NOOPT_DDK3790_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+
+ DEBUG_DDK3790_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_DDK3790_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4078 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_DDK3790_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# x64 definitions
+##################
+*_DDK3790_X64_CC_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790_X64_SLINK_PATH = DEF(WINDDK_BINX64)\lib.exe
+*_DDK3790_X64_DLINK_PATH = DEF(WINDDK_BINX64)\link.exe
+*_DDK3790_X64_PP_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790_X64_VFRPP_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790_X64_APP_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_DDK3790_X64_ASLCC_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790_X64_ASLPP_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790_X64_ASLDLINK_PATH = DEF(WINDDK_BINX64)\link.exe
+
+ DEBUG_DDK3790_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_DDK3790_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_DDK3790_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_DDK3790_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_DDK3790_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_DDK3790_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_DDK3790_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:AMD64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_DDK3790_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4078 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:AMD64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_DDK3790_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:AMD64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_DDK3790_IPF_CC_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790_IPF_SLINK_PATH = DEF(WINDDK_BIN64)\lib.exe
+*_DDK3790_IPF_DLINK_PATH = DEF(WINDDK_BIN64)\link.exe
+*_DDK3790_IPF_PP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790_IPF_VFRPP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790_IPF_APP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790_IPF_ASM_PATH = DEF(WINDDK_BIN64)\ias.exe
+*_DDK3790_IPF_ASLCC_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790_IPF_ASLPP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790_IPF_ASLDLINK_PATH = DEF(WINDDK_BIN64)\link.exe
+
+
+ DEBUG_DDK3790_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_DDK3790_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_DDK3790_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_DDK3790_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_DDK3790_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_DDK3790_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_DDK3790_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_DDK3790_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_DDK3790_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_DDK3790_EBC_*_FAMILY = INTEL
+
+*_DDK3790_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_DDK3790_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_DDK3790_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+*_DDK3790_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_DDK3790_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+
+*_DDK3790_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_DDK3790_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_DDK3790_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Microsoft Device Driver Kit 3790.1830 (IA-32, X64, Itanium, with Link Time Code Generation)
+# And Microsoft ACPI Compiler
+#
+####################################################################################
+# DDK3790xASL - Microsoft Windows DDK 3790.1830
+# ASL - Microsoft ACPI Source Language Compiler (asl.exe)
+*_DDK3790xASL_*_*_FAMILY = MSFT
+
+*_DDK3790xASL_*_MAKE_PATH = DEF(WINDDK_BIN32)\nmake.exe
+*_DDK3790xASL_*_MAKE_FLAGS = /nologo
+*_DDK3790xASL_*_RC_PATH = DEF(WINDDK_BIN32)\rc.exe
+
+*_DDK3790xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_DDK3790xASL_*_APP_FLAGS = /nologo /E /TC
+*_DDK3790xASL_*_SLINK_FLAGS = /nologo /LTCG
+*_DDK3790xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+
+*_DDK3790xASL_*_ASM16_PATH = DEF(WINDDK_BIN32)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_DDK3790xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_DDK3790xASL_*_ASL_FLAGS =
+*_DDK3790xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_DDK3790xASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_DDK3790xASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_DDK3790xASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_DDK3790xASL_IA32_CC_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790xASL_IA32_SLINK_PATH = DEF(WINDDK_BIN32)\lib.exe
+*_DDK3790xASL_IA32_DLINK_PATH = DEF(WINDDK_BIN32)\link.exe
+*_DDK3790xASL_IA32_PP_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790xASL_IA32_VFRPP_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790xASL_IA32_APP_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790xASL_IA32_ASM_PATH = DEF(WINDDK_BIN32)\ml.exe
+*_DDK3790xASL_IA32_ASLCC_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790xASL_IA32_ASLPP_PATH = DEF(WINDDK_BIN32)\cl.exe
+*_DDK3790xASL_IA32_ASLDLINK_PATH = DEF(WINDDK_BIN32)\link.exe
+
+ DEBUG_DDK3790xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_DDK3790xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_DDK3790xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_DDK3790xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+RELEASE_DDK3790xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd
+NOOPT_DDK3790xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+
+ DEBUG_DDK3790xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_DDK3790xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4078 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_DDK3790xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# x64 definitions
+##################
+*_DDK3790xASL_X64_CC_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790xASL_X64_SLINK_PATH = DEF(WINDDK_BINX64)\lib.exe
+*_DDK3790xASL_X64_DLINK_PATH = DEF(WINDDK_BINX64)\link.exe
+*_DDK3790xASL_X64_PP_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790xASL_X64_VFRPP_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790xASL_X64_APP_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790xASL_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_DDK3790xASL_X64_ASLCC_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790xASL_X64_ASLPP_PATH = DEF(WINDDK_BINX64)\cl.exe
+*_DDK3790xASL_X64_ASLDLINK_PATH = DEF(WINDDK_BINX64)\link.exe
+
+ DEBUG_DDK3790xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_DDK3790xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_DDK3790xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+
+ DEBUG_DDK3790xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_DDK3790xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_DDK3790xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_DDK3790xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:AMD64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_DDK3790xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4078 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:AMD64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_DDK3790xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:AMD64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_DDK3790xASL_IPF_CC_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790xASL_IPF_SLINK_PATH = DEF(WINDDK_BIN64)\lib.exe
+*_DDK3790xASL_IPF_DLINK_PATH = DEF(WINDDK_BIN64)\link.exe
+*_DDK3790xASL_IPF_PP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790xASL_IPF_VFRPP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790xASL_IPF_APP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790xASL_IPF_ASM_PATH = DEF(WINDDK_BIN64)\ias.exe
+*_DDK3790xASL_IPF_ASLCC_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790xASL_IPF_ASLPP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_DDK3790xASL_IPF_ASLDLINK_PATH = DEF(WINDDK_BIN64)\link.exe
+
+
+ DEBUG_DDK3790xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32 /Zi
+RELEASE_DDK3790xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /Os /GL /FIAutoGen.h /QIPF_fr32
+NOOPT_DDK3790xASL_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /EHs-c- /GR- /Gy /FIAutoGen.h /QIPF_fr32 /Zi /Od
+
+ DEBUG_DDK3790xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_DDK3790xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_DDK3790xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+
+ DEBUG_DDK3790xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_DDK3790xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_DDK3790xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+##################
+# EBC definitions
+##################
+*_DDK3790xASL_EBC_*_FAMILY = INTEL
+
+*_DDK3790xASL_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_DDK3790xASL_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_DDK3790xASL_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+*_DDK3790xASL_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_DDK3790xASL_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+
+*_DDK3790xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_DDK3790xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_DDK3790xASL_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /ALIGN:32 /DRIVER
+
+
+####################################################################################
+# GCC Common
+####################################################################################
+
+*_*_*_OBJCOPY_PATH = echo
+*_*_*_OBJCOPY_FLAGS = objcopy not needed for
+*_*_*_SYMRENAME_PATH = echo
+*_*_*_SYMRENAME_FLAGS = Symbol renaming not needed for
+DEBUG_*_*_OBJCOPY_ADDDEBUGFLAG = --add-gnu-debuglink=$(DEBUG_DIR)/$(MODULE_NAME).debug
+RELEASE_*_*_OBJCOPY_ADDDEBUGFLAG =
+
+DEFINE GCC_ALL_CC_FLAGS = -g -Os -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -Wno-array-bounds -c -include AutoGen.h
+DEFINE GCC_IA32_CC_FLAGS = DEF(GCC_ALL_CC_FLAGS) -m32 -malign-double -freorder-blocks -freorder-blocks-and-partition -O2 -mno-stack-arg-probe
+DEFINE GCC_X64_CC_FLAGS = DEF(GCC_ALL_CC_FLAGS) -mno-red-zone -Wno-address -mno-stack-arg-probe
+DEFINE GCC_IPF_CC_FLAGS = DEF(GCC_ALL_CC_FLAGS) -minline-int-divide-min-latency
+DEFINE GCC_ARMGCC_CC_FLAGS = DEF(GCC_ALL_CC_FLAGS) -mword-relocations -mlittle-endian -mabi=aapcs -mapcs -fno-short-enums -save-temps -fsigned-char -ffunction-sections -fdata-sections -fomit-frame-pointer
+DEFINE GCC_DLINK_FLAGS_COMMON = -nostdlib --pie
+DEFINE GCC_IA32_X64_DLINK_COMMON = DEF(GCC_DLINK_FLAGS_COMMON) --gc-sections
+DEFINE GCC_IA32_X64_ASLDLINK_FLAGS = DEF(GCC_IA32_X64_DLINK_COMMON) --entry _ReferenceAcpiTable -u $(IMAGE_ENTRY_POINT)
+DEFINE GCC_IA32_X64_DLINK_FLAGS = DEF(GCC_IA32_X64_DLINK_COMMON) --entry _$(IMAGE_ENTRY_POINT) --file-alignment 0x20 --section-alignment 0x20 -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+DEFINE GCC_IPF_DLINK_FLAGS = -nostdlib -O2 --gc-sections --dll -static --entry $(IMAGE_ENTRY_POINT) --undefined $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+DEFINE GCC_IPF_OBJCOPY_FLAGS = -I elf64-ia64-little -O efi-bsdrv-ia64
+DEFINE GCC_IPF_SYMRENAME_FLAGS = --redefine-sym memcpy=CopyMem
+DEFINE GCC_ASM_FLAGS = -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h
+DEFINE GCC_PP_FLAGS = -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+DEFINE GCC_VFRPP_FLAGS = -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+DEFINE GCC_ASLPP_FLAGS = -x c -E -P
+DEFINE GCC_ASLCC_FLAGS = -x c
+DEFINE GCC_WINDRES_FLAGS = -J rc -O coff
+DEFINE GCC_IA32_RC_FLAGS = -I binary -O elf32-i386 -B i386 --rename-section .data=.hii
+DEFINE GCC_X64_RC_FLAGS = -I binary -O elf64-x86-64 -B i386 --rename-section .data=.hii
+DEFINE GCC_IPF_RC_FLAGS = -I binary -O elf64-ia64-little -B ia64 --rename-section .data=.hii
+
+#RTC:29891 - Warning have been disabled for GCC build. Should be turned back on when resolved.
+# DEFINE GCC43_ALL_CC_FLAGS = -g -fshort-wchar -fno-stack-protector -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -Wno-array-bounds -ffunction-sections -fdata-sections -c -include AutoGen.h -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
+DEFINE GCC43_ALL_CC_FLAGS = -g -fshort-wchar -fno-stack-protector -fno-strict-aliasing -Wall -Wno-missing-braces -Wno-array-bounds -ffunction-sections -fdata-sections -c -include AutoGen.h -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
+DEFINE GCC43_IA32_CC_FLAGS = DEF(GCC43_ALL_CC_FLAGS) -m32 -march=i586 -malign-double -D EFI32
+DEFINE GCC43_X64_CC_FLAGS = DEF(GCC43_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -DNO_BUILTIN_VA_FUNCS -mno-red-zone -Wno-address -mcmodel=large
+DEFINE GCC43_IA32_X64_DLINK_COMMON = -nostdlib -n -q --gc-sections --script=$(EDK_TOOLS_PATH)/Scripts/gcc4.4-ld-script
+DEFINE GCC43_IA32_X64_ASLDLINK_FLAGS = DEF(GCC43_IA32_X64_DLINK_COMMON) --entry ReferenceAcpiTable -u ReferenceAcpiTable
+DEFINE GCC43_IA32_X64_DLINK_FLAGS = DEF(GCC43_IA32_X64_DLINK_COMMON) --entry $(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+DEFINE GCC43_X64_DLINK_FLAGS = DEF(GCC43_IA32_X64_DLINK_FLAGS) -melf_x86_64 --oformat=elf64-x86-64
+DEFINE GCC43_ASM_FLAGS = DEF(GCC_ASM_FLAGS)
+
+DEFINE GCC44_IA32_CC_FLAGS = DEF(GCC43_IA32_CC_FLAGS)
+DEFINE GCC44_X64_CC_FLAGS = DEF(GCC43_X64_CC_FLAGS)
+DEFINE GCC44_IA32_X64_DLINK_COMMON = DEF(GCC43_IA32_X64_DLINK_COMMON)
+DEFINE GCC44_IA32_X64_ASLDLINK_FLAGS = DEF(GCC43_IA32_X64_ASLDLINK_FLAGS)
+DEFINE GCC44_IA32_X64_DLINK_FLAGS = DEF(GCC43_IA32_X64_DLINK_FLAGS)
+DEFINE GCC44_X64_DLINK_FLAGS = DEF(GCC43_X64_DLINK_FLAGS)
+DEFINE GCC44_ASM_FLAGS = DEF(GCC43_ASM_FLAGS)
+
+DEFINE GCC45_IA32_CC_FLAGS = DEF(GCC44_IA32_CC_FLAGS)
+DEFINE GCC45_X64_CC_FLAGS = DEF(GCC44_X64_CC_FLAGS)
+DEFINE GCC45_IA32_X64_DLINK_COMMON = DEF(GCC44_IA32_X64_DLINK_COMMON)
+DEFINE GCC45_IA32_X64_ASLDLINK_FLAGS = DEF(GCC44_IA32_X64_ASLDLINK_FLAGS)
+DEFINE GCC45_IA32_X64_DLINK_FLAGS = DEF(GCC44_IA32_X64_DLINK_FLAGS)
+DEFINE GCC45_X64_DLINK_FLAGS = DEF(GCC44_X64_DLINK_FLAGS)
+DEFINE GCC45_ASM_FLAGS = DEF(GCC44_ASM_FLAGS)
+
+DEFINE GCC46_IA32_CC_FLAGS = DEF(GCC45_IA32_CC_FLAGS) -Wno-address -Wno-unused-but-set-variable
+DEFINE GCC46_X64_CC_FLAGS = DEF(GCC45_X64_CC_FLAGS) -Wno-address -Wno-unused-but-set-variable
+DEFINE GCC46_IA32_X64_DLINK_COMMON = DEF(GCC45_IA32_X64_DLINK_COMMON)
+DEFINE GCC46_IA32_X64_ASLDLINK_FLAGS = DEF(GCC45_IA32_X64_ASLDLINK_FLAGS)
+DEFINE GCC46_IA32_X64_DLINK_FLAGS = DEF(GCC45_IA32_X64_DLINK_FLAGS)
+DEFINE GCC46_X64_DLINK_FLAGS = DEF(GCC45_X64_DLINK_FLAGS)
+DEFINE GCC46_ASM_FLAGS = DEF(GCC45_ASM_FLAGS)
+
+DEFINE GCC47_IA32_CC_FLAGS = DEF(GCC46_IA32_CC_FLAGS)
+DEFINE GCC47_X64_CC_FLAGS = DEF(GCC46_X64_CC_FLAGS)
+DEFINE GCC47_IA32_X64_DLINK_COMMON = DEF(GCC46_IA32_X64_DLINK_COMMON)
+DEFINE GCC47_IA32_X64_ASLDLINK_FLAGS = DEF(GCC46_IA32_X64_ASLDLINK_FLAGS)
+DEFINE GCC47_IA32_X64_DLINK_FLAGS = DEF(GCC46_IA32_X64_DLINK_FLAGS)
+DEFINE GCC47_X64_DLINK_FLAGS = DEF(GCC46_X64_DLINK_FLAGS)
+DEFINE GCC47_ASM_FLAGS = DEF(GCC46_ASM_FLAGS)
+
+####################################################################################
+#
+# Unix GCC And Intel Linux ACPI Compiler
+#
+####################################################################################
+# UNIXGCC - UNIX GCC
+# ASL - Intel Linux ACPI Source Language Compiler (iasl)
+*_UNIXGCC_*_*_FAMILY = GCC
+
+*_UNIXGCC_*_MAKE_PATH = make
+*_UNIXGCC_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+
+*_UNIXGCC_IA32_DLINK_FLAGS = DEF(GCC_IA32_X64_DLINK_FLAGS) --image-base=0
+*_UNIXGCC_X64_DLINK_FLAGS = DEF(GCC_IA32_X64_DLINK_FLAGS) --image-base=0
+*_UNIXGCC_IA32_ASLDLINK_FLAGS = DEF(GCC_IA32_X64_ASLDLINK_FLAGS)
+*_UNIXGCC_X64_ASLDLINK_FLAGS = DEF(GCC_IA32_X64_ASLDLINK_FLAGS)
+*_UNIXGCC_*_ASM_FLAGS = DEF(GCC_ASM_FLAGS)
+*_UNIXGCC_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_UNIXGCC_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_UNIXGCC_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_UNIXGCC_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_UNIXGCC_*_APP_FLAGS =
+*_UNIXGCC_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_UNIXGCC_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+
+##################
+# IA32 definitions
+##################
+*_UNIXGCC_IA32_OBJCOPY_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)objcopy
+*_UNIXGCC_IA32_PP_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IA32_CC_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IA32_SLINK_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)ar
+*_UNIXGCC_IA32_DLINK_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)ld
+*_UNIXGCC_IA32_ASLPP_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IA32_ASLCC_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IA32_ASLDLINK_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)ld
+*_UNIXGCC_IA32_ASM_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IA32_VFRPP_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IA32_RC_PATH = DEF(UNIXGCC_IA32_PETOOLS_PREFIX)objcopy
+
+*_UNIXGCC_IA32_CC_FLAGS = DEF(GCC_IA32_CC_FLAGS)
+*_UNIXGCC_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_UNIXGCC_IA32_OBJCOPY_FLAGS =
+
+##################
+# X64 definitions
+##################
+*_UNIXGCC_X64_CC_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)gcc
+*_UNIXGCC_X64_ASLCC_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)gcc
+*_UNIXGCC_X64_SLINK_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)ar
+*_UNIXGCC_X64_DLINK_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)ld
+*_UNIXGCC_X64_ASLDLINK_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)ld
+*_UNIXGCC_X64_ASM_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)gcc
+*_UNIXGCC_X64_PP_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)gcc
+*_UNIXGCC_X64_ASLPP_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)gcc
+*_UNIXGCC_X64_VFRPP_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)gcc
+*_UNIXGCC_X64_RC_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)objcopy
+*_UNIXGCC_X64_OBJCOPY_PATH = DEF(UNIXGCC_X64_PETOOLS_PREFIX)objcopy
+
+*_UNIXGCC_X64_CC_FLAGS = DEF(GCC_X64_CC_FLAGS)
+*_UNIXGCC_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_UNIXGCC_X64_OBJCOPY_FLAGS =
+
+##################
+# IPF definitions
+##################
+*_UNIXGCC_IPF_CC_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IPF_ASLCC_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IPF_SLINK_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)ar
+*_UNIXGCC_IPF_DLINK_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)ld
+*_UNIXGCC_IPF_ASLDLINK_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)ld
+*_UNIXGCC_IPF_ASM_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IPF_PP_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IPF_ASLPP_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IPF_VFRPP_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)gcc
+*_UNIXGCC_IPF_OBJCOPY_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)objcopy
+*_UNIXGCC_IPF_SYMRENAME_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)objcopy
+*_UNIXGCC_IPF_RC_PATH = DEF(UNIXGCC_IPF_PETOOLS_PREFIX)objcopy
+
+*_UNIXGCC_IPF_CC_FLAGS = DEF(GCC_IPF_CC_FLAGS)
+*_UNIXGCC_IPF_DLINK_FLAGS = DEF(GCC_IPF_DLINK_FLAGS)
+*_UNIXGCC_IPF_OBJCOPY_FLAGS = DEF(GCC_IPF_OBJCOPY_FLAGS)
+*_UNIXGCC_IPF_SYMRENAME_FLAGS = DEF(GCC_IPF_SYMRENAME_FLAGS)
+*_UNIXGCC_IPF_RC_FLAGS = DEF(GCC_IPF_RC_FLAGS)
+
+
+####################################################################################
+#
+# GCC 4.3 - This configuration is used to compile under Linux to produce
+# PE/COFF binaries using GCC 4.3.
+#
+####################################################################################
+*_GCC43_*_*_FAMILY = GCC
+
+*_GCC43_*_MAKE_PATH = make
+*_GCC43_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+
+*_GCC43_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_GCC43_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_GCC43_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_GCC43_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_GCC43_*_APP_FLAGS =
+*_GCC43_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_GCC43_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+
+##################
+# GCC43 IA32 definitions
+##################
+*_GCC43_IA32_OBJCOPY_PATH = DEF(GCC43_IA32_PREFIX)objcopy
+*_GCC43_IA32_CC_PATH = DEF(GCC43_IA32_PREFIX)gcc
+*_GCC43_IA32_SLINK_PATH = DEF(GCC43_IA32_PREFIX)ar
+*_GCC43_IA32_DLINK_PATH = DEF(GCC43_IA32_PREFIX)ld
+*_GCC43_IA32_ASLDLINK_PATH = DEF(GCC43_IA32_PREFIX)ld
+*_GCC43_IA32_ASM_PATH = DEF(GCC43_IA32_PREFIX)gcc
+*_GCC43_IA32_PP_PATH = DEF(GCC43_IA32_PREFIX)gcc
+*_GCC43_IA32_VFRPP_PATH = DEF(GCC43_IA32_PREFIX)gcc
+*_GCC43_IA32_ASLCC_PATH = DEF(GCC43_IA32_PREFIX)gcc
+*_GCC43_IA32_ASLPP_PATH = DEF(GCC43_IA32_PREFIX)gcc
+*_GCC43_IA32_RC_PATH = DEF(GCC43_IA32_PREFIX)objcopy
+
+*_GCC43_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
+*_GCC43_IA32_ASLDLINK_FLAGS = DEF(GCC43_IA32_X64_ASLDLINK_FLAGS) -m elf_i386
+*_GCC43_IA32_ASM_FLAGS = DEF(GCC43_ASM_FLAGS) -m32 --32 -march=i386
+*_GCC43_IA32_CC_FLAGS = DEF(GCC43_IA32_CC_FLAGS) -Os
+*_GCC43_IA32_DLINK_FLAGS = DEF(GCC43_IA32_X64_DLINK_FLAGS) -m elf_i386 --oformat=elf32-i386
+*_GCC43_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_GCC43_IA32_OBJCOPY_FLAGS =
+
+##################
+# GCC43 X64 definitions
+##################
+*_GCC43_X64_OBJCOPY_PATH = DEF(GCC43_X64_PREFIX)objcopy
+*_GCC43_X64_CC_PATH = DEF(GCC43_X64_PREFIX)gcc
+*_GCC43_X64_SLINK_PATH = DEF(GCC43_X64_PREFIX)ar
+*_GCC43_X64_DLINK_PATH = DEF(GCC43_X64_PREFIX)ld
+*_GCC43_X64_ASLDLINK_PATH = DEF(GCC43_X64_PREFIX)ld
+*_GCC43_X64_ASM_PATH = DEF(GCC43_X64_PREFIX)gcc
+*_GCC43_X64_PP_PATH = DEF(GCC43_X64_PREFIX)gcc
+*_GCC43_X64_VFRPP_PATH = DEF(GCC43_X64_PREFIX)gcc
+*_GCC43_X64_ASLCC_PATH = DEF(GCC43_X64_PREFIX)gcc
+*_GCC43_X64_ASLPP_PATH = DEF(GCC43_X64_PREFIX)gcc
+*_GCC43_X64_RC_PATH = DEF(GCC43_X64_PREFIX)objcopy
+
+*_GCC43_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
+*_GCC43_X64_ASLDLINK_FLAGS = DEF(GCC43_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
+*_GCC43_X64_ASM_FLAGS = DEF(GCC43_ASM_FLAGS) -m64 --64 -melf_x86_64
+*_GCC43_X64_CC_FLAGS = DEF(GCC43_X64_CC_FLAGS)
+*_GCC43_X64_DLINK_FLAGS = DEF(GCC43_X64_DLINK_FLAGS)
+*_GCC43_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_GCC43_X64_OBJCOPY_FLAGS =
+
+
+####################################################################################
+#
+# GCC 4.4 - This configuration is used to compile under Linux to produce
+# PE/COFF binaries using GCC 4.4.
+#
+####################################################################################
+*_GCC44_*_*_FAMILY = GCC
+
+*_GCC44_*_MAKE_PATH = make
+*_GCC44_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+
+*_GCC44_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_GCC44_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_GCC44_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_GCC44_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_GCC44_*_APP_FLAGS =
+*_GCC44_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_GCC44_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+
+##################
+# GCC44 IA32 definitions
+##################
+*_GCC44_IA32_OBJCOPY_PATH = DEF(GCC44_IA32_PREFIX)objcopy
+*_GCC44_IA32_CC_PATH = DEF(GCC44_IA32_PREFIX)gcc
+*_GCC44_IA32_SLINK_PATH = DEF(GCC44_IA32_PREFIX)ar
+*_GCC44_IA32_DLINK_PATH = DEF(GCC44_IA32_PREFIX)ld
+*_GCC44_IA32_ASLDLINK_PATH = DEF(GCC44_IA32_PREFIX)ld
+*_GCC44_IA32_ASM_PATH = DEF(GCC44_IA32_PREFIX)gcc
+*_GCC44_IA32_PP_PATH = DEF(GCC44_IA32_PREFIX)gcc
+*_GCC44_IA32_VFRPP_PATH = DEF(GCC44_IA32_PREFIX)gcc
+*_GCC44_IA32_ASLCC_PATH = DEF(GCC44_IA32_PREFIX)gcc
+*_GCC44_IA32_ASLPP_PATH = DEF(GCC44_IA32_PREFIX)gcc
+*_GCC44_IA32_RC_PATH = DEF(GCC44_IA32_PREFIX)objcopy
+
+*_GCC44_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
+*_GCC44_IA32_ASLDLINK_FLAGS = DEF(GCC44_IA32_X64_ASLDLINK_FLAGS) -m elf_i386
+*_GCC44_IA32_ASM_FLAGS = DEF(GCC44_ASM_FLAGS) -m32 --32 -march=i386
+*_GCC44_IA32_CC_FLAGS = DEF(GCC44_IA32_CC_FLAGS) -Os
+*_GCC44_IA32_DLINK_FLAGS = DEF(GCC44_IA32_X64_DLINK_FLAGS) -m elf_i386 --oformat=elf32-i386
+*_GCC44_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_GCC44_IA32_OBJCOPY_FLAGS =
+
+##################
+# GCC44 X64 definitions
+##################
+*_GCC44_X64_OBJCOPY_PATH = DEF(GCC44_X64_PREFIX)objcopy
+*_GCC44_X64_CC_PATH = DEF(GCC44_X64_PREFIX)gcc
+*_GCC44_X64_SLINK_PATH = DEF(GCC44_X64_PREFIX)ar
+*_GCC44_X64_DLINK_PATH = DEF(GCC44_X64_PREFIX)ld
+*_GCC44_X64_ASLDLINK_PATH = DEF(GCC44_X64_PREFIX)ld
+*_GCC44_X64_ASM_PATH = DEF(GCC44_X64_PREFIX)gcc
+*_GCC44_X64_PP_PATH = DEF(GCC44_X64_PREFIX)gcc
+*_GCC44_X64_VFRPP_PATH = DEF(GCC44_X64_PREFIX)gcc
+*_GCC44_X64_ASLCC_PATH = DEF(GCC44_X64_PREFIX)gcc
+*_GCC44_X64_ASLPP_PATH = DEF(GCC44_X64_PREFIX)gcc
+*_GCC44_X64_RC_PATH = DEF(GCC44_X64_PREFIX)objcopy
+
+*_GCC44_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
+*_GCC44_X64_ASLDLINK_FLAGS = DEF(GCC44_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
+*_GCC44_X64_ASM_FLAGS = DEF(GCC44_ASM_FLAGS) -m64 --64 -melf_x86_64
+*_GCC44_X64_CC_FLAGS = DEF(GCC44_X64_CC_FLAGS)
+*_GCC44_X64_DLINK_FLAGS = DEF(GCC44_X64_DLINK_FLAGS)
+*_GCC44_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_GCC44_X64_OBJCOPY_FLAGS =
+
+####################################################################################
+#
+# GCC 4.5 - This configuration is used to compile under Linux to produce
+# PE/COFF binaries using GCC 4.5.
+#
+####################################################################################
+*_GCC45_*_*_FAMILY = GCC
+
+*_GCC45_*_MAKE_PATH = make
+*_GCC45_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+
+*_GCC45_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_GCC45_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_GCC45_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_GCC45_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_GCC45_*_APP_FLAGS =
+*_GCC45_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_GCC45_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+
+##################
+# GCC45 IA32 definitions
+##################
+*_GCC45_IA32_OBJCOPY_PATH = DEF(GCC45_IA32_PREFIX)objcopy
+*_GCC45_IA32_CC_PATH = DEF(GCC45_IA32_PREFIX)gcc
+*_GCC45_IA32_SLINK_PATH = DEF(GCC45_IA32_PREFIX)ar
+*_GCC45_IA32_DLINK_PATH = DEF(GCC45_IA32_PREFIX)ld
+*_GCC45_IA32_ASLDLINK_PATH = DEF(GCC45_IA32_PREFIX)ld
+*_GCC45_IA32_ASM_PATH = DEF(GCC45_IA32_PREFIX)gcc
+*_GCC45_IA32_PP_PATH = DEF(GCC45_IA32_PREFIX)gcc
+*_GCC45_IA32_VFRPP_PATH = DEF(GCC45_IA32_PREFIX)gcc
+*_GCC45_IA32_ASLCC_PATH = DEF(GCC45_IA32_PREFIX)gcc
+*_GCC45_IA32_ASLPP_PATH = DEF(GCC45_IA32_PREFIX)gcc
+*_GCC45_IA32_RC_PATH = DEF(GCC45_IA32_PREFIX)objcopy
+
+*_GCC45_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
+*_GCC45_IA32_ASLDLINK_FLAGS = DEF(GCC45_IA32_X64_ASLDLINK_FLAGS) -m elf_i386
+*_GCC45_IA32_ASM_FLAGS = DEF(GCC45_ASM_FLAGS) -m32 --32 -march=i386
+*_GCC45_IA32_CC_FLAGS = DEF(GCC45_IA32_CC_FLAGS) -Os
+*_GCC45_IA32_DLINK_FLAGS = DEF(GCC45_IA32_X64_DLINK_FLAGS) -m elf_i386 --oformat=elf32-i386
+*_GCC45_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_GCC45_IA32_OBJCOPY_FLAGS =
+
+##################
+# GCC45 X64 definitions
+##################
+*_GCC45_X64_OBJCOPY_PATH = DEF(GCC45_X64_PREFIX)objcopy
+*_GCC45_X64_CC_PATH = DEF(GCC45_X64_PREFIX)gcc
+*_GCC45_X64_SLINK_PATH = DEF(GCC45_X64_PREFIX)ar
+*_GCC45_X64_DLINK_PATH = DEF(GCC45_X64_PREFIX)ld
+*_GCC45_X64_ASLDLINK_PATH = DEF(GCC45_X64_PREFIX)ld
+*_GCC45_X64_ASM_PATH = DEF(GCC45_X64_PREFIX)gcc
+*_GCC45_X64_PP_PATH = DEF(GCC45_X64_PREFIX)gcc
+*_GCC45_X64_VFRPP_PATH = DEF(GCC45_X64_PREFIX)gcc
+*_GCC45_X64_ASLCC_PATH = DEF(GCC45_X64_PREFIX)gcc
+*_GCC45_X64_ASLPP_PATH = DEF(GCC45_X64_PREFIX)gcc
+*_GCC45_X64_RC_PATH = DEF(GCC45_X64_PREFIX)objcopy
+
+*_GCC45_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
+*_GCC45_X64_ASLDLINK_FLAGS = DEF(GCC45_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
+*_GCC45_X64_ASM_FLAGS = DEF(GCC45_ASM_FLAGS) -m64 --64 -melf_x86_64
+*_GCC45_X64_CC_FLAGS = DEF(GCC45_X64_CC_FLAGS)
+*_GCC45_X64_DLINK_FLAGS = DEF(GCC45_X64_DLINK_FLAGS)
+*_GCC45_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_GCC45_X64_OBJCOPY_FLAGS =
+
+####################################################################################
+#
+# GCC 4.6 - This configuration is used to compile under Linux to produce
+# PE/COFF binaries using GCC 4.6.
+#
+####################################################################################
+*_GCC46_*_*_FAMILY = GCC
+
+*_GCC46_*_MAKE_PATH = make
+*_GCC46_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+
+*_GCC46_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_GCC46_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_GCC46_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_GCC46_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_GCC46_*_APP_FLAGS =
+*_GCC46_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_GCC46_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+
+##################
+# GCC46 IA32 definitions
+##################
+*_GCC46_IA32_OBJCOPY_PATH = DEF(GCC46_IA32_PREFIX)objcopy
+*_GCC46_IA32_CC_PATH = DEF(GCC46_IA32_PREFIX)gcc
+*_GCC46_IA32_SLINK_PATH = DEF(GCC46_IA32_PREFIX)ar
+*_GCC46_IA32_DLINK_PATH = DEF(GCC46_IA32_PREFIX)ld
+*_GCC46_IA32_ASLDLINK_PATH = DEF(GCC46_IA32_PREFIX)ld
+*_GCC46_IA32_ASM_PATH = DEF(GCC46_IA32_PREFIX)gcc
+*_GCC46_IA32_PP_PATH = DEF(GCC46_IA32_PREFIX)gcc
+*_GCC46_IA32_VFRPP_PATH = DEF(GCC46_IA32_PREFIX)gcc
+*_GCC46_IA32_ASLCC_PATH = DEF(GCC46_IA32_PREFIX)gcc
+*_GCC46_IA32_ASLPP_PATH = DEF(GCC46_IA32_PREFIX)gcc
+*_GCC46_IA32_RC_PATH = DEF(GCC46_IA32_PREFIX)objcopy
+
+*_GCC46_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
+*_GCC46_IA32_ASLDLINK_FLAGS = DEF(GCC46_IA32_X64_ASLDLINK_FLAGS) -m elf_i386
+*_GCC46_IA32_ASM_FLAGS = DEF(GCC46_ASM_FLAGS) -m32 -march=i386
+*_GCC46_IA32_CC_FLAGS = DEF(GCC46_IA32_CC_FLAGS) -Os
+*_GCC46_IA32_DLINK_FLAGS = DEF(GCC46_IA32_X64_DLINK_FLAGS) -m elf_i386 --oformat=elf32-i386
+*_GCC46_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_GCC46_IA32_OBJCOPY_FLAGS =
+
+##################
+# GCC46 X64 definitions
+##################
+*_GCC46_X64_OBJCOPY_PATH = DEF(GCC46_X64_PREFIX)objcopy
+*_GCC46_X64_CC_PATH = DEF(GCC46_X64_PREFIX)gcc
+*_GCC46_X64_SLINK_PATH = DEF(GCC46_X64_PREFIX)ar
+*_GCC46_X64_DLINK_PATH = DEF(GCC46_X64_PREFIX)ld
+*_GCC46_X64_ASLDLINK_PATH = DEF(GCC46_X64_PREFIX)ld
+*_GCC46_X64_ASM_PATH = DEF(GCC46_X64_PREFIX)gcc
+*_GCC46_X64_PP_PATH = DEF(GCC46_X64_PREFIX)gcc
+*_GCC46_X64_VFRPP_PATH = DEF(GCC46_X64_PREFIX)gcc
+*_GCC46_X64_ASLCC_PATH = DEF(GCC46_X64_PREFIX)gcc
+*_GCC46_X64_ASLPP_PATH = DEF(GCC46_X64_PREFIX)gcc
+*_GCC46_X64_RC_PATH = DEF(GCC46_X64_PREFIX)objcopy
+
+*_GCC46_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
+*_GCC46_X64_ASLDLINK_FLAGS = DEF(GCC46_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
+*_GCC46_X64_ASM_FLAGS = DEF(GCC46_ASM_FLAGS) -m64 -melf_x86_64
+*_GCC46_X64_CC_FLAGS = DEF(GCC46_X64_CC_FLAGS)
+*_GCC46_X64_DLINK_FLAGS = DEF(GCC46_X64_DLINK_FLAGS)
+*_GCC46_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_GCC46_X64_OBJCOPY_FLAGS =
+
+####################################################################################
+#
+# GCC 4.7 - This configuration is used to compile under Linux to produce
+# PE/COFF binaries using GCC 4.7.
+#
+####################################################################################
+*_GCC47_*_*_FAMILY = GCC
+
+*_GCC47_*_MAKE_PATH = make
+*_GCC47_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+
+*_GCC47_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_GCC47_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_GCC47_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_GCC47_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_GCC47_*_APP_FLAGS =
+*_GCC47_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_GCC47_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+
+##################
+# GCC47 IA32 definitions
+##################
+*_GCC47_IA32_OBJCOPY_PATH = DEF(GCC47_IA32_PREFIX)objcopy
+*_GCC47_IA32_CC_PATH = DEF(GCC47_IA32_PREFIX)gcc
+*_GCC47_IA32_SLINK_PATH = DEF(GCC47_IA32_PREFIX)ar
+*_GCC47_IA32_DLINK_PATH = DEF(GCC47_IA32_PREFIX)ld
+*_GCC47_IA32_ASLDLINK_PATH = DEF(GCC47_IA32_PREFIX)ld
+*_GCC47_IA32_ASM_PATH = DEF(GCC47_IA32_PREFIX)gcc
+*_GCC47_IA32_PP_PATH = DEF(GCC47_IA32_PREFIX)gcc
+*_GCC47_IA32_VFRPP_PATH = DEF(GCC47_IA32_PREFIX)gcc
+*_GCC47_IA32_ASLCC_PATH = DEF(GCC47_IA32_PREFIX)gcc
+*_GCC47_IA32_ASLPP_PATH = DEF(GCC47_IA32_PREFIX)gcc
+*_GCC47_IA32_RC_PATH = DEF(GCC47_IA32_PREFIX)objcopy
+
+*_GCC47_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32
+*_GCC47_IA32_ASLDLINK_FLAGS = DEF(GCC47_IA32_X64_ASLDLINK_FLAGS) -m elf_i386
+*_GCC47_IA32_ASM_FLAGS = DEF(GCC47_ASM_FLAGS) -m32 -march=i386
+*_GCC47_IA32_CC_FLAGS = DEF(GCC47_IA32_CC_FLAGS) -Os
+*_GCC47_IA32_DLINK_FLAGS = DEF(GCC47_IA32_X64_DLINK_FLAGS) -m elf_i386 --oformat=elf32-i386
+*_GCC47_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_GCC47_IA32_OBJCOPY_FLAGS =
+
+##################
+# GCC47 X64 definitions
+##################
+*_GCC47_X64_OBJCOPY_PATH = DEF(GCC47_X64_PREFIX)objcopy
+*_GCC47_X64_CC_PATH = DEF(GCC47_X64_PREFIX)gcc
+*_GCC47_X64_SLINK_PATH = DEF(GCC47_X64_PREFIX)ar
+*_GCC47_X64_DLINK_PATH = DEF(GCC47_X64_PREFIX)ld
+*_GCC47_X64_ASLDLINK_PATH = DEF(GCC47_X64_PREFIX)ld
+*_GCC47_X64_ASM_PATH = DEF(GCC47_X64_PREFIX)gcc
+*_GCC47_X64_PP_PATH = DEF(GCC47_X64_PREFIX)gcc
+*_GCC47_X64_VFRPP_PATH = DEF(GCC47_X64_PREFIX)gcc
+*_GCC47_X64_ASLCC_PATH = DEF(GCC47_X64_PREFIX)gcc
+*_GCC47_X64_ASLPP_PATH = DEF(GCC47_X64_PREFIX)gcc
+*_GCC47_X64_RC_PATH = DEF(GCC47_X64_PREFIX)objcopy
+
+*_GCC47_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
+*_GCC47_X64_ASLDLINK_FLAGS = DEF(GCC47_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
+*_GCC47_X64_ASM_FLAGS = DEF(GCC47_ASM_FLAGS) -m64
+*_GCC47_X64_CC_FLAGS = DEF(GCC47_X64_CC_FLAGS)
+*_GCC47_X64_DLINK_FLAGS = DEF(GCC47_X64_DLINK_FLAGS)
+*_GCC47_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_GCC47_X64_OBJCOPY_FLAGS =
+
+####################################################################################
+#
+# Cygwin GCC And Intel ACPI Compiler
+#
+####################################################################################
+# CYGGCC - CygWin GCC
+# ASL - Intel ACPI Source Language Compiler (iasl.exe)
+*_CYGGCC_*_*_FAMILY = GCC
+
+*_CYGGCC_*_*_DLL = DEF(CYGWIN_BIN)
+*_CYGGCC_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_CYGGCC_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+
+*_CYGGCC_IA32_DLINK_FLAGS = DEF(GCC_IA32_X64_DLINK_FLAGS) --image-base=0
+*_CYGGCC_X64_DLINK_FLAGS = DEF(GCC_IA32_X64_DLINK_FLAGS) --image-base=0
+*_CYGGCC_IA32_ASLDLINK_FLAGS = DEF(GCC_IA32_X64_ASLDLINK_FLAGS)
+*_CYGGCC_X64_ASLDLINK_FLAGS = DEF(GCC_IA32_X64_ASLDLINK_FLAGS)
+*_CYGGCC_*_MAKE_FLAGS = /nologo
+*_CYGGCC_*_ASM_FLAGS = DEF(GCC_ASM_FLAGS)
+*_CYGGCC_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_CYGGCC_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_CYGGCC_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_CYGGCC_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_CYGGCC_*_APP_FLAGS =
+*_CYGGCC_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_CYGGCC_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+
+##################
+# IA32 definitions
+##################
+*_CYGGCC_IA32_CC_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCC_IA32_SLINK_PATH = DEF(CYGWIN_BINIA32)ar
+*_CYGGCC_IA32_DLINK_PATH = DEF(CYGWIN_BINIA32)ld
+*_CYGGCC_IA32_ASM_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCC_IA32_PP_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCC_IA32_APP_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCC_IA32_VFRPP_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCC_IA32_ASLCC_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCC_IA32_ASLPP_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCC_IA32_ASLDLINK_PATH = DEF(CYGWIN_BINIA32)ld
+*_CYGGCC_IA32_RC_PATH = DEF(CYGWIN_BINIA32)objcopy
+*_CYGGCC_IA32_OBJCOPY_PATH = DEF(CYGWIN_BINIA32)objcopy
+
+*_CYGGCC_IA32_CC_FLAGS = DEF(GCC_IA32_CC_FLAGS)
+*_CYGGCC_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_CYGGCC_IA32_OBJCOPY_FLAGS =
+
+##################
+# X64 definitions
+##################
+*_CYGGCC_X64_CC_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCC_X64_SLINK_PATH = DEF(CYGWIN_BINX64)ar
+*_CYGGCC_X64_DLINK_PATH = DEF(CYGWIN_BINX64)ld
+*_CYGGCC_X64_ASM_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCC_X64_PP_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCC_X64_APP_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCC_X64_VFRPP_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCC_X64_ASLCC_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCC_X64_ASLPP_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCC_X64_ASLDLINK_PATH = DEF(CYGWIN_BINX64)ld
+*_CYGGCC_X64_RC_PATH = DEF(CYGWIN_BINX64)objcopy
+*_CYGGCC_X64_OBJCOPY_PATH = DEF(CYGWIN_BINX64)objcopy
+
+*_CYGGCC_X64_CC_FLAGS = DEF(GCC_X64_CC_FLAGS)
+*_CYGGCC_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_CYGGCC_X64_OBJCOPY_FLAGS =
+
+##################
+# IPF definitions
+##################
+*_CYGGCC_IPF_CC_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCC_IPF_SLINK_PATH = DEF(CYGWIN_BINIPF)ar
+*_CYGGCC_IPF_DLINK_PATH = DEF(CYGWIN_BINIPF)ld
+*_CYGGCC_IPF_ASLDLINK_PATH = DEF(CYGWIN_BINIPF)ld
+*_CYGGCC_IPF_ASM_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCC_IPF_PP_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCC_IPF_VFRPP_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCC_IPF_ASLCC_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCC_IPF_ASLPP_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCC_IPF_OBJCOPY_PATH = DEF(CYGWIN_BINIPF)objcopy
+*_CYGGCC_IPF_SYMRENAME_PATH = DEF(CYGWIN_BINIPF)objcopy
+*_CYGGCC_IPF_RC_PATH = DEF(CYGWIN_BINIPF)objcopy
+
+*_CYGGCC_IPF_CC_FLAGS = DEF(GCC_IPF_CC_FLAGS)
+*_CYGGCC_IPF_DLINK_FLAGS = DEF(GCC_IPF_DLINK_FLAGS)
+*_CYGGCC_IPF_OBJCOPY_FLAGS = DEF(GCC_IPF_OBJCOPY_FLAGS)
+*_CYGGCC_IPF_SYMRENAME_FLAGS = DEF(GCC_IPF_SYMRENAME_FLAGS)
+*_CYGGCC_IPF_RC_FLAGS = DEF(GCC_IPF_RC_FLAGS)
+
+##################
+# EBC definitions
+##################
+*_CYGGCC_EBC_*_FAMILY = INTEL
+
+*_CYGGCC_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_CYGGCC_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_CYGGCC_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+*_CYGGCC_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_CYGGCC_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_CYGGCC_EBC_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_CYGGCC_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_CYGGCC_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_CYGGCC_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Cygwin GCC And Microsoft ACPI Compiler
+#
+####################################################################################
+# CYGGCCxASL - CygWin GCC
+# ASL - Microsoft ACPI Source Language Compiler (asl.exe)
+*_CYGGCCxASL_*_*_FAMILY = GCC
+
+*_CYGGCCxASL_*_*_DLL = DEF(CYGWIN_BIN)
+*_CYGGCCxASL_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+
+*_CYGGCCxASL_*_MAKE_FLAGS = /nologo
+*_CYGGCCxASL_*_PP_FLAGS = -E -x assembler-with-cpp -include AutoGen.h
+*_CYGGCCxASL_*_DLINK_FLAGS = -nostdlib -O2 --gc-sections --dll --export-all-symbols --entry _$(IMAGE_ENTRY_POINT) --file-alignment 0x20 --section-alignment 0x20
+*_CYGGCCxASL_*_ASM_FLAGS = -c -x assembler -imacros AutoGen.h
+*_CYGGCCxASL_*_APP_FLAGS = -E -x assembler
+*_CYGGCCxASL_*_VFRPP_FLAGS = -x c -E -P -DVFRCOMPILE --include $(MODULE_NAME)StrDefs.h
+
+##################
+# ASL definitions
+##################
+*_CYGGCCxASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_CYGGCCxASL_*_ASL_FLAGS =
+*_CYGGCCxASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_CYGGCCxASL_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_CYGGCCxASL_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_CYGGCCxASL_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_CYGGCCxASL_IA32_CC_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCCxASL_IA32_SLINK_PATH = DEF(CYGWIN_BINIA32)ar
+*_CYGGCCxASL_IA32_DLINK_PATH = DEF(CYGWIN_BINIA32)ld
+*_CYGGCCxASL_IA32_ASM_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCCxASL_IA32_PP_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCCxASL_IA32_APP_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCCxASL_IA32_VFRPP_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCCxASL_IA32_ASLCC_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCCxASL_IA32_ASLPP_PATH = DEF(CYGWIN_BINIA32)gcc
+*_CYGGCCxASL_IA32_ASLDLINK_PATH = DEF(CYGWIN_BINIA32)ld
+*_CYGGCCxASL_IA32_RC_PATH = DEF(CYGWIN_BINIA32)objcopy
+
+*_CYGGCCxASL_IA32_CC_FLAGS = DEF(GCC_IA32_CC_FLAGS)
+*_CYGGCCxASL_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+
+##################
+# X64 definitions
+##################
+*_CYGGCCxASL_X64_CC_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCCxASL_X64_SLINK_PATH = DEF(CYGWIN_BINX64)ar
+*_CYGGCCxASL_X64_DLINK_PATH = DEF(CYGWIN_BINX64)ld
+*_CYGGCCxASL_X64_ASM_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCCxASL_X64_PP_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCCxASL_X64_APP_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCCxASL_X64_VFRPP_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCCxASL_X64_ASLCC_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCCxASL_X64_ASLPP_PATH = DEF(CYGWIN_BINX64)gcc
+*_CYGGCCxASL_X64_ASLDLINK_PATH = DEF(CYGWIN_BINX64)ld
+*_CYGGCCxASL_X64_RC_PATH = DEF(CYGWIN_BINX64)objcopy
+
+*_CYGGCCxASL_X64_CC_FLAGS = DEF(GCC_X64_CC_FLAGS)
+*_CYGGCCxASL_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+
+##################
+# IPF definitions
+##################
+*_CYGGCCxASL_IPF_CC_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCCxASL_IPF_SLINK_PATH = DEF(CYGWIN_BINIPF)ar
+*_CYGGCCxASL_IPF_DLINK_PATH = DEF(CYGWIN_BINIPF)ld
+*_CYGGCCxASL_IPF_ASLDLINK_PATH = DEF(CYGWIN_BINIPF)ld
+*_CYGGCCxASL_IPF_ASM_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCCxASL_IPF_PP_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCCxASL_IPF_VFRPP_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCCxASL_IPF_ASLCC_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCCxASL_IPF_ASLPP_PATH = DEF(CYGWIN_BINIPF)gcc
+*_CYGGCCxASL_IPF_OBJCOPY_PATH = DEF(CYGWIN_BINIPF)objcopy
+*_CYGGCCxASL_IPF_SYMRENAME_PATH = DEF(CYGWIN_BINIPF)objcopy
+*_CYGGCCxASL_IPF_RC_PATH = DEF(CYGWIN_BINIPF)objcopy
+
+*_CYGGCCxASL_IPF_CC_FLAGS = DEF(GCC_IPF_CC_FLAGS)
+*_CYGGCCxASL_IPF_DLINK_FLAGS = DEF(GCC_IPF_DLINK_FLAGS)
+*_CYGGCCxASL_IPF_OBJCOPY_FLAGS = DEF(GCC_IPF_OBJCOPY_FLAGS)
+*_CYGGCCxASL_IPF_SYMRENAME_FLAGS = DEF(GCC_IPF_SYMRENAME_FLAGS)
+*_CYGGCCxASL_IPF_RC_FLAGS = DEF(GCC_IPF_RC_FLAGS)
+
+##################
+# EBC definitions
+##################
+*_CYGGCCxASL_EBC_*_FAMILY = INTEL
+
+*_CYGGCCxASL_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_CYGGCCxASL_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_CYGGCCxASL_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+*_CYGGCCxASL_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_CYGGCCxASL_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_CYGGCCxASL_EBC_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_CYGGCCxASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_CYGGCCxASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_CYGGCCxASL_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Elf GCC - This configuration is used to compile on Linux boxes to produce elf
+# binaries.
+#
+####################################################################################
+# ELFGCC - Linux ELF GCC
+*_ELFGCC_*_*_FAMILY = GCC
+*_ELFGCC_*_MAKE_PATH = make
+
+*_ELFGCC_*_PP_FLAGS = -E -x assembler-with-cpp -include AutoGen.h
+*_ELFGCC_*_VFRPP_FLAGS = -x c -E -P -DVFRCOMPILE --include $(MODULE_NAME)StrDefs.h
+
+##################
+# ASL definitions
+##################
+*_ELFGCC_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+*_ELFGCC_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_ELFGCC_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+*_ELFGCC_*_ASLPP_FLAGS = -x c -E -P
+*_ELFGCC_*_ASLCC_FLAGS = -x c
+*_ELFGCC_*_ASLDLINK_FLAGS = DEF(GCC_DLINK_FLAGS_COMMON) --entry _ReferenceAcpiTable
+
+##################
+# IA32 definitions
+##################
+*_ELFGCC_IA32_OBJCOPY_PATH = DEF(ELFGCC_BIN)/objcopy
+*_ELFGCC_IA32_CC_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IA32_SLINK_PATH = DEF(ELFGCC_BIN)/ar
+*_ELFGCC_IA32_DLINK_PATH = DEF(ELFGCC_BIN)/ld
+*_ELFGCC_IA32_ASM_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IA32_PP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IA32_VFRPP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC32_IA32_ASLCC_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC32_IA32_ASLPP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC32_IA32_ASLDLINK_PATH = DEF(ELFGCC_BIN)/ld
+*_ELFGCC_IA32_RC_PATH = DEF(ELFGCC_BIN)/objcopy
+
+*_ELFGCC_IA32_CC_FLAGS = -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -c -include $(DEST_DIR_DEBUG)/AutoGen.h -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
+*_ELFGCC_IA32_SLINK_FLAGS =
+*_ELFGCC_IA32_DLINK_FLAGS = -melf_i386 -nostdlib --shared --entry $(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+#*_ELFGCC_IA32_DLINK_FLAGS = -melf_i386 -nostdlib -n -q -Ttext 0x220 --entry $(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT)
+*_ELFGCC_IA32_ASM_FLAGS = -m32 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h
+*_ELFGCC_IA32_PP_FLAGS = -m32 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_ELFGCC_IA32_VFRPP_FLAGS = -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+*_ELFGCC_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_ELFGCC_IA32_OBJCOPY_FLAGS =
+
+##################
+# X64 definitions
+##################
+*_ELFGCC_X64_CC_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_X64_ASLCC_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_X64_SLINK_PATH = DEF(ELFGCC_BIN)/ar
+*_ELFGCC_X64_DLINK_PATH = DEF(ELFGCC_BIN)/ld
+*_ELFGCC_X64_ASLDLINK_PATH = DEF(ELFGCC_BIN)/ld
+*_ELFGCC_X64_ASM_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_X64_PP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_X64_ASLPP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_X64_VFRPP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_X64_RC_PATH = DEF(ELFGCC_BIN)/objcopy
+
+*_ELFGCC_X64_CC_FLAGS = -Os -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -Wno-address -Wno-array-bounds -c -include AutoGen.h -D_EFI_P64
+*_ELFGCC_X64_DLINK_FLAGS = -nostdlib --shared --entry $(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+*_ELFGCC_X64_SLINK_FLAGS =
+*_ELFGCC_X64_ASM_FLAGS = -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h
+*_ELFGCC_X64_PP_FLAGS = -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_ELFGCC_X64_VFRPP_FLAGS = -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+*_ELFGCC_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+
+##################
+# IPF definitions
+##################
+*_ELFGCC_IPF_CC_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IPF_ASLCC_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IPF_SLINK_PATH = DEF(ELFGCC_BIN)/ar
+*_ELFGCC_IPF_DLINK_PATH = DEF(ELFGCC_BIN)/ld
+*_ELFGCC_IPF_ASLDLINK_PATH = DEF(ELFGCC_BIN)/ld
+*_ELFGCC_IPF_ASM_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IPF_PP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IPF_ASLPP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IPF_VFRPP_PATH = DEF(ELFGCC_BIN)/gcc
+*_ELFGCC_IPF_RC_PATH = DEF(ELFGCC_BIN)/objcopy
+
+*_ELFGCC_IPF_CC_FLAGS = -Os -fshort-wchar -Wall -Werror -c -include AutoGen.h -D_EFI_P64
+*_ELFGCC_IPF_DLINK_FLAGS = -nostdlib --shared --entry $(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+*_ELFGCC_IPF_SLINK_FLAGS =
+*_ELFGCC_IPF_ASM_FLAGS = -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h
+*_ELFGCC_IPF_PP_FLAGS = -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_ELFGCC_IPF_VFRPP_FLAGS = -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+*_ELFGCC_IPF_RC_FLAGS = DEF(GCC_IPF_RC_FLAGS)
+
+####################################################################################
+#
+# Intel(R) C++ Compiler Version 9.1
+#
+# IPF - Intel(R) C++ Compiler for Itanium(R)Version 9.1 Build 20060928 Package ID: W_CC_C_9.1.032
+# ASL - Intel ACPI Source Language Compiler
+#
+####################################################################################
+# ICC - Intel C Compiler V9.1
+*_ICC_*_*_FAMILY = INTEL
+
+*_ICC_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC_*_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_ICC_*_MAKE_FLAGS = /nologo
+*_ICC_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC_*_APP_FLAGS = /nologo /E /TC
+*_ICC_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+
+*_ICC_*_ASM16_PATH = DEF(MS_VS_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_ICC_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_ICC_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_ICC_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_ICC_*_ASLCC_FLAGS = DEF(ICC_WIN_ASLCC_FLAGS)
+*_ICC_*_ASLPP_FLAGS = DEF(ICC_WIN_ASLPP_FLAGS)
+*_ICC_*_ASLDLINK_FLAGS = DEF(ICC_WIN_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_ICC_IA32_CC_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICC_IA32_SLINK_PATH = DEF(ICC_BIN32)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC_IA32_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC_IA32_DLINK_PATH = DEF(ICC_BIN32)\xilink.exe
+*_ICC_IA32_PP_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICC_IA32_VFRPP_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICC_IA32_APP_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICC_IA32_ASM_PATH = DEF(MS_VS_BIN)\ml.exe
+*_ICC_IA32_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC_IA32_ASLCC_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICC_IA32_ASLPP_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICC_IA32_ASLDLINK_PATH = DEF(ICC_BIN32)\xilink.exe
+
+ DEBUG_ICC_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm
+RELEASE_ICC_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF
+NOOPT_ICC_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm /Od
+
+ DEBUG_ICC_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+RELEASE_ICC_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd
+NOOPT_ICC_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+
+ *_ICC_IA32_SLINK_FLAGS = /nologo
+ DEBUG_ICC_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_ICC_X64_CC_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICC_X64_SLINK_PATH = DEF(ICC_BINX64)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC_X64_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC_X64_DLINK_PATH = DEF(ICC_BINX64)\xilink.exe
+*_ICC_X64_PP_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICC_X64_VFRPP_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICC_X64_APP_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICC_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_ICC_X64_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC_X64_ASLCC_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICC_X64_ASLPP_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICC_X64_ASLDLINK_PATH = DEF(ICC_BINX64)\xilink.exe
+
+ DEBUG_ICC_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF
+RELEASE_ICC_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF
+NOOPT_ICC_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF /Od
+
+ DEBUG_ICC_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_ICC_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_ICC_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_ICC_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+ *_ICC_X64_SLINK_FLAGS = /nologo /LTCG
+
+
+##################
+# IPF definitions
+##################
+*_ICC_IPF_CC_PATH = DEF(ICC_BIN64)\icl.exe
+# icl.exe needs cl.exe from Visual Studio
+*_ICC_IPF_CC_DLL = DEF(MS_VS_BIN)
+*_ICC_IPF_SLINK_PATH = DEF(ICC_BIN64)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC_IPF_SLINK_DLL = DEF(MS_VS_BIN);DEF(MS_VS_DLL)
+*_ICC_IPF_DLINK_PATH = DEF(ICC_BIN64)\xilink.exe
+*_ICC_IPF_PP_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICC_IPF_VFRPP_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICC_IPF_APP_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICC_IPF_ASM_PATH = DEF(ICC_BIN64)\ias.exe
+*_ICC_IPF_ASLCC_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICC_IPF_ASLPP_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICC_IPF_ASLDLINK_PATH = DEF(ICC_BIN64)\xilink.exe
+
+ DEBUG_ICC_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Zi
+RELEASE_ICC_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF
+NOOPT_ICC_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Zi
+
+ DEBUG_ICC_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+RELEASE_ICC_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -F COFF32
+NOOPT_ICC_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+
+ DEBUG_ICC_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_ICC_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_ICC_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+ *_ICC_IPF_SLINK_FLAGS = /nologo
+
+##################
+# EBC definitions
+##################
+*_ICC_EBC_*_FAMILY = INTEL
+
+*_ICC_EBC_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_ICC_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_ICC_EBC_MAKE_FLAGS = /nologo
+*_ICC_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_ICC_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_ICC_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_ICC_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Intel(R) C++ Compiler Version 9.1
+#
+# IPF - Intel(R) C++ Compiler for Itanium(R)Version 9.1 Build 20060928 Package ID: W_CC_C_9.1.032
+# ASL - Microsoft ACPI Source Language Compiler
+#
+####################################################################################
+# ICCxASL - Intel C Compiler V9.1
+*_ICCxASL_*_*_FAMILY = INTEL
+
+*_ICCxASL_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICCxASL_*_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_ICCxASL_*_MAKE_FLAGS = /nologo
+*_ICCxASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICCxASL_*_APP_FLAGS = /nologo /E /TC
+*_ICCxASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+
+*_ICCxASL_*_ASM16_PATH = DEF(MS_VS_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_ICCxASL_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_ICCxASL_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_ICCxASL_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_ICCxASL_*_ASLCC_FLAGS = DEF(ICC_WIN_ASLCC_FLAGS)
+*_ICCxASL_*_ASLPP_FLAGS = DEF(ICC_WIN_ASLPP_FLAGS)
+*_ICCxASL_*_ASLDLINK_FLAGS = DEF(ICC_WIN_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_ICCxASL_IA32_CC_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICCxASL_IA32_SLINK_PATH = DEF(ICC_BIN32)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCxASL_IA32_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICCxASL_IA32_DLINK_PATH = DEF(ICC_BIN32)\xilink.exe
+*_ICCxASL_IA32_PP_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICCxASL_IA32_VFRPP_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICCxASL_IA32_APP_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICCxASL_IA32_ASM_PATH = DEF(MS_VS_BIN)\ml.exe
+*_ICCxASL_IA32_ASM_DLL = DEF(MS_VS_DLL)
+*_ICCxASL_IA32_ASLCC_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICCxASL_IA32_ASLPP_PATH = DEF(ICC_BIN32)\icl.exe
+*_ICCxASL_IA32_ASLDLINK_PATH = DEF(ICC_BIN32)\xilink.exe
+
+ DEBUG_ICCxASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm
+RELEASE_ICCxASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF
+NOOPT_ICCxASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm /Od
+
+ DEBUG_ICCxASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+RELEASE_ICCxASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd
+NOOPT_ICCxASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+
+ *_ICCxASL_IA32_SLINK_FLAGS = /nologo
+ DEBUG_ICCxASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICCxASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICCxASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_ICCxASL_X64_CC_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICCxASL_X64_SLINK_PATH = DEF(ICC_BINX64)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCxASL_X64_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICCxASL_X64_DLINK_PATH = DEF(ICC_BINX64)\xilink.exe
+*_ICCxASL_X64_PP_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICCxASL_X64_VFRPP_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICCxASL_X64_APP_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICCxASL_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_ICCxASL_X64_ASM_DLL = DEF(MS_VS_DLL)
+*_ICCxASL_X64_ASLCC_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICCxASL_X64_ASLPP_PATH = DEF(ICC_BINX64)\icl.exe
+*_ICCxASL_X64_ASLDLINK_PATH = DEF(ICC_BINX64)\xilink.exe
+
+ DEBUG_ICCxASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF
+RELEASE_ICCxASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF
+NOOPT_ICCxASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF /Od
+
+ DEBUG_ICCxASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_ICCxASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_ICCxASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_ICCxASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICCxASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICCxASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+ *_ICCxASL_X64_SLINK_FLAGS = /nologo /LTCG
+
+
+##################
+# IPF definitions
+##################
+*_ICCxASL_IPF_CC_PATH = DEF(ICC_BIN64)\icl.exe
+# icl.exe needs cl.exe from Visual Studio
+*_ICCxASL_IPF_CC_DLL = DEF(MS_VS_BIN)
+*_ICCxASL_IPF_SLINK_PATH = DEF(ICC_BIN64)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCxASL_IPF_SLINK_DLL = DEF(MS_VS_BIN);DEF(MS_VS_DLL)
+*_ICCxASL_IPF_DLINK_PATH = DEF(ICC_BIN64)\xilink.exe
+*_ICCxASL_IPF_PP_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICCxASL_IPF_VFRPP_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICCxASL_IPF_APP_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICCxASL_IPF_ASM_PATH = DEF(ICC_BIN64)\ias.exe
+*_ICCxASL_IPF_ASLCC_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICCxASL_IPF_ASLPP_PATH = DEF(ICC_BIN64)\icl.exe
+*_ICCxASL_IPF_ASLDLINK_PATH = DEF(ICC_BIN64)\xilink.exe
+
+ DEBUG_ICCxASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Zi
+RELEASE_ICCxASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF
+NOOPT_ICCxASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Zi
+
+ DEBUG_ICCxASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+RELEASE_ICCxASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -F COFF32
+NOOPT_ICCxASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+
+ DEBUG_ICCxASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_ICCxASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_ICCxASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+ *_ICCxASL_IPF_SLINK_FLAGS = /nologo
+
+##################
+# EBC definitions
+##################
+*_ICCxASL_EBC_*_FAMILY = INTEL
+
+*_ICCxASL_EBC_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICCxASL_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_ICCxASL_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_ICCxASL_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_ICCxASL_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_ICCxASL_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_ICCxASL_EBC_MAKE_FLAGS = /nologo
+*_ICCxASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_ICCxASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_ICCxASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICCxASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_ICCxASL_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+#
+# Intel(R) C++ Compiler Version 9.1 x86 (32-bit on 64-bit OS)
+#
+# ICCx86 - Intel(R) C++ Compiler for Itanium(R)Version 9.1 Build 20060928 Package ID: W_CC_C_9.1.032
+# ASL - Intel ACPI Source Language Compiler
+#
+####################################################################################
+# ICCx86 - Intel C Compiler V9.1
+*_ICCx86_*_*_FAMILY = INTEL
+
+*_ICCx86_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICCx86_*_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_ICCx86_*_MAKE_FLAGS = /nologo
+*_ICCx86_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICCx86_*_APP_FLAGS = /nologo /E /TC
+*_ICCx86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+
+*_ICCx86_*_ASM16_PATH = DEF(MS_VS_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_ICCx86_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_ICCx86_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_ICCx86_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_ICCx86_*_ASLCC_FLAGS = DEF(ICC_WIN_ASLCC_FLAGS)
+*_ICCx86_*_ASLPP_FLAGS = DEF(ICC_WIN_ASLPP_FLAGS)
+*_ICCx86_*_ASLDLINK_FLAGS = DEF(ICC_WIN_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_ICCx86_IA32_CC_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86_IA32_SLINK_PATH = DEF(ICC_BIN32x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCx86_IA32_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICCx86_IA32_DLINK_PATH = DEF(ICC_BIN32x86)\xilink.exe
+*_ICCx86_IA32_PP_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86_IA32_VFRPP_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86_IA32_APP_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86_IA32_ASM_PATH = DEF(MS_VS_BIN)\ml.exe
+*_ICCx86_IA32_ASM_DLL = DEF(MS_VS_DLL)
+*_ICCx86_IA32_ASLCC_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86_IA32_ASLPP_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86_IA32_ASLDLINK_PATH = DEF(ICC_BIN32x86)\xilink.exe
+
+ DEBUG_ICCx86_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm
+RELEASE_ICCx86_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF
+NOOPT_ICCx86_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm /Od
+
+ DEBUG_ICCx86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+RELEASE_ICCx86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd
+NOOPT_ICCx86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+
+ *_ICCx86_IA32_SLINK_FLAGS = /nologo
+ DEBUG_ICCx86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICCx86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICCx86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_ICCx86_X64_CC_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86_X64_SLINK_PATH = DEF(ICC_BINX64x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCx86_X64_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICCx86_X64_DLINK_PATH = DEF(ICC_BINX64x86)\xilink.exe
+*_ICCx86_X64_PP_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86_X64_VFRPP_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86_X64_APP_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_ICCx86_X64_ASM_DLL = DEF(MS_VS_DLL)
+*_ICCx86_X64_ASLCC_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86_X64_ASLPP_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86_X64_ASLDLINK_PATH = DEF(ICC_BINX64x86)\xilink.exe
+
+ DEBUG_ICCx86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF
+RELEASE_ICCx86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF
+NOOPT_ICCx86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF /Od
+
+ DEBUG_ICCx86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_ICCx86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_ICCx86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_ICCx86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICCx86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICCx86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+ *_ICCx86_X64_SLINK_FLAGS = /nologo /LTCG
+
+
+##################
+# IPF definitions
+##################
+*_ICCx86_IPF_CC_PATH = DEF(ICC_BIN64x86)\icl.exe
+# icl.exe needs cl.exe from Visual Studio
+*_ICCx86_IPF_CC_DLL = DEF(MS_VS_BIN)
+*_ICCx86_IPF_SLINK_PATH = DEF(ICC_BIN64x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCx86_IPF_SLINK_DLL = DEF(MS_VS_BIN);DEF(MS_VS_DLL)
+*_ICCx86_IPF_DLINK_PATH = DEF(ICC_BIN64x86)\xilink.exe
+*_ICCx86_IPF_PP_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86_IPF_VFRPP_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86_IPF_APP_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86_IPF_ASM_PATH = DEF(ICC_BIN64x86)\ias.exe
+*_ICCx86_IPF_ASLCC_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86_IPF_ASLPP_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86_IPF_ASLDLINK_PATH = DEF(ICC_BIN64x86)\xilink.exe
+
+ DEBUG_ICCx86_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Zi
+RELEASE_ICCx86_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF
+NOOPT_ICCx86_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Zi
+
+ DEBUG_ICCx86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+RELEASE_ICCx86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -F COFF32
+NOOPT_ICCx86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+
+ DEBUG_ICCx86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_ICCx86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_ICCx86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+ *_ICCx86_IPF_SLINK_FLAGS = /nologo
+
+##################
+# EBC definitions
+##################
+*_ICCx86_EBC_*_FAMILY = INTEL
+
+*_ICCx86_EBC_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICCx86_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICCx86_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICCx86_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICCx86_EBC_SLINK_PATH = DEF(EBC_BINx86)\link.exe
+*_ICCx86_EBC_DLINK_PATH = DEF(EBC_BINx86)\link.exe
+
+*_ICCx86_EBC_MAKE_FLAGS = /nologo
+*_ICCx86_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_ICCx86_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_ICCx86_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICCx86_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_ICCx86_EBC_DLINK_FLAGS = "C:\Program Files (x86)\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+#
+# Intel(R) C++ Compiler Version 9.1 x86 (32-bit on 64-bit OS)
+#
+# ICCx86xASL - Intel(R) C++ Compiler for Itanium(R)Version 9.1 Build 20060928 Package ID: W_CC_C_9.1.032
+# ASL - Microsoft ACPI Source Language Compiler
+#
+####################################################################################
+# ICCx86xASL - Intel C Compiler V9.1
+*_ICCx86xASL_*_*_FAMILY = INTEL
+
+*_ICCx86xASL_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICCx86xASL_*_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_ICCx86xASL_*_MAKE_FLAGS = /nologo
+*_ICCx86xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICCx86xASL_*_APP_FLAGS = /nologo /E /TC
+*_ICCx86xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+
+*_ICCx86ASL_*_ASM16_PATH = DEF(MS_VS_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_ICCx86xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_ICCx86xASL_*_ASL_FLAGS =
+*_ICCx86xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_ICCx86xASL_*_ASLCC_FLAGS = DEF(ICC_WIN_ASLCC_FLAGS)
+*_ICCx86xASL_*_ASLPP_FLAGS = DEF(ICC_WIN_ASLPP_FLAGS)
+*_ICCx86xASL_*_ASLDLINK_FLAGS = DEF(ICC_WIN_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_ICCx86xASL_IA32_CC_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86xASL_IA32_SLINK_PATH = DEF(ICC_BIN32x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCx86xASL_IA32_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICCx86xASL_IA32_DLINK_PATH = DEF(ICC_BIN32x86)\xilink.exe
+*_ICCx86xASL_IA32_PP_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86xASL_IA32_VFRPP_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86xASL_IA32_APP_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86xASL_IA32_ASM_PATH = DEF(MS_VS_BIN)\ml.exe
+*_ICCx86xASL_IA32_ASM_DLL = DEF(MS_VS_DLL)
+*_ICCx86xASL_IA32_ASLCC_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86xASL_IA32_ASLPP_PATH = DEF(ICC_BIN32x86)\icl.exe
+*_ICCx86xASL_IA32_ASLDLINK_PATH = DEF(ICC_BIN32x86)\xilink.exe
+
+ DEBUG_ICCx86xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm
+RELEASE_ICCx86xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF
+NOOPT_ICCx86xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm /Od
+
+ DEBUG_ICCx86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+RELEASE_ICCx86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd
+NOOPT_ICCx86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+
+ *_ICCx86xASL_IA32_SLINK_FLAGS = /nologo
+ DEBUG_ICCx86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICCx86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICCx86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_ICCx86xASL_X64_CC_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86xASL_X64_SLINK_PATH = DEF(ICC_BINX64x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCx86xASL_X64_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICCx86xASL_X64_DLINK_PATH = DEF(ICC_BINX64x86)\xilink.exe
+*_ICCx86xASL_X64_PP_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86xASL_X64_VFRPP_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86xASL_X64_APP_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86xASL_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_ICCx86xASL_X64_ASM_DLL = DEF(MS_VS_DLL)
+*_ICCx86xASL_X64_ASLCC_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86xASL_X64_ASLPP_PATH = DEF(ICC_BINX64x86)\icl.exe
+*_ICCx86xASL_X64_ASLDLINK_PATH = DEF(ICC_BINX64x86)\xilink.exe
+
+ DEBUG_ICCx86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF
+RELEASE_ICCx86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF
+NOOPT_ICCx86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF /Od
+
+ DEBUG_ICCx86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_ICCx86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_ICCx86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+
+ DEBUG_ICCx86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICCx86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICCx86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+ *_ICCx86xASL_X64_SLINK_FLAGS = /nologo /LTCG
+
+
+##################
+# IPF definitions
+##################
+*_ICCx86xASL_IPF_CC_PATH = DEF(ICC_BIN64x86)\icl.exe
+# icl.exe needs cl.exe from Visual Studio
+*_ICCx86xASL_IPF_CC_DLL = DEF(MS_VS_BIN)
+*_ICCx86xASL_IPF_SLINK_PATH = DEF(ICC_BIN64x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICCx86xASL_IPF_SLINK_DLL = DEF(MS_VS_BIN);DEF(MS_VS_DLL)
+*_ICCx86xASL_IPF_DLINK_PATH = DEF(ICC_BIN64x86)\xilink.exe
+*_ICCx86xASL_IPF_PP_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86xASL_IPF_VFRPP_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86xASL_IPF_APP_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86xASL_IPF_ASM_PATH = DEF(ICC_BIN64x86)\ias.exe
+*_ICCx86xASL_IPF_ASLCC_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86xASL_IPF_ASLPP_PATH = DEF(ICC_BIN64x86)\icl.exe
+*_ICCx86xASL_IPF_ASLDLINK_PATH = DEF(ICC_BIN64x86)\xilink.exe
+
+ DEBUG_ICCx86xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Zi
+RELEASE_ICCx86xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF
+NOOPT_ICCx86xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Zi
+
+ DEBUG_ICCx86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+RELEASE_ICCx86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -F COFF32
+NOOPT_ICCx86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+
+ DEBUG_ICCx86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_ICCx86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_ICCx86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+ *_ICCx86xASL_IPF_SLINK_FLAGS = /nologo
+
+##################
+# EBC definitions
+##################
+*_ICCx86xASL_EBC_*_FAMILY = INTEL
+
+*_ICCx86xASL_EBC_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICCx86xASL_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICCx86xASL_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICCx86xASL_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICCx86xASL_EBC_SLINK_PATH = DEF(EBC_BINx86)\link.exe
+*_ICCx86xASL_EBC_DLINK_PATH = DEF(EBC_BINx86)\link.exe
+
+*_ICCx86xASL_EBC_MAKE_FLAGS = /nologo
+*_ICCx86xASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_ICCx86xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_ICCx86xASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICCx86xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_ICCx86xASL_EBC_DLINK_FLAGS = "C:\Program Files (x86)\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+#
+# Intel(R) C++ Compiler Version 11.1
+# IA32 - Intel(R) C++ Compiler for applications running on IA32 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_ia32)
+# X64 - Intel(R) C++ Compiler for applications running on Intel(R) 64 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_intel64)
+# IPF - Intel(R) C++ Compiler for applications running on IA-64 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_ia64)
+# ASL - Intel ACPI Source Language Compiler
+#
+####################################################################################
+# ICC11 - Intel C Compiler V11.1
+*_ICC11_*_*_FAMILY = INTEL
+
+*_ICC11_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC11_*_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_ICC11_*_MAKE_FLAGS = /nologo
+*_ICC11_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC11_*_APP_FLAGS = /nologo /E /TC
+*_ICC11_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+
+*_ICC11_*_ASM16_PATH = DEF(MS_VS_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_ICC11_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_ICC11_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_ICC11_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_ICC11_*_ASLCC_FLAGS = DEF(ICC_WIN_ASLCC_FLAGS)
+*_ICC11_*_ASLPP_FLAGS = DEF(ICC_WIN_ASLPP_FLAGS)
+*_ICC11_*_ASLDLINK_FLAGS = DEF(ICC_WIN_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_ICC11_IA32_CC_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11_IA32_SLINK_PATH = DEF(ICC11_BIN32)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11_IA32_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC11_IA32_DLINK_PATH = DEF(ICC11_BIN32)\xilink.exe
+*_ICC11_IA32_PP_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11_IA32_VFRPP_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11_IA32_APP_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11_IA32_ASM_PATH = DEF(MS_VS_BIN)\ml.exe
+*_ICC11_IA32_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC11_IA32_ASLCC_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11_IA32_ASLPP_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11_IA32_ASLDLINK_PATH = DEF(ICC11_BIN32)\xilink.exe
+
+ DEBUG_ICC11_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm
+RELEASE_ICC11_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF
+NOOPT_ICC11_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm /Od
+
+ DEBUG_ICC11_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+RELEASE_ICC11_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd
+NOOPT_ICC11_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+ *_ICC11_IA32_SLINK_FLAGS = /nologo
+ DEBUG_ICC11_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC11_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC11_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_ICC11_X64_CC_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11_X64_SLINK_PATH = DEF(ICC11_BINX64)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11_X64_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC11_X64_DLINK_PATH = DEF(ICC11_BINX64)\xilink.exe
+*_ICC11_X64_PP_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11_X64_VFRPP_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11_X64_APP_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_ICC11_X64_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC11_X64_ASLCC_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11_X64_ASLPP_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11_X64_ASLDLINK_PATH = DEF(ICC11_BINX64)\xilink.exe
+
+ DEBUG_ICC11_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF
+RELEASE_ICC11_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF
+NOOPT_ICC11_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF /Od
+
+ DEBUG_ICC11_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_ICC11_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_ICC11_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+ DEBUG_ICC11_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC11_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC11_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+ *_ICC11_X64_SLINK_FLAGS = /nologo /LTCG
+
+
+##################
+# IPF definitions
+##################
+*_ICC11_IPF_CC_PATH = DEF(ICC11_BIN64)\icl.exe
+# icl.exe needs cl.exe from Visual Studio
+*_ICC11_IPF_CC_DLL = DEF(MS_VS_BIN)
+*_ICC11_IPF_SLINK_PATH = DEF(ICC11_BIN64)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11_IPF_SLINK_DLL = DEF(MS_VS_BIN);DEF(MS_VS_DLL)
+*_ICC11_IPF_DLINK_PATH = DEF(ICC11_BIN64)\xilink.exe
+*_ICC11_IPF_PP_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11_IPF_VFRPP_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11_IPF_APP_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11_IPF_ASM_PATH = DEF(ICC11_BIN64)\ias.exe
+*_ICC11_IPF_ASLCC_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11_IPF_ASLPP_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11_IPF_ASLDLINK_PATH = DEF(ICC11_BIN64)\xilink.exe
+
+ DEBUG_ICC11_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding /Zi
+RELEASE_ICC11_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding
+NOOPT_ICC11_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding /Zi
+
+ DEBUG_ICC11_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+RELEASE_ICC11_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -F COFF32
+NOOPT_ICC11_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+ DEBUG_ICC11_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_ICC11_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_ICC11_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+ *_ICC11_IPF_SLINK_FLAGS = /nologo
+
+##################
+# EBC definitions
+##################
+*_ICC11_EBC_*_FAMILY = INTEL
+
+*_ICC11_EBC_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC11_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC11_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC11_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC11_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_ICC11_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_ICC11_EBC_MAKE_FLAGS = /nologo
+*_ICC11_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_ICC11_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_ICC11_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC11_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_ICC11_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+####################################################################################
+#
+# Intel(R) C++ Compiler Version 11.1
+#
+# IA32 - Intel(R) C++ Compiler for applications running on IA32 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_ia32)
+# X64 - Intel(R) C++ Compiler for applications running on Intel(R) 64 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_intel64)
+# IPF - Intel(R) C++ Compiler for applications running on IA-64 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_ia64)
+# ASL - Microsoft ACPI Source Language Compiler
+#
+####################################################################################
+# ICC11xASL - Intel C Compiler V11.1
+*_ICC11xASL_*_*_FAMILY = INTEL
+
+*_ICC11xASL_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC11xASL_*_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_ICC11xASL_*_MAKE_FLAGS = /nologo
+*_ICC11xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC11xASL_*_APP_FLAGS = /nologo /E /TC
+*_ICC11xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+
+*_ICC11xASL_*_ASM16_PATH = DEF(MS_VS_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_ICC11xASL_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_ICC11xASL_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_ICC11xASL_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_ICC11xASL_*_ASLCC_FLAGS = DEF(ICC_WIN_ASLCC_FLAGS)
+*_ICC11xASL_*_ASLPP_FLAGS = DEF(ICC_WIN_ASLPP_FLAGS)
+*_ICC11xASL_*_ASLDLINK_FLAGS = DEF(ICC_WIN_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_ICC11xASL_IA32_CC_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11xASL_IA32_SLINK_PATH = DEF(ICC11_BIN32)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11xASL_IA32_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC11xASL_IA32_DLINK_PATH = DEF(ICC11_BIN32)\xilink.exe
+*_ICC11xASL_IA32_PP_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11xASL_IA32_VFRPP_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11xASL_IA32_APP_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11xASL_IA32_ASM_PATH = DEF(MS_VS_BIN)\ml.exe
+*_ICC11xASL_IA32_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC11xASL_IA32_ASLCC_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11xASL_IA32_ASLPP_PATH = DEF(ICC11_BIN32)\icl.exe
+*_ICC11xASL_IA32_ASLDLINK_PATH = DEF(ICC11_BIN32)\xilink.exe
+
+ DEBUG_ICC11xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm
+RELEASE_ICC11xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF
+NOOPT_ICC11xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm /Od
+
+ DEBUG_ICC11xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+RELEASE_ICC11xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd
+NOOPT_ICC11xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+ *_ICC11xASL_IA32_SLINK_FLAGS = /nologo
+ DEBUG_ICC11xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC11xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC11xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_ICC11xASL_X64_CC_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11xASL_X64_SLINK_PATH = DEF(ICC11_BINX64)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11xASL_X64_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC11xASL_X64_DLINK_PATH = DEF(ICC11_BINX64)\xilink.exe
+*_ICC11xASL_X64_PP_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11xASL_X64_VFRPP_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11xASL_X64_APP_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11xASL_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_ICC11xASL_X64_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC11xASL_X64_ASLCC_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11xASL_X64_ASLPP_PATH = DEF(ICC11_BINX64)\icl.exe
+*_ICC11xASL_X64_ASLDLINK_PATH = DEF(ICC11_BINX64)\xilink.exe
+
+ DEBUG_ICC11xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF
+RELEASE_ICC11xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF
+NOOPT_ICC11xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF /Od
+
+ DEBUG_ICC11xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_ICC11xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_ICC11xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+ DEBUG_ICC11xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC11xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC11xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+ *_ICC11xASL_X64_SLINK_FLAGS = /nologo /LTCG
+
+
+##################
+# IPF definitions
+##################
+*_ICC11xASL_IPF_CC_PATH = DEF(ICC11_BIN64)\icl.exe
+# icl.exe needs cl.exe from Visual Studio
+*_ICC11xASL_IPF_CC_DLL = DEF(MS_VS_BIN)
+*_ICC11xASL_IPF_SLINK_PATH = DEF(ICC11_BIN64)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11xASL_IPF_SLINK_DLL = DEF(MS_VS_BIN);DEF(MS_VS_DLL)
+*_ICC11xASL_IPF_DLINK_PATH = DEF(ICC11_BIN64)\xilink.exe
+*_ICC11xASL_IPF_PP_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11xASL_IPF_VFRPP_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11xASL_IPF_APP_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11xASL_IPF_ASM_PATH = DEF(ICC11_BIN64)\ias.exe
+*_ICC11xASL_IPF_ASLCC_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11xASL_IPF_ASLPP_PATH = DEF(ICC11_BIN64)\icl.exe
+*_ICC11xASL_IPF_ASLDLINK_PATH = DEF(ICC11_BIN64)\xilink.exe
+
+ DEBUG_ICC11xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding /Zi
+RELEASE_ICC11xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding
+NOOPT_ICC11xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding /Zi
+
+ DEBUG_ICC11xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+RELEASE_ICC11xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -F COFF32
+NOOPT_ICC11xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+
+ DEBUG_ICC11xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_ICC11xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_ICC11xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+ *_ICC11xASL_IPF_SLINK_FLAGS = /nologo
+
+##################
+# EBC definitions
+##################
+*_ICC11xASL_EBC_*_FAMILY = INTEL
+
+*_ICC11xASL_EBC_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC11xASL_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC11xASL_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC11xASL_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_ICC11xASL_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_ICC11xASL_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+
+*_ICC11xASL_EBC_MAKE_FLAGS = /nologo
+*_ICC11xASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_ICC11xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_ICC11xASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC11xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_ICC11xASL_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+#
+# Intel(R) C++ Compiler Version 11.1 x86 (32-bit on 64-bit OS)
+#
+# IA32 - Intel(R) C++ Compiler for applications running on IA32 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_ia32)
+# X64 - Intel(R) C++ Compiler for applications running on Intel(R) 64 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_intel64)
+# IPF - Intel(R) C++ Compiler for applications running on IA-64 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_ia64)
+# ASL - Intel ACPI Source Language Compiler
+#
+####################################################################################
+# ICC11x86 - Intel C Compiler V11.1
+*_ICC11x86_*_*_FAMILY = INTEL
+
+*_ICC11x86_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC11x86_*_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_ICC11x86_*_MAKE_FLAGS = /nologo
+*_ICC11x86_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC11x86_*_APP_FLAGS = /nologo /E /TC
+*_ICC11x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+
+*_ICC11x86_*_ASM16_PATH = DEF(MS_VS_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_ICC11x86_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_ICC11x86_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_ICC11x86_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_ICC11x86_*_ASLCC_FLAGS = DEF(ICC_WIN_ASLCC_FLAGS)
+*_ICC11x86_*_ASLPP_FLAGS = DEF(ICC_WIN_ASLPP_FLAGS)
+*_ICC11x86_*_ASLDLINK_FLAGS = DEF(ICC_WIN_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_ICC11x86_IA32_CC_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86_IA32_SLINK_PATH = DEF(ICC11_BIN32x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11x86_IA32_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC11x86_IA32_DLINK_PATH = DEF(ICC11_BIN32x86)\xilink.exe
+*_ICC11x86_IA32_PP_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86_IA32_VFRPP_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86_IA32_APP_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86_IA32_ASM_PATH = DEF(MS_VS_BIN)\ml.exe
+*_ICC11x86_IA32_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC11x86_IA32_ASLCC_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86_IA32_ASLPP_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86_IA32_ASLDLINK_PATH = DEF(ICC11_BIN32x86)\xilink.exe
+
+ DEBUG_ICC11x86_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm
+RELEASE_ICC11x86_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF
+NOOPT_ICC11x86_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm /Od
+ DEBUG_ICC11x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+RELEASE_ICC11x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd
+NOOPT_ICC11x86_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+ *_ICC11x86_IA32_SLINK_FLAGS = /nologo
+ DEBUG_ICC11x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC11x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC11x86_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_ICC11x86_X64_CC_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86_X64_SLINK_PATH = DEF(ICC11_BINX64x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11x86_X64_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC11x86_X64_DLINK_PATH = DEF(ICC11_BINX64x86)\xilink.exe
+*_ICC11x86_X64_PP_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86_X64_VFRPP_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86_X64_APP_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_ICC11x86_X64_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC11x86_X64_ASLCC_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86_X64_ASLPP_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86_X64_ASLDLINK_PATH = DEF(ICC11_BINX64x86)\xilink.exe
+
+ DEBUG_ICC11x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF
+RELEASE_ICC11x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF
+NOOPT_ICC11x86_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF /Od
+ DEBUG_ICC11x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_ICC11x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_ICC11x86_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+ DEBUG_ICC11x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC11x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC11x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+ *_ICC11x86_X64_SLINK_FLAGS = /nologo /LTCG
+
+
+##################
+# IPF definitions
+##################
+*_ICC11x86_IPF_CC_PATH = DEF(ICC11_BIN64x86)\icl.exe
+# icl.exe needs cl.exe from Visual Studio
+*_ICC11x86_IPF_CC_DLL = DEF(MS_VS_BIN)
+*_ICC11x86_IPF_SLINK_PATH = DEF(ICC11_BIN64x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11x86_IPF_SLINK_DLL = DEF(MS_VS_BIN);DEF(MS_VS_DLL)
+*_ICC11x86_IPF_DLINK_PATH = DEF(ICC11_BIN64x86)\xilink.exe
+*_ICC11x86_IPF_PP_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86_IPF_VFRPP_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86_IPF_APP_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86_IPF_ASM_PATH = DEF(ICC11_BIN64x86)\ias.exe
+*_ICC11x86_IPF_ASLCC_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86_IPF_ASLPP_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86_IPF_ASLDLINK_PATH = DEF(ICC11_BIN64x86)\xilink.exe
+
+ DEBUG_ICC11x86_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding /Zi
+RELEASE_ICC11x86_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding
+NOOPT_ICC11x86_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding /Zi
+
+ DEBUG_ICC11x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+RELEASE_ICC11x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -F COFF32
+NOOPT_ICC11x86_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+ DEBUG_ICC11x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_ICC11x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_ICC11x86_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+
+ *_ICC11x86_IPF_SLINK_FLAGS = /nologo
+
+##################
+# EBC definitions
+##################
+*_ICC11x86_EBC_*_FAMILY = INTEL
+
+*_ICC11x86_EBC_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC11x86_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICC11x86_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICC11x86_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICC11x86_EBC_SLINK_PATH = DEF(EBC_BINx86)\link.exe
+*_ICC11x86_EBC_DLINK_PATH = DEF(EBC_BINx86)\link.exe
+
+*_ICC11x86_EBC_MAKE_FLAGS = /nologo
+*_ICC11x86_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_ICC11x86_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_ICC11x86_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC11x86_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_ICC11x86_EBC_DLINK_FLAGS = "C:\Program Files (x86)\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+#
+# Intel(R) C++ Compiler Version 11.1 x86 (32-bit on 64-bit OS)
+#
+# IA32 - Intel(R) C++ Compiler for applications running on IA32 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_ia32)
+# X64 - Intel(R) C++ Compiler for applications running on Intel(R) 64 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_intel64)
+# IPF - Intel(R) C++ Compiler for applications running on IA-64 (Version 11.1 Build 072 Package ID: w_cproc_p_11.1.072_ia64)
+# ASL - Microsoft ACPI Source Language Compiler
+#
+####################################################################################
+# ICC11x86xASL - Intel C Compiler V11.1
+*_ICC11x86xASL_*_*_FAMILY = INTEL
+
+*_ICC11x86xASL_*_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC11x86xASL_*_RC_PATH = DEF(MS_VS_BIN)\rc.exe
+
+*_ICC11x86xASL_*_MAKE_FLAGS = /nologo
+*_ICC11x86xASL_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC11x86xASL_*_APP_FLAGS = /nologo /E /TC
+*_ICC11x86xASL_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+
+*_ICC11x86xASL_*_ASM16_PATH = DEF(MS_VS_BIN)\ml.exe
+
+##################
+# ASL definitions
+##################
+*_ICC11x86xASL_*_ASL_PATH = DEF(WIN_ASL_BIN)
+*_ICC11x86xASL_*_ASL_FLAGS =
+*_ICC11x86xASL_*_ASL_OUTFLAGS = DEF(MS_ASL_OUTFLAGS)
+*_ICC11x86xASL_*_ASLCC_FLAGS = DEF(ICC_WIN_ASLCC_FLAGS)
+*_ICC11x86xASL_*_ASLPP_FLAGS = DEF(ICC_WIN_ASLPP_FLAGS)
+*_ICC11x86xASL_*_ASLDLINK_FLAGS = DEF(ICC_WIN_ASLDLINK_FLAGS)
+
+##################
+# IA32 definitions
+##################
+*_ICC11x86xASL_IA32_CC_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86xASL_IA32_SLINK_PATH = DEF(ICC11_BIN32x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11x86xASL_IA32_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC11x86xASL_IA32_DLINK_PATH = DEF(ICC11_BIN32x86)\xilink.exe
+*_ICC11x86xASL_IA32_PP_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86xASL_IA32_VFRPP_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86xASL_IA32_APP_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86xASL_IA32_ASM_PATH = DEF(MS_VS_BIN)\ml.exe
+*_ICC11x86xASL_IA32_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC11x86xASL_IA32_ASLCC_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86xASL_IA32_ASLPP_PATH = DEF(ICC11_BIN32x86)\icl.exe
+*_ICC11x86xASL_IA32_ASLDLINK_PATH = DEF(ICC11_BIN32x86)\xilink.exe
+
+ DEBUG_ICC11x86xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm
+RELEASE_ICC11x86xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /O1ib2 /GL /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF
+NOOPT_ICC11x86xASL_IA32_CC_FLAGS = /nologo /c /WX /W4 /Gy /Gs32768 /D UNICODE /DEFI_FIRMWARE_VENDOR=L\"INTEL\" /FIAutoGen.h /EHs-c- /GF /Zi /Gm /Od
+
+ DEBUG_ICC11x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+RELEASE_ICC11x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd
+NOOPT_ICC11x86xASL_IA32_ASM_FLAGS = /nologo /c /WX /W3 /Zd /Zi
+ *_ICC11x86xASL_IA32_SLINK_FLAGS = /nologo
+ DEBUG_ICC11x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC11x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC11x86xASL_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# X64 definitions
+##################
+*_ICC11x86xASL_X64_CC_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86xASL_X64_SLINK_PATH = DEF(ICC11_BINX64x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11x86xASL_X64_SLINK_DLL = DEF(MS_VS_BIN)
+*_ICC11x86xASL_X64_DLINK_PATH = DEF(ICC11_BINX64x86)\xilink.exe
+*_ICC11x86xASL_X64_PP_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86xASL_X64_VFRPP_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86xASL_X64_APP_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86xASL_X64_ASM_PATH = DEF(WINDDK_BINX64)\ml64.exe
+*_ICC11x86xASL_X64_ASM_DLL = DEF(MS_VS_DLL)
+*_ICC11x86xASL_X64_ASLCC_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86xASL_X64_ASLPP_PATH = DEF(ICC11_BINX64x86)\icl.exe
+*_ICC11x86xASL_X64_ASLDLINK_PATH = DEF(ICC11_BINX64x86)\xilink.exe
+
+ DEBUG_ICC11x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF
+RELEASE_ICC11x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF
+NOOPT_ICC11x86xASL_X64_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /Gy /FI$(DEST_DIR_DEBUG)/AutoGen.h /Zi /Gm /EHs-c- /GF /Od
+
+ DEBUG_ICC11x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_ICC11x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_ICC11x86xASL_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+ DEBUG_ICC11x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_ICC11x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_ICC11x86xASL_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+ *_ICC11x86xASL_X64_SLINK_FLAGS = /nologo /LTCG
+
+
+##################
+# IPF definitions
+##################
+*_ICC11x86xASL_IPF_CC_PATH = DEF(ICC11_BIN64x86)\icl.exe
+# icl.exe needs cl.exe from Visual Studio
+*_ICC11x86xASL_IPF_CC_DLL = DEF(MS_VS_BIN)
+*_ICC11x86xASL_IPF_SLINK_PATH = DEF(ICC11_BIN64x86)\xilib.exe
+# xilib.exe needs lib.exe from Visual Studio
+*_ICC11x86xASL_IPF_SLINK_DLL = DEF(MS_VS_BIN);DEF(MS_VS_DLL)
+*_ICC11x86xASL_IPF_DLINK_PATH = DEF(ICC11_BIN64x86)\xilink.exe
+*_ICC11x86xASL_IPF_PP_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86xASL_IPF_VFRPP_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86xASL_IPF_APP_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86xASL_IPF_ASM_PATH = DEF(ICC11_BIN64x86)\ias.exe
+*_ICC11x86xASL_IPF_ASLCC_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86xASL_IPF_ASLPP_PATH = DEF(ICC11_BIN64x86)\icl.exe
+*_ICC11x86xASL_IPF_ASLDLINK_PATH = DEF(ICC11_BIN64x86)\xilink.exe
+
+ DEBUG_ICC11x86xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding /Zi
+RELEASE_ICC11x86xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding
+NOOPT_ICC11x86xASL_IPF_CC_FLAGS = /nologo /c /WX /W4 /GX /Gy /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /QIA64_fr32 /GF /Qfreestanding /Zi
+ DEBUG_ICC11x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+RELEASE_ICC11x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -F COFF32
+NOOPT_ICC11x86xASL_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W3 -d debug -F COFF32
+ DEBUG_ICC11x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+RELEASE_ICC11x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb
+NOOPT_ICC11x86xASL_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF,ICF /IGNORE:4001 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEST_DIR_DEBUG)/$(BASE_NAME).pdb /DEBUG
+ *_ICC11x86xASL_IPF_SLINK_FLAGS = /nologo
+
+##################
+# EBC definitions
+##################
+*_ICC11x86xASL_EBC_*_FAMILY = INTEL
+
+*_ICC11x86xASL_EBC_MAKE_PATH = DEF(MS_VS_BIN)\nmake.exe
+*_ICC11x86xASL_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICC11x86xASL_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICC11x86xASL_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
+*_ICC11x86xASL_EBC_SLINK_PATH = DEF(EBC_BINx86)\link.exe
+*_ICC11x86xASL_EBC_DLINK_PATH = DEF(EBC_BINx86)\link.exe
+
+*_ICC11x86xASL_EBC_MAKE_FLAGS = /nologo
+*_ICC11x86xASL_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_ICC11x86xASL_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_ICC11x86xASL_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_ICC11x86xASL_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_ICC11x86xASL_EBC_DLINK_FLAGS = "C:\Program Files (x86)\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+#
+# MYTOOLS
+# IA32 - Microsoft Visual Studio 2008 Team Suite
+# X64 - Microsoft Visual Studio 2008 Team Suite
+# IPF - Microsoft Windows DDK 3790.1830
+# EBC - Intel EFI Byte Code Compiler
+#
+####################################################################################
+# MYTOOLS - Settings compatible with previous versions of tools_def.template
+*_MYTOOLS_*_*_FAMILY = MSFT
+
+##################
+# ASL definitions
+##################
+*_MYTOOLS_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN)
+*_MYTOOLS_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS)
+*_MYTOOLS_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS)
+*_MYTOOLS_*_ASLCC_FLAGS = DEF(MSFT_ASLCC_FLAGS)
+*_MYTOOLS_*_ASLPP_FLAGS = DEF(MSFT_ASLPP_FLAGS)
+*_MYTOOLS_*_ASLDLINK_FLAGS = DEF(MSFT_ASLDLINK_FLAGS)
+
+
+*_MYTOOLS_*_MAKE_FLAGS = /nologo
+*_MYTOOLS_*_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_MYTOOLS_*_APP_FLAGS = /nologo /E /TC
+*_MYTOOLS_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_MYTOOLS_*_SLINK_FLAGS = /nologo /LTCG
+
+*_MYTOOLS_*_ASM16_PATH = DEF(VS2008_BIN)\ml.exe
+
+##################
+# IA32 definitions
+##################
+*_MYTOOLS_IA32_*_DLL = DEF(VS2008_DLL)
+
+*_MYTOOLS_IA32_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
+*_MYTOOLS_IA32_CC_PATH = DEF(VS2008_BIN)\cl.exe
+*_MYTOOLS_IA32_SLINK_PATH = DEF(VS2008_BIN)\lib.exe
+*_MYTOOLS_IA32_DLINK_PATH = DEF(VS2008_BIN)\link.exe
+*_MYTOOLS_IA32_PP_PATH = DEF(VS2008_BIN)\cl.exe
+*_MYTOOLS_IA32_VFRPP_PATH = DEF(VS2008_BIN)\cl.exe
+*_MYTOOLS_IA32_APP_PATH = DEF(VS2008_BIN)\cl.exe
+*_MYTOOLS_IA32_ASM_PATH = DEF(VS2008_BIN)\ml.exe
+*_MYTOOLS_IA32_ASLCC_PATH = DEF(VS2008_BIN)\cl.exe
+*_MYTOOLS_IA32_ASLPP_PATH = DEF(VS2008_BIN)\cl.exe
+*_MYTOOLS_IA32_ASLDLINK_PATH = DEF(VS2008_BIN)\link.exe
+*_MYTOOLS_IA32_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+ DEBUG_MYTOOLS_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_MYTOOLS_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_MYTOOLS_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /Gy /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+ DEBUG_MYTOOLS_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+RELEASE_MYTOOLS_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd
+NOOPT_MYTOOLS_IA32_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+ DEBUG_MYTOOLS_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+RELEASE_MYTOOLS_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_MYTOOLS_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+
+##################
+# x64 definitions
+##################
+*_MYTOOLS_X64_*_DLL = DEF(VS2008_DLL)
+
+*_MYTOOLS_X64_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
+*_MYTOOLS_X64_CC_PATH = DEF(VS2008_BINX64)\cl.exe
+*_MYTOOLS_X64_SLINK_PATH = DEF(VS2008_BINX64)\lib.exe
+*_MYTOOLS_X64_DLINK_PATH = DEF(VS2008_BINX64)\link.exe
+*_MYTOOLS_X64_PP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_MYTOOLS_X64_VFRPP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_MYTOOLS_X64_APP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_MYTOOLS_X64_ASM_PATH = DEF(VS2008_BINX64)\ml64.exe
+*_MYTOOLS_X64_ASLCC_PATH = DEF(VS2008_BINX64)\cl.exe
+*_MYTOOLS_X64_ASLPP_PATH = DEF(VS2008_BINX64)\cl.exe
+*_MYTOOLS_X64_ASLDLINK_PATH = DEF(VS2008_BINX64)\link.exe
+*_MYTOOLS_X64_RC_PATH = DEF(WINSDK_BIN)\rc.exe
+
+ DEBUG_MYTOOLS_X64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+RELEASE_MYTOOLS_X64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
+NOOPT_MYTOOLS_X64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /Gy /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od
+ DEBUG_MYTOOLS_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+RELEASE_MYTOOLS_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd
+NOOPT_MYTOOLS_X64_ASM_FLAGS = /nologo /c /WX /W3 /Cx /Zd /Zi
+ DEBUG_MYTOOLS_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+RELEASE_MYTOOLS_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
+NOOPT_MYTOOLS_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
+
+##################
+# IPF definitions
+##################
+*_MYTOOLS_IPF_MAKE_PATH = DEF(WINDDK_BIN32)\nmake.exe
+*_MYTOOLS_IPF_CC_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_MYTOOLS_IPF_SLINK_PATH = DEF(WINDDK_BIN64)\lib.exe
+*_MYTOOLS_IPF_DLINK_PATH = DEF(WINDDK_BIN64)\link.exe
+*_MYTOOLS_IPF_PP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_MYTOOLS_IPF_VFRPP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_MYTOOLS_IPF_APP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_MYTOOLS_IPF_ASM_PATH = DEF(WINDDK_BIN64)\ias.exe
+*_MYTOOLS_IPF_ASLCC_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_MYTOOLS_IPF_ASLPP_PATH = DEF(WINDDK_BIN64)\cl.exe
+*_MYTOOLS_IPF_ASLDLINK_PATH = DEF(WINDDK_BIN64)\link.exe
+*_MYTOOLS_IPF_RC_PATH = DEF(WINDDK_BIN32)\rc.exe
+
+ *_MYTOOLS_IPF_ASM_OUTPUT = "-o "
+ DEBUG_MYTOOLS_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gy /Ox /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zx /QIPF_fr32 /Zi
+RELEASE_MYTOOLS_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gy /Ox /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zx /QIPF_fr32
+NOOPT_MYTOOLS_IPF_CC_FLAGS = /nologo /c /WX /GS- /X /W4 /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zx /QIPF_fr32 /Zi /Od
+ DEBUG_MYTOOLS_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+RELEASE_MYTOOLS_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4
+NOOPT_MYTOOLS_IPF_ASM_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -d debug
+ DEBUG_MYTOOLS_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF /OPT:ICF=10 /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+RELEASE_MYTOOLS_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF /OPT:ICF=10 /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+NOOPT_MYTOOLS_IPF_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /LTCG /DLL /OPT:REF /OPT:ICF=10 /IGNORE:4001 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:IA64 /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MAP:$(DEST_DIR_DEBUG)/$(BASE_NAME).map /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb /DEBUG
+ *_MYTOOLS_IPF_SLINK_FLAGS = /nologo /LTCG
+
+##################
+# EBC definitions
+##################
+*_MYTOOLS_EBC_*_FAMILY = INTEL
+
+*_MYTOOLS_EBC_MAKE_PATH = DEF(VS2005_BIN)\nmake.exe
+*_MYTOOLS_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
+*_MYTOOLS_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
+*_MYTOOLS_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
+*_MYTOOLS_EBC_SLINK_PATH = DEF(EBC_BIN)\link.exe
+*_MYTOOLS_EBC_DLINK_PATH = DEF(EBC_BIN)\link.exe
+*_MYTOOLS_EBC_RC_PATH = DEF(VS2005_BIN)\rc.exe
+
+*_MYTOOLS_EBC_MAKE_FLAGS = /nologo
+*_MYTOOLS_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+*_MYTOOLS_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
+*_MYTOOLS_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
+*_MYTOOLS_EBC_SLINK_FLAGS = /lib /NOLOGO /MACHINE:EBC
+*_MYTOOLS_EBC_DLINK_FLAGS = "C:\Program Files\Intel\EBC\Lib\EbcLib.lib" /NOLOGO /NODEFAULTLIB /MACHINE:EBC /OPT:REF /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MAP /ALIGN:32 /DRIVER
+
+
+####################################################################################
+#
+# Xcode Support for building on Mac OS X (Snow Leopard)
+#
+####################################################################################
+# XCODE32 - Xcode 3.2 Tools (Snow Leopard)
+*_XCODE32_*_*_FAMILY = GCC
+*_XCODE32_*_*_BUILDRULEFAMILY = XCODE
+
+
+*_XCODE32_*_ASL_PATH = /usr/bin/iasl
+
+*_XCODE32_*_MAKE_PATH = make
+
+*_XCODE32_*_DSYMUTIL_PATH = /usr/bin/dsymutil
+
+# This tool needs to be installed seperatly from Xcode 3.2
+*_XCODE32_*_MTOC_PATH = /usr/local/bin/mtoc
+
+ DEBUG_XCODE32_*_MTOC_FLAGS = -align 0x20 -d $(DEBUG_DIR)/$(MODULE_NAME).dll
+RELEASE_XCODE32_*_MTOC_FLAGS = -align 0x20
+
+##################
+# IA32 definitions
+##################
+*_XCODE32_IA32_CC_PATH = gcc
+*_XCODE32_IA32_SLINK_PATH = libtool
+*_XCODE32_IA32_DLINK_PATH = ld
+*_XCODE32_IA32_ASM_PATH = as
+*_XCODE32_IA32_PP_PATH = gcc
+*_XCODE32_IA32_VFRPP_PATH = gcc
+*_XCODE32_IA32_ASL_PATH = iasl
+*_XCODE32_IA32_ASLCC_PATH = gcc
+*_XCODE32_IA32_ASLPP_PATH = gcc
+*_XCODE32_IA32_ASLDLINK_PATH = ld
+
+ DEBUG_XCODE32_IA32_DLINK_FLAGS = -arch i386 -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -all_load -dead_strip -seg1addr 0x240 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+RELEASE_XCODE32_IA32_DLINK_FLAGS = -arch i386 -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -all_load -dead_strip -seg1addr 0x220 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+*_XCODE32_IA32_SLINK_FLAGS = -static -o
+ DEBUG_XCODE32_IA32_ASM_FLAGS = -arch i386 -g
+RELEASE_XCODE32_IA32_ASM_FLAGS = -arch i386
+*_XCODE32_IA32_PP_FLAGS = -arch i386 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_XCODE32_IA32_VFRPP_FLAGS = -arch i386 -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+ DEBUG_XCODE32_IA32_CC_FLAGS = -arch i386 -save-temps -g -O0 -combine -mms-bitfields -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -c -include AutoGen.h -mdynamic-no-pic -fno-stack-protector
+RELEASE_XCODE32_IA32_CC_FLAGS = -arch i386 -Oz -combine -mms-bitfields -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -fomit-frame-pointer -c -include AutoGen.h -mdynamic-no-pic -fno-stack-protector
+
+*_XCODE32_IA32_ASLCC_FLAGS = -arch i386 -x c -save-temps -g -O0 -mms-bitfields -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -c -include AutoGen.h -mdynamic-no-pic
+*_XCODE32_IA32_ASLDLINK_FLAGS = -arch i386 -e _main -preload -segalign 0x20 -pie -seg1addr 0x220 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+*_XCODE32_IA32_ASLPP_FLAGS = -arch i386 -x c -E
+*_XCODE32_IA32_ASL_FLAGS =
+
+##################
+# X64 definitions - still a work in progress. This tool chain does not produce
+# the correct ABI, it is just used to compile the code....
+##################
+*_XCODE32_X64_CC_PATH = gcc
+*_XCODE32_X64_SLINK_PATH = libtool
+*_XCODE32_X64_DLINK_PATH = ld
+*_XCODE32_X64_ASM_PATH = as
+*_XCODE32_X64_PP_PATH = gcc
+*_XCODE32_X64_VFRPP_PATH = gcc
+*_XCODE32_X64_ASL_PATH = iasl
+*_XCODE32_X64_ASLCC_PATH = gcc
+*_XCODE32_X64_ASLPP_PATH = gcc
+*_XCODE32_X64_ASLDLINK_PATH = ld
+
+*_XCODE32_X64_DLINK_FLAGS = -arch x86_64 -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -seg1addr 0x240 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+*_XCODE32_X64_SLINK_FLAGS = -static -o
+
+ DEBUG_XCODE32_X64_ASM_FLAGS = -arch x86_64 -g
+RELEASE_XCODE32_X64_ASM_FLAGS = -arch x86_64
+*_XCODE32_X64_PP_FLAGS = -arch x86_64 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_XCODE32_X64_VFRPP_FLAGS = -arch x86_64 -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+
+ DEBUG_XCODE32_X64_CC_FLAGS = -arch x86_64 -save-temps -g -O0 -combine -mms-bitfields -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -Wno-address -fomit-frame-pointer -static -c -include AutoGen.h -fno-stack-protector
+RELEASE_XCODE32_X64_CC_FLAGS = -arch x86_64 -Oz -combine -mms-bitfields -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -Wno-address -fomit-frame-pointer -static -c -include AutoGen.h -fno-stack-protector
+
+##################
+# ARM definitions - (Assumes iPhone SDK installed on Snow Leopard)
+##################
+
+*_XCODE32_ARM_ARCHCC_FLAGS = -arch armv7 -march=armv7 -mthumb
+*_XCODE32_ARM_ARCHASM_FLAGS = -arch armv7
+*_XCODE32_ARM_ARCHDLINK_FLAGS = -arch armv7
+*_XCODE32_ARM_PLATFORM_FLAGS =
+
+*_XCODE32_ARM_CC_PATH = DEF(IPHONE_TOOLS)/usr/bin/gcc
+*_XCODE32_ARM_SLINK_PATH = DEF(IPHONE_TOOLS)/usr/bin/libtool
+*_XCODE32_ARM_DLINK_PATH = ld
+*_XCODE32_ARM_ASM_PATH = DEF(IPHONE_TOOLS)/usr/bin/as
+*_XCODE32_ARM_PP_PATH = DEF(IPHONE_TOOLS)/usr/bin/gcc
+*_XCODE32_ARM_VFRPP_PATH = DEF(IPHONE_TOOLS)/usr/bin/gcc
+
+ DEBUG_XCODE32_ARM_DLINK_FLAGS = $(ARCHDLINK_FLAGS) -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -all_load -dead_strip -seg1addr 0x220 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+RELEASE_XCODE32_ARM_DLINK_FLAGS = $(ARCHDLINK_FLAGS) -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -all_load -dead_strip -seg1addr 0x220 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+
+*_XCODE32_ARM_SLINK_FLAGS = -static -o
+
+ DEBUG_XCODE32_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) -g
+RELEASE_XCODE32_ARM_ASM_FLAGS = $(ARCHASM_FLAGS)
+*_XCODE32_ARM_PP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_XCODE32_ARM_VFRPP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+
+ DEBUG_XCODE32_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -mthumb-interwork -g -Oz -mabi=aapcs -mapcs -fno-short-enums -save-temps -combine -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -fomit-frame-pointer -c -include AutoGen.h -fno-stack-protector
+RELEASE_XCODE32_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -mthumb-interwork -Oz -mabi=aapcs -mapcs -fno-short-enums -save-temps -combine -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -fomit-frame-pointer -c -include AutoGen.h -fno-stack-protector
+
+
+####################################################################################
+#
+# Clang Support for building on Mac OS X
+#
+####################################################################################
+# CLANG - clang that produce Mach-O with EFI x86_64 ABI
+*_XCLANG_*_*_FAMILY = GCC
+*_XCLANG_*_*_BUILDRULEFAMILY = XCODE
+
+*_XCLANG_*_ASL_PATH = /usr/bin/iasl
+
+*_XCLANG_*_MAKE_PATH = make
+*_XCLANG_*_DSYMUTIL_PATH = /usr/bin/dsymutil
+
+ *_*_*_MTOC_PATH = /usr/local/bin/mtoc
+
+ DEBUG_XCLANG_*_MTOC_FLAGS = -align 0x20 -d $(DEBUG_DIR)/$(MODULE_NAME).dll
+RELEASE_XCLANG_*_MTOC_FLAGS = -align 0x20
+
+
+*_XCLANG_*_CC_PATH = DEF(CLANG_BIN)clang
+*_XCLANG_*_SLINK_PATH = libtool
+*_XCLANG_*_DLINK_PATH = ld
+*_XCLANG_*_ASM_PATH = as
+*_XCLANG_*_PP_PATH = DEF(CLANG_BIN)clang
+*_XCLANG_*_VFRPP_PATH = DEF(CLANG_BIN)clang
+*_XCLANG_*_ASL_PATH = iasl
+*_XCLANG_*_ASLCC_PATH = DEF(CLANG_BIN)clang
+*_XCLANG_*_ASLPP_PATH = DEF(CLANG_BIN)clang
+*_XCLANG_*_ASLDLINK_PATH = ld
+
+####################
+# IA-32 definitions
+####################
+ DEBUG_XCLANG_IA32_DLINK_FLAGS = -arch i386 -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -all_load -dead_strip -seg1addr 0x240 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+RELEASE_XCLANG_IA32_DLINK_FLAGS = -arch i386 -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -all_load -dead_strip -seg1addr 0x220 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+*_XCLANG_IA32_SLINK_FLAGS = -static -o
+ DEBUG_XCLANG_IA32_ASM_FLAGS = -arch i386 -g
+RELEASE_XCLANG_IA32_ASM_FLAGS = -arch i386
+
+
+ DEBUG_XCLANG_IA32_CC_FLAGS = -arch i386 -c -g -O0 -Wall -Werror -include AutoGen.h -fno-stack-protector -fno-builtin -fshort-wchar -mdynamic-no-pic -mno-sse -mno-mmx -Wno-empty-body -Wno-pointer-sign -Wno-unused-function -Wno-unused-value -Wno-missing-braces -Wno-tautological-compare -Wreturn-type -Wno-unused-variable -fasm-blocks -mms-bitfields -msoft-float -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang
+RELEASE_XCLANG_IA32_CC_FLAGS = -arch i386 -c -Os -Wall -Werror -include AutoGen.h -fno-stack-protector -fno-builtin -fshort-wchar -mdynamic-no-pic -mno-sse -mno-mmx -Wno-empty-body -Wno-pointer-sign -Wno-unused-function -Wno-unused-value -Wno-missing-braces -Wno-tautological-compare -Wreturn-type -Wno-unused-variable -fasm-blocks -mms-bitfields -msoft-float -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang
+
+
+##################
+# X64 definitions
+##################
+ DEBUG_XCLANG_X64_DLINK_FLAGS = -arch x86_64 -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -all_load -dead_strip -seg1addr 0x240 -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+RELEASE_XCLANG_X64_DLINK_FLAGS = -arch x86_64 -u _$(IMAGE_ENTRY_POINT) -e _$(IMAGE_ENTRY_POINT) -preload -segalign 0x20 -pie -all_load -dead_strip -seg1addr 0x220 -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+*_XCLANG_X64_SLINK_FLAGS = -static -o
+ DEBUG_XCLANG_X64_ASM_FLAGS = -arch x86_64 -g
+RELEASE_XCLANG_X64_ASM_FLAGS = -arch x86_64
+*_XCLANG_*_PP_FLAGS = -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_XCLANG_*_VFRPP_FLAGS = -x c -E -P -DVFRCOMPILE -include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+
+
+ DEBUG_XCLANG_X64_CC_FLAGS = -ccc-host-triple x86_64-pc-win32-macho -c -g -O0 -Wall -Werror -include AutoGen.h -fno-stack-protector -fno-builtin -fshort-wchar -mdynamic-no-pic -Wno-empty-body -Wno-pointer-sign -Wno-unused-function -Wno-unused-value -Wno-missing-braces -Wno-tautological-compare -Wreturn-type -Wno-unused-variable -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang
+RELEASE_XCLANG_X64_CC_FLAGS = -ccc-host-triple x86_64-pc-win32-macho -c -Os -Wall -Werror -include AutoGen.h -fno-stack-protector -fno-builtin -fshort-wchar -mdynamic-no-pic -Wno-empty-body -Wno-pointer-sign -Wno-unused-function -Wno-unused-value -Wno-missing-braces -Wno-tautological-compare -Wreturn-type -Wno-unused-variable -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang
+*_XCLANG_*_ASLCC_FLAGS = -x c -save-temps -g -O0 -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -c -include AutoGen.h -mdynamic-no-pic
+*_XCLANG_*_ASLDLINK_FLAGS = -e _main -preload -segalign 0x20 -pie -seg1addr 0x240 -read_only_relocs suppress -map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+*_XCLANG_*_ASLPP_FLAGS = -x c -E
+*_XCLANG_*_ASL_FLAGS =
+
+####################################################################################
+#
+# RVCT Common
+#
+####################################################################################
+
+DEFINE RVCT_ALL_CC_FLAGS = --c90 -c --no_autoinline --asm --gnu --apcs /interwork --signed_chars --no_unaligned_access --split_sections --enum_is_int --preinclude AutoGen.h --diag_warning 167 --diag_style=ide
+DEFINE RVCT_ALL_DLINK_FLAGS = --ro-base 0 --no_scanlib --reloc --no_exceptions --datacompressor off --strict --symbols --diag_style=ide
+
+####################################################################################
+#
+# ARM RealView Tools - Windows
+#
+####################################################################################
+# RVCT - Tools from ARM
+
+*_RVCT_*_*_FAMILY = RVCT
+
+#
+# Use default values, or override in DSC file
+#
+*_RVCT_ARM_ARCHCC_FLAGS = --thumb
+*_RVCT_ARM_ARCHASM_FLAGS =
+*_RVCT_ARM_ARCHDLINK_FLAGS =
+*_RVCT_ARM_PLATFORM_FLAGS = --cpu 7-A
+
+ DEBUG_RVCT_ARM_DLINK_FLAGS = $(ARCHDLINK_FLAGS) DEF(RVCT_ALL_DLINK_FLAGS) --entry $(IMAGE_ENTRY_POINT) --map --list $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+RELEASE_RVCT_ARM_DLINK_FLAGS = $(ARCHDLINK_FLAGS) DEF(RVCT_ALL_DLINK_FLAGS) --entry $(IMAGE_ENTRY_POINT) --map --list $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+
+
+*_RVCT_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) --apcs /interwork
+*_RVCT_ARM_PP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E
+*_RVCT_ARM_VFRPP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E -DVFRCOMPILE --preinclude $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+*_RVCT_ARM_MAKE_PATH = nmake /NOLOGO
+*_RVCT_ARM_SLINK_FLAGS = --partial -o
+ DEBUG_RVCT_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(RVCT_ALL_CC_FLAGS) -O1 -g
+RELEASE_RVCT_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(RVCT_ALL_CC_FLAGS) -O2
+
+##################
+# ARM definitions
+##################
+*_RVCT_ARM_CC_PATH = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCT_ARM_SLINK_PATH = ENV(RVCT_TOOLS_PATH)armlink
+*_RVCT_ARM_DLINK_PATH = ENV(RVCT_TOOLS_PATH)armlink
+*_RVCT_ARM_ASM_PATH = ENV(RVCT_TOOLS_PATH)armasm
+*_RVCT_ARM_PP_PATH = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCT_ARM_VFRPP_PATH = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCT_ARM_FROMELF_PATH = ENV(RVCT_TOOLS_PATH)fromelf
+
+####################################################################################
+#
+# ARM RealView Tools - Linux
+#
+####################################################################################
+# RVCTLINUX - Tools from ARM in a Cygwin environment
+*_RVCTLINUX_*_*_FAMILY = RVCT
+*_RVCTLINUX_*_*_BUILDRULEFAMILY = RVCTLINUX
+
+#
+# Use default values, or override in DSC file
+#
+*_RVCTLINUX_ARM_ARCHCC_FLAGS = --thumb
+*_RVCTLINUX_ARM_ARCHASM_FLAGS =
+*_RVCTLINUX_ARM_ARCHDLINK_FLAGS =
+*_RVCTLINUX_ARM_PLATFORM_FLAGS = --cpu 7-A
+
+DEBUG_RVCTLINUX_ARM_DLINK_FLAGS = $(ARCHDLINK_FLAGS) DEF(RVCT_ALL_DLINK_FLAGS) --entry $(IMAGE_ENTRY_POINT) --map --list $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+RELEASE_RVCTLINUX_ARM_DLINK_FLAGS = $(ARCHDLINK_FLAGS) DEF(RVCT_ALL_DLINK_FLAGS) --entry $(IMAGE_ENTRY_POINT) --map --list $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+
+*_RVCTLINUX_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) --apcs /interwork
+*_RVCTLINUX_ARM_PP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E
+*_RVCTLINUX_ARM_VFRPP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E -DVFRCOMPILE --preinclude $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+*_RVCTLINUX_ARM_MAKE_PATH = make
+*_RVCTLINUX_ARM_SLINK_FLAGS = --partial -o
+ DEBUG_RVCTLINUX_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(RVCT_ALL_CC_FLAGS) -O1 -g
+RELEASE_RVCTLINUX_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(RVCT_ALL_CC_FLAGS) -O2
+
+##################
+# ARM definitions
+##################
+*_RVCTLINUX_ARM_CC_PATH = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCTLINUX_ARM_SLINK_PATH = ENV(RVCT_TOOLS_PATH)armlink
+*_RVCTLINUX_ARM_DLINK_PATH = ENV(RVCT_TOOLS_PATH)armlink
+*_RVCTLINUX_ARM_ASM_PATH = ENV(RVCT_TOOLS_PATH)armasm
+*_RVCTLINUX_ARM_PP_PATH = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCTLINUX_ARM_VFRPP_PATH = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCTLINUX_ARM_FROMELF_PATH = ENV(RVCT_TOOLS_PATH)fromelf
+
+####################################################################################
+#
+# ARM RealView Tools - Cygwin
+#
+####################################################################################
+# ARMCYGWIN - Tools from ARM in a Cygwin environment
+
+*_RVCTCYGWIN_*_*_FAMILY = RVCT
+*_RVCTCYGWIN_*_*_BUILDRULEFAMILY = RVCTCYGWIN
+
+*_RVCTCYGWIN_ARM_CCPATH_FLAG = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCTCYGWIN_ARM_SLINKPATH_FLAG = ENV(RVCT_TOOLS_PATH)armlink
+*_RVCTCYGWIN_ARM_DLINKPATH_FLAG = ENV(RVCT_TOOLS_PATH)armlink
+*_RVCTCYGWIN_ARM_ASMPATH_FLAG = ENV(RVCT_TOOLS_PATH)armasm
+*_RVCTCYGWIN_ARM_PPPATH_FLAG = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCTCYGWIN_ARM_VFRPPPATH_FLAG = ENV(RVCT_TOOLS_PATH)armcc
+*_RVCTCYGWIN_ARM_FROMELFPATH_FLAG = ENV(RVCT_TOOLS_PATH)fromelf
+
+#
+# Use default values, or override in DSC file
+#
+*_RVCTCYGWIN_ARM_ARCHCC_FLAGS = --thumb
+*_RVCTCYGWIN_ARM_ARCHASM_FLAGS =
+*_RVCTCYGWIN_ARM_ARCHDLINK_FLAGS =
+*_RVCTCYGWIN_ARM_PLATFORM_FLAGS = --cpu 7-A
+
+ DEBUG_RVCTCYGWIN_ARM_DLINK_FLAGS = "$(DLINKPATH_FLAG)" $(ARCHDLINK_FLAGS) DEF(RVCT_ALL_DLINK_FLAGS) --entry $(IMAGE_ENTRY_POINT) --map --list `cygpath -m $(DEST_DIR_DEBUG)/$(BASE_NAME).map`
+RELEASE_RVCTCYGWIN_ARM_DLINK_FLAGS = "$(DLINKPATH_FLAG)" $(ARCHDLINK_FLAGS) DEF(RVCT_ALL_DLINK_FLAGS) --entry $(IMAGE_ENTRY_POINT) --map --list `cygpath -m $(DEST_DIR_DEBUG)/$(BASE_NAME).map`
+
+*_RVCTCYGWIN_ARM_ASM_FLAGS = "$(ASMPATH_FLAG)" $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) --apcs /interwork
+*_RVCTCYGWIN_ARM_PP_FLAGS = "$(CCPATH_FLAG)" $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E
+*_RVCTCYGWIN_ARM_VFRPP_FLAGS = "$(CCPATH_FLAG)" $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E -DVFRCOMPILE --preinclude `cygpath -m $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h`
+*_RVCTCYGWIN_ARM_MAKE_PATH = make
+*_RVCTCYGWIN_ARM_SLINK_FLAGS = "$(SLINKPATH_FLAG)" --partial -o
+ DEBUG_RVCTCYGWIN_ARM_CC_FLAGS = "$(CCPATH_FLAG)" $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(RVCT_ALL_CC_FLAGS) -O1 -g
+RELEASE_RVCTCYGWIN_ARM_CC_FLAGS = "$(CCPATH_FLAG)" $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(RVCT_ALL_CC_FLAGS) -O2
+
+##################
+# ARM definitions
+##################
+*_RVCTCYGWIN_ARM_CC_PATH = ENV(WORKSPACE)/BaseTools/Bin/CYGWIN_NT-5.1-i686/armcc_wrapper.py
+*_RVCTCYGWIN_ARM_SLINK_PATH = ENV(WORKSPACE)/BaseTools/Bin/CYGWIN_NT-5.1-i686/armcc_wrapper.py
+*_RVCTCYGWIN_ARM_DLINK_PATH = ENV(WORKSPACE)/BaseTools/Bin/CYGWIN_NT-5.1-i686/armcc_wrapper.py
+*_RVCTCYGWIN_ARM_ASM_PATH = ENV(WORKSPACE)/BaseTools/Bin/CYGWIN_NT-5.1-i686/armcc_wrapper.py
+*_RVCTCYGWIN_ARM_PP_PATH = ENV(WORKSPACE)/BaseTools/Bin/CYGWIN_NT-5.1-i686/armcc_wrapper.py
+*_RVCTCYGWIN_ARM_VFRPP_PATH = ENV(WORKSPACE)/BaseTools/Bin/CYGWIN_NT-5.1-i686/armcc_wrapper.py
+*_RVCTCYGWIN_ARM_FROMELF_PATH = ENV(WORKSPACE)/BaseTools/Bin/CYGWIN_NT-5.1-i686/armcc_wrapper.py
+
+####################################################################################
+#
+# ARM EABI GCC (www.codesourcery.com)
+#
+####################################################################################
+# ARMGCC - ARM version of the GCC cross compiler
+
+*_ARMGCC_*_*_FAMILY = GCC
+*_ARMGCC_*_*_BUILDRULEFAMILY = ARMGCC
+
+*_ARMGCC_*_MAKE_PATH = make
+*_ARMGCC_*_MAKE_FLAGS = --no-print-directory
+
+##################
+# ASL definitions
+##################
+*_ARMGCC_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+*_ARMGCC_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_ARMGCC_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+*_ARMGCC_*_ASLPP_FLAGS = -x c -E -P
+*_ARMGCC_*_ASLCC_FLAGS = -x c
+*_ARMGCC_*_ASLDLINK_FLAGS = DEF(GCC_DLINK_FLAGS_COMMON) --entry _ReferenceAcpiTable
+
+##################
+# ARM definitions
+##################
+
+*_ARMGCC_ARM_ASLCC_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-gcc
+*_ARMGCC_ARM_ASLDLINK_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-ld
+*_ARMGCC_ARM_ASLPP_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-gcc
+
+*_ARMGCC_ARM_CC_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-gcc
+*_ARMGCC_ARM_SLINK_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-ar
+*_ARMGCC_ARM_DLINK_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-ld
+*_ARMGCC_ARM_ASM_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-as
+*_ARMGCC_ARM_PP_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-gcc
+*_ARMGCC_ARM_VFRPP_PATH = ENV(ARMGCC_TOOLS_PATH)arm-none-eabi-gcc
+
+#
+# Use default values, or override in DSC file
+#
+*_ARMGCC_ARM_ARCHCC_FLAGS = -mthumb
+*_ARMGCC_ARM_ARCHASM_FLAGS =
+*_ARMGCC_ARM_ARCHDLINK_FLAGS =
+*_ARMGCC_ARM_PLATFORM_FLAGS = -march=armv7-a
+
+ DEBUG_ARMGCC_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) -mlittle-endian -g
+RELEASE_ARMGCC_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) -mlittle-endian
+
+*_ARMGCC_ARM_PP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_ARMGCC_ARM_VFRPP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+
+*_ARMGCC_ARM_SLINK_FLAGS = -rc
+*_ARMGCC_ARM_DLINK_FLAGS = $(ARCHDLINK_FLAGS) -Ttext=0x0 --oformat=elf32-littlearm --emit-relocs -nostdlib -u $(IMAGE_ENTRY_POINT) -e $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+
+ DEBUG_ARMGCC_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_ARMGCC_CC_FLAGS) -combine -O0
+RELEASE_ARMGCC_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_ARMGCC_CC_FLAGS) -combine -Wno-unused
+
+####################################################################################
+#
+# ARM GNU/Linux GCC
+#
+####################################################################################
+# ARMLINUXGCC - ARM version of the GCC cross compiler
+
+*_ARMLINUXGCC_*_*_FAMILY = GCC
+*_ARMLINUXGCC_*_*_BUILDRULEFAMILY = ARMLINUXGCC
+
+*_ARMLINUXGCC_*_MAKE_PATH = make
+*_ARMLINUXGCC_*_MAKE_FLAGS = --no-print-directory
+
+##################
+# ASL definitions
+##################
+*_ARMLINUXGCC_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+*_ARMLINUXGCC_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_ARMLINUXGCC_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+*_ARMLINUXGCC_*_ASLPP_FLAGS = -x c -E -P
+*_ARMLINUXGCC_*_ASLCC_FLAGS = -x c
+*_ARMLINUXGCC_*_ASLDLINK_FLAGS = DEF(GCC_DLINK_FLAGS_COMMON) --entry _ReferenceAcpiTable
+
+##################
+# ARM definitions
+##################
+
+*_ARMLINUXGCC_ARM_ASLCC_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-gcc
+*_ARMLINUXGCC_ARM_ASLDLINK_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-ld
+*_ARMLINUXGCC_ARM_ASLPP_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-gcc
+
+*_ARMLINUXGCC_ARM_CC_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-gcc
+*_ARMLINUXGCC_ARM_SLINK_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-ar
+*_ARMLINUXGCC_ARM_DLINK_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-ld
+*_ARMLINUXGCC_ARM_ASM_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-as
+*_ARMLINUXGCC_ARM_PP_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-gcc
+*_ARMLINUXGCC_ARM_VFRPP_PATH = ENV(ARMLINUXGCC_TOOLS_PATH)arm-linux-gnueabi-gcc
+
+#
+# Use default values, or override in DSC file
+#
+*_ARMLINUXGCC_ARM_ARCHCC_FLAGS = -mthumb
+*_ARMLINUXGCC_ARM_ARCHASM_FLAGS =
+*_ARMLINUXGCC_ARM_ARCHDLINK_FLAGS =
+*_ARMLINUXGCC_ARM_PLATFORM_FLAGS = -march=armv7-a
+
+ DEBUG_ARMLINUXGCC_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) -mlittle-endian -g
+RELEASE_ARMLINUXGCC_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) -mlittle-endian
+
+*_ARMLINUXGCC_ARM_PP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
+*_ARMLINUXGCC_ARM_VFRPP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -x c -E -P -DVFRCOMPILE --include $(DEST_DIR_DEBUG)/$(MODULE_NAME)StrDefs.h
+
+*_ARMLINUXGCC_ARM_SLINK_FLAGS = -rc
+*_ARMLINUXGCC_ARM_DLINK_FLAGS = $(ARCHDLINK_FLAGS) -Ttext=0x0 --oformat=elf32-littlearm --emit-relocs -nostdlib -u $(IMAGE_ENTRY_POINT) -e $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
+
+ DEBUG_ARMLINUXGCC_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_ARMGCC_CC_FLAGS) -Wno-address -O0
+RELEASE_ARMLINUXGCC_ARM_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_ARMGCC_CC_FLAGS) -Wno-address -Wno-unused-but-set-variable
+
+#################
+# ASM 16 linker defintions
+#################
+*_*_*_ASMLINK_PATH = DEF(WINDDK_BIN16)\link16.exe
+*_*_*_ASMLINK_FLAGS = /nologo /tiny
+
+##################
+# VfrCompiler definitions
+##################
+*_*_*_VFR_PATH = VfrCompile
+*_*_*_VFR_FLAGS = -l -n
+
+##################
+# OptionRom tool definitions
+##################
+*_*_*_OPTROM_PATH = EfiRom
+*_*_*_OPTROM_FLAGS = -e
+
+##################
+# GenFw tool definitions
+##################
+*_*_*_GENFW_PATH = GenFw
+*_*_*_GENFW_FLAGS =
+
+##################
+# Asl Compiler definitions
+##################
+*_*_*_ASLCC_FLAGS = /nologo /c /FIAutoGen.h /TC /Dmain=ReferenceAcpiTable
+*_*_*_ASLDLINK_FLAGS = /NODEFAULTLIB /ENTRY:ReferenceAcpiTable /SUBSYSTEM:CONSOLE
+*_*_*_ASLPP_FLAGS = /nologo /EP /C
+*_*_*_ASL_FLAGS =
+
+##################
+# GenCrc32 tool definitions
+##################
+*_*_*_CRC32_PATH = GenCrc32
+*_*_*_CRC32_GUID = FC1BCDB0-7D31-49AA-936A-A4600D9DD083
+
+##################
+# LzmaCompress tool definitions
+##################
+*_*_*_LZMA_PATH = LzmaCompress
+*_*_*_LZMA_GUID = EE4E5898-3914-4259-9D6E-DC7BD79403CF
+
+##################
+# LzmaF86Compress tool definitions with converter for x86 code.
+# It can improve the compression ratio if the input file is IA32 or X64 PE image.
+# Notes: If X64 PE image is built based on GCC43/GCC44, it may not get the better compression.
+##################
+*_*_*_LZMAF86_PATH = LzmaF86Compress
+*_*_*_LZMAF86_GUID = D42AE6BD-1352-4bfb-909A-CA72A6EAE889
+
+##################
+# TianoCompress tool definitions
+##################
+*_*_*_TIANO_PATH = TianoCompress
+*_*_*_TIANO_GUID = A31280AD-481E-41B6-95E8-127F4C984779
+
+##################
+# BPDG tool definitions
+##################
+*_*_*_VPDTOOL_PATH = BPDG
+*_*_*_VPDTOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E08
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
new file mode 100644
index 0000000..8833096
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
@@ -0,0 +1,2128 @@
+/** @file
+ The Ehci controller driver.
+
+ EhciDxe driver is responsible for managing the behavior of EHCI controller.
+ It implements the interfaces of monitoring the status of all ports and transferring
+ Control, Bulk, Interrupt and Isochronous requests to Usb2.0 device.
+
+ Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached
+ to the EHCI controller before the UHCI driver attaches to the companion UHCI controller.
+ This way avoids the control transfer on a shared port between EHCI and companion host
+ controller when UHCI gets attached earlier than EHCI and a USB 2.0 device inserts.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "Ehci.h"
+
+//
+// Two arrays used to translate the EHCI port state (change)
+// to the UEFI protocol's port state (change).
+//
+USB_PORT_STATE_MAP mUsbPortStateMap[] = {
+ {PORTSC_CONN, USB_PORT_STAT_CONNECTION},
+ {PORTSC_ENABLED, USB_PORT_STAT_ENABLE},
+ {PORTSC_SUSPEND, USB_PORT_STAT_SUSPEND},
+ {PORTSC_OVERCUR, USB_PORT_STAT_OVERCURRENT},
+ {PORTSC_RESET, USB_PORT_STAT_RESET},
+ {PORTSC_POWER, USB_PORT_STAT_POWER},
+ {PORTSC_OWNER, USB_PORT_STAT_OWNER}
+};
+
+USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
+ {PORTSC_CONN_CHANGE, USB_PORT_STAT_C_CONNECTION},
+ {PORTSC_ENABLE_CHANGE, USB_PORT_STAT_C_ENABLE},
+ {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}
+};
+
+EFI_DRIVER_BINDING_PROTOCOL
+gEhciDriverBinding = {
+ EhcDriverBindingSupported,
+ EhcDriverBindingStart,
+ EhcDriverBindingStop,
+ 0x30,
+ NULL,
+ NULL
+};
+
+/**
+ Retrieves the capability of root hub ports.
+
+ @param This This EFI_USB_HC_PROTOCOL instance.
+ @param MaxSpeed Max speed supported by the controller.
+ @param PortNumber Number of the root hub ports.
+ @param Is64BitCapable Whether the controller supports 64-bit memory
+ addressing.
+
+ @retval EFI_SUCCESS Host controller capability were retrieved successfully.
+ @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcGetCapability (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_TPL OldTpl;
+
+ if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+
+ *MaxSpeed = EFI_USB_SPEED_HIGH;
+ *PortNumber = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS);
+ *Is64BitCapable = (UINT8) (Ehc->HcCapParams & HCCP_64BIT);
+
+ DEBUG ((EFI_D_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
+
+ gBS->RestoreTPL (OldTpl);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Provides software reset for the USB host controller.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param Attributes A bit mask of the reset operation to perform.
+
+ @retval EFI_SUCCESS The reset operation succeeded.
+ @retval EFI_INVALID_PARAMETER Attributes is not valid.
+ @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
+ not currently supported by the host controller.
+ @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcReset (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ UINT32 DbgCtrlStatus;
+
+ Ehc = EHC_FROM_THIS (This);
+
+ if (Ehc->DevicePath != NULL) {
+ //
+ // Report Status Code to indicate reset happens
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
+ Ehc->DevicePath
+ );
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+
+ switch (Attributes) {
+ case EFI_USB_HC_RESET_GLOBAL:
+ //
+ // Flow through, same behavior as Host Controller Reset
+ //
+ case EFI_USB_HC_RESET_HOST_CONTROLLER:
+ //
+ // Host Controller must be Halt when Reset it
+ //
+ if (Ehc->DebugPortNum != 0) {
+ DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0);
+ if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
+ Status = EFI_SUCCESS;
+ goto ON_EXIT;
+ }
+ }
+
+ if (!EhcIsHalt (Ehc)) {
+ Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+ }
+
+ //
+ // Clean up the asynchronous transfers, currently only
+ // interrupt supports asynchronous operation.
+ //
+ EhciDelAllAsyncIntTransfers (Ehc);
+ EhcAckAllInterrupt (Ehc);
+ EhcFreeSched (Ehc);
+
+ Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
+
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ Status = EhcInitHC (Ehc);
+ break;
+
+ case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
+ case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ON_EXIT:
+ DEBUG ((EFI_D_INFO, "EhcReset: exit status %r\n", Status));
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+
+/**
+ Retrieve the current state of the USB host controller.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param State Variable to return the current host controller
+ state.
+
+ @retval EFI_SUCCESS Host controller state was returned in State.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+ @retval EFI_DEVICE_ERROR An error was encountered while attempting to
+ retrieve the host controller's current state.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcGetState (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+ )
+{
+ EFI_TPL OldTpl;
+ USB2_HC_DEV *Ehc;
+
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+
+ if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
+ *State = EfiUsbHcStateHalt;
+ } else {
+ *State = EfiUsbHcStateOperational;
+ }
+
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG ((EFI_D_INFO, "EhcGetState: current state %d\n", *State));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Sets the USB host controller to a specific state.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param State The state of the host controller that will be set.
+
+ @retval EFI_SUCCESS The USB host controller was successfully placed
+ in the state specified by State.
+ @retval EFI_INVALID_PARAMETER State is invalid.
+ @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcSetState (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ EFI_USB_HC_STATE CurState;
+
+ Status = EhcGetState (This, &CurState);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (CurState == State) {
+ return EFI_SUCCESS;
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+
+ switch (State) {
+ case EfiUsbHcStateHalt:
+ Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
+ break;
+
+ case EfiUsbHcStateOperational:
+ if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ //
+ // Software must not write a one to this field unless the host controller
+ // is in the Halted state. Doing so will yield undefined results.
+ // refers to Spec[EHCI1.0-2.3.1]
+ //
+ if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
+ break;
+
+ case EfiUsbHcStateSuspend:
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((EFI_D_INFO, "EhcSetState: exit status %r\n", Status));
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+
+/**
+ Retrieves the current status of a USB root hub port.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param PortNumber The root hub port to retrieve the state from.
+ This value is zero-based.
+ @param PortStatus Variable to receive the port state.
+
+ @retval EFI_SUCCESS The status of the USB root hub port specified.
+ by PortNumber was returned in PortStatus.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid.
+ @retval EFI_DEVICE_ERROR Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcGetRootHubPortStatus (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_TPL OldTpl;
+ UINT32 Offset;
+ UINT32 State;
+ UINT32 TotalPort;
+ UINTN Index;
+ UINTN MapSize;
+ EFI_STATUS Status;
+ UINT32 DbgCtrlStatus;
+
+ if (PortStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+
+ Ehc = EHC_FROM_THIS (This);
+ Status = EFI_SUCCESS;
+
+ TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
+
+ if (PortNumber >= TotalPort) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ if ((Ehc->DebugPortNum != 0) && (PortNumber == (Ehc->DebugPortNum - 1))) {
+ DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0);
+ if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
+ goto ON_EXIT;
+ }
+ }
+
+ State = EhcReadOpReg (Ehc, Offset);
+
+ //
+ // Identify device speed. If in K state, it is low speed.
+ // If the port is enabled after reset, the device is of
+ // high speed. The USB bus driver should retrieve the actual
+ // port speed after reset.
+ //
+ if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+
+ } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
+ }
+
+ //
+ // Convert the EHCI port/port change state to UEFI status
+ //
+ MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
+
+ for (Index = 0; Index < MapSize; Index++) {
+ if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
+ PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
+ }
+ }
+
+ MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
+
+ for (Index = 0; Index < MapSize; Index++) {
+ if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
+ PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
+ }
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+
+/**
+ Sets a feature for the specified root hub port.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param PortNumber Root hub port to set.
+ @param PortFeature Feature to set.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was set.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+ @retval EFI_DEVICE_ERROR Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcSetRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_TPL OldTpl;
+ UINT32 Offset;
+ UINT32 State;
+ UINT32 TotalPort;
+ EFI_STATUS Status;
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+ Status = EFI_SUCCESS;
+
+ TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
+
+ if (PortNumber >= TotalPort) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
+ State = EhcReadOpReg (Ehc, Offset);
+
+ //
+ // Mask off the port status change bits, these bits are
+ // write clean bit
+ //
+ State &= ~PORTSC_CHANGE_MASK;
+
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ //
+ // Sofeware can't set this bit, Port can only be enable by
+ // EHCI as a part of the reset and enable
+ //
+ State |= PORTSC_ENABLED;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortSuspend:
+ State |= PORTSC_SUSPEND;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortReset:
+ //
+ // Make sure Host Controller not halt before reset it
+ //
+ if (EhcIsHalt (Ehc)) {
+ Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
+ break;
+ }
+ }
+
+ //
+ // Set one to PortReset bit must also set zero to PortEnable bit
+ //
+ State |= PORTSC_RESET;
+ State &= ~PORTSC_ENABLED;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortPower:
+ //
+ // Set port power bit when PPC is 1
+ //
+ if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
+ State |= PORTSC_POWER;
+ EhcWriteOpReg (Ehc, Offset, State);
+ }
+ break;
+
+ case EfiUsbPortOwner:
+ State |= PORTSC_OWNER;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ON_EXIT:
+ DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));
+
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+
+/**
+ Clears a feature for the specified root hub port.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param PortNumber Specifies the root hub port whose feature is
+ requested to be cleared.
+ @param PortFeature Indicates the feature selector associated with the
+ feature clear request.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was cleared
+ for the USB root hub port specified by PortNumber.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+ @retval EFI_DEVICE_ERROR Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcClearRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_TPL OldTpl;
+ UINT32 Offset;
+ UINT32 State;
+ UINT32 TotalPort;
+ EFI_STATUS Status;
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+ Status = EFI_SUCCESS;
+
+ TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
+
+ if (PortNumber >= TotalPort) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
+ State = EhcReadOpReg (Ehc, Offset);
+ State &= ~PORTSC_CHANGE_MASK;
+
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ //
+ // Clear PORT_ENABLE feature means disable port.
+ //
+ State &= ~PORTSC_ENABLED;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortSuspend:
+ //
+ // A write of zero to this bit is ignored by the host
+ // controller. The host controller will unconditionally
+ // set this bit to a zero when:
+ // 1. software sets the Forct Port Resume bit to a zero from a one.
+ // 2. software sets the Port Reset bit to a one frome a zero.
+ //
+ State &= ~PORSTSC_RESUME;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortReset:
+ //
+ // Clear PORT_RESET means clear the reset signal.
+ //
+ State &= ~PORTSC_RESET;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortOwner:
+ //
+ // Clear port owner means this port owned by EHC
+ //
+ State &= ~PORTSC_OWNER;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortConnectChange:
+ //
+ // Clear connect status change
+ //
+ State |= PORTSC_CONN_CHANGE;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortEnableChange:
+ //
+ // Clear enable status change
+ //
+ State |= PORTSC_ENABLE_CHANGE;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortOverCurrentChange:
+ //
+ // Clear PortOverCurrent change
+ //
+ State |= PORTSC_OVERCUR_CHANGE;
+ EhcWriteOpReg (Ehc, Offset, State);
+ break;
+
+ case EfiUsbPortPower:
+ //
+ // Clear port power bit when PPC is 1
+ //
+ if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
+ State &= ~PORTSC_POWER;
+ EhcWriteOpReg (Ehc, Offset, State);
+ }
+ break;
+ case EfiUsbPortSuspendChange:
+ case EfiUsbPortResetChange:
+ //
+ // Not supported or not related operation
+ //
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ON_EXIT:
+ DEBUG ((EFI_D_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+
+/**
+ Submits control transfer to a target USB device.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress The target device address.
+ @param DeviceSpeed Target device speed.
+ @param MaximumPacketLength Maximum packet size the default control transfer
+ endpoint is capable of sending or receiving.
+ @param Request USB device request to send.
+ @param TransferDirection Specifies the data direction for the data stage
+ @param Data Data buffer to be transmitted or received from USB
+ device.
+ @param DataLength The size (in bytes) of the data buffer.
+ @param TimeOut Indicates the maximum timeout, in millisecond.
+ @param Translator Transaction translator to be used by this device.
+ @param TransferResult Return the result of this control transfer.
+
+ @retval EFI_SUCCESS Transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT Transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcControlTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+{
+ USB2_HC_DEV *Ehc;
+ URB *Urb;
+ EFI_TPL OldTpl;
+ UINT8 Endpoint;
+ EFI_STATUS Status;
+
+ //
+ // Validate parameters
+ //
+ if ((Request == NULL) || (TransferResult == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((TransferDirection != EfiUsbDataIn) &&
+ (TransferDirection != EfiUsbDataOut) &&
+ (TransferDirection != EfiUsbNoData)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((TransferDirection == EfiUsbNoData) &&
+ ((Data != NULL) || (*DataLength != 0))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((TransferDirection != EfiUsbNoData) &&
+ ((Data == NULL) || (*DataLength == 0))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
+ (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+
+ Status = EFI_DEVICE_ERROR;
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+
+ if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
+ DEBUG ((EFI_D_ERROR, "EhcControlTransfer: HC halted at entrance\n"));
+
+ EhcAckAllInterrupt (Ehc);
+ goto ON_EXIT;
+ }
+
+ EhcAckAllInterrupt (Ehc);
+
+ //
+ // Create a new URB, insert it into the asynchronous
+ // schedule list, then poll the execution status.
+ //
+ //
+ // Encode the direction in address, although default control
+ // endpoint is bidirectional. EhcCreateUrb expects this
+ // combination of Ep addr and its direction.
+ //
+ Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
+ Urb = EhcCreateUrb (
+ Ehc,
+ DeviceAddress,
+ Endpoint,
+ DeviceSpeed,
+ 0,
+ MaximumPacketLength,
+ Translator,
+ EHC_CTRL_TRANSFER,
+ Request,
+ Data,
+ *DataLength,
+ NULL,
+ NULL,
+ 1
+ );
+
+ if (Urb == NULL) {
+ DEBUG ((EFI_D_ERROR, "EhcControlTransfer: failed to create URB"));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ EhcLinkQhToAsync (Ehc, Urb->Qh);
+ Status = EhcExecTransfer (Ehc, Urb, TimeOut);
+ EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
+
+ //
+ // Get the status from URB. The result is updated in EhcCheckUrbResult
+ // which is called by EhcExecTransfer
+ //
+ *TransferResult = Urb->Result;
+ *DataLength = Urb->Completed;
+
+ if (*TransferResult == EFI_USB_NOERROR) {
+ Status = EFI_SUCCESS;
+ }
+
+ EhcAckAllInterrupt (Ehc);
+ EhcFreeUrb (Ehc, Urb);
+
+ON_EXIT:
+ Ehc->PciIo->Flush (Ehc->PciIo);
+ gBS->RestoreTPL (OldTpl);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
+ }
+
+ return Status;
+}
+
+
+/**
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and its direction in bit 7.
+ @param DeviceSpeed Device speed, Low speed device doesn't support bulk
+ transfer.
+ @param MaximumPacketLength Maximum packet size the endpoint is capable of
+ sending or receiving.
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.
+ @param Data Array of pointers to the buffers of data to transmit
+ from or receive into.
+ @param DataLength The lenght of the data buffer.
+ @param DataToggle On input, the initial data toggle for the transfer;
+ On output, it is updated to to next data toggle to
+ use of the subsequent bulk transfer.
+ @param TimeOut Indicates the maximum time, in millisecond, which
+ the transfer is allowed to complete.
+ @param Translator A pointr to the transaction translator data.
+ @param TransferResult A pointer to the detailed result information of the
+ bulk transfer.
+
+ @retval EFI_SUCCESS The transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT The transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcBulkTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+{
+ USB2_HC_DEV *Ehc;
+ URB *Urb;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+
+ //
+ // Validate the parameters
+ //
+ if ((DataLength == NULL) || (*DataLength == 0) ||
+ (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 0) && (*DataToggle != 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
+ ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
+ ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+
+ if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
+ DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: HC is halted\n"));
+
+ EhcAckAllInterrupt (Ehc);
+ goto ON_EXIT;
+ }
+
+ EhcAckAllInterrupt (Ehc);
+
+ //
+ // Create a new URB, insert it into the asynchronous
+ // schedule list, then poll the execution status.
+ //
+ Urb = EhcCreateUrb (
+ Ehc,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ *DataToggle,
+ MaximumPacketLength,
+ Translator,
+ EHC_BULK_TRANSFER,
+ NULL,
+ Data[0],
+ *DataLength,
+ NULL,
+ NULL,
+ 1
+ );
+
+ if (Urb == NULL) {
+ DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: failed to create URB\n"));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ EhcLinkQhToAsync (Ehc, Urb->Qh);
+ Status = EhcExecTransfer (Ehc, Urb, TimeOut);
+ EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
+
+ *TransferResult = Urb->Result;
+ *DataLength = Urb->Completed;
+ *DataToggle = Urb->DataToggle;
+
+ if (*TransferResult == EFI_USB_NOERROR) {
+ Status = EFI_SUCCESS;
+ }
+
+ EhcAckAllInterrupt (Ehc);
+ EhcFreeUrb (Ehc, Urb);
+
+ON_EXIT:
+ Ehc->PciIo->Flush (Ehc->PciIo);
+ gBS->RestoreTPL (OldTpl);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
+ }
+
+ return Status;
+}
+
+
+/**
+ Submits an asynchronous interrupt transfer to an
+ interrupt endpoint of a USB device.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and its direction encoded in bit 7
+ @param DeviceSpeed Indicates device speed.
+ @param MaximumPacketLength Maximum packet size the target endpoint is capable
+ @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
+ transfer If FALSE, to remove the specified
+ asynchronous interrupt.
+ @param DataToggle On input, the initial data toggle to use; on output,
+ it is updated to indicate the next data toggle.
+ @param PollingInterval The he interval, in milliseconds, that the transfer
+ is polled.
+ @param DataLength The length of data to receive at the rate specified
+ by PollingInterval.
+ @param Translator Transaction translator to use.
+ @param CallBackFunction Function to call at the rate specified by
+ PollingInterval.
+ @param Context Context to CallBackFunction.
+
+ @retval EFI_SUCCESS The request has been successfully submitted or canceled.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcAsyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context OPTIONAL
+ )
+{
+ USB2_HC_DEV *Ehc;
+ URB *Urb;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ UINT8 *Data;
+
+ //
+ // Validate parameters
+ //
+ if (!EHCI_IS_DATAIN (EndPointAddress)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsNewTransfer) {
+ if (DataLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((PollingInterval > 255) || (PollingInterval < 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+
+ //
+ // Delete Async interrupt transfer request. DataToggle will return
+ // the next data toggle to use.
+ //
+ if (!IsNewTransfer) {
+ Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);
+
+ DEBUG ((EFI_D_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));
+ goto ON_EXIT;
+ }
+
+ Status = EFI_SUCCESS;
+
+ if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
+ DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));
+ EhcAckAllInterrupt (Ehc);
+
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ EhcAckAllInterrupt (Ehc);
+
+ Data = AllocatePool (DataLength);
+
+ if (Data == NULL) {
+ DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ Urb = EhcCreateUrb (
+ Ehc,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ *DataToggle,
+ MaximumPacketLength,
+ Translator,
+ EHC_INT_TRANSFER_ASYNC,
+ NULL,
+ Data,
+ DataLength,
+ CallBackFunction,
+ Context,
+ PollingInterval
+ );
+
+ if (Urb == NULL) {
+ DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to create URB\n"));
+
+ gBS->FreePool (Data);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ //
+ // New asynchronous transfer must inserted to the head.
+ // Check the comments in EhcMoniteAsyncRequests
+ //
+ EhcLinkQhToPeriod (Ehc, Urb->Qh);
+ InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList);
+
+ON_EXIT:
+ Ehc->PciIo->Flush (Ehc->PciIo);
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and its direction encoded in bit 7
+ @param DeviceSpeed Indicates device speed.
+ @param MaximumPacketLength Maximum packet size the target endpoint is capable
+ of sending or receiving.
+ @param Data Buffer of data that will be transmitted to USB
+ device or received from USB device.
+ @param DataLength On input, the size, in bytes, of the data buffer; On
+ output, the number of bytes transferred.
+ @param DataToggle On input, the initial data toggle to use; on output,
+ it is updated to indicate the next data toggle.
+ @param TimeOut Maximum time, in second, to complete.
+ @param Translator Transaction translator to use.
+ @param TransferResult Variable to receive the transfer result.
+
+ @return EFI_SUCCESS The transfer was completed successfully.
+ @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
+ @return EFI_INVALID_PARAMETER Some parameters are invalid.
+ @return EFI_TIMEOUT The transfer failed due to timeout.
+ @return EFI_DEVICE_ERROR The failed due to host controller or device error
+
+**/
+EFI_STATUS
+EFIAPI
+EhcSyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_TPL OldTpl;
+ URB *Urb;
+ EFI_STATUS Status;
+
+ //
+ // Validates parameters
+ //
+ if ((DataLength == NULL) || (*DataLength == 0) ||
+ (Data == NULL) || (TransferResult == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!EHCI_IS_DATAIN (EndPointAddress)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||
+ ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
+ ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = EHC_FROM_THIS (This);
+
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+
+ if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
+ DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
+
+ EhcAckAllInterrupt (Ehc);
+ goto ON_EXIT;
+ }
+
+ EhcAckAllInterrupt (Ehc);
+
+ Urb = EhcCreateUrb (
+ Ehc,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ *DataToggle,
+ MaximumPacketLength,
+ Translator,
+ EHC_INT_TRANSFER_SYNC,
+ NULL,
+ Data,
+ *DataLength,
+ NULL,
+ NULL,
+ 1
+ );
+
+ if (Urb == NULL) {
+ DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ EhcLinkQhToPeriod (Ehc, Urb->Qh);
+ Status = EhcExecTransfer (Ehc, Urb, TimeOut);
+ EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
+
+ *TransferResult = Urb->Result;
+ *DataLength = Urb->Completed;
+ *DataToggle = Urb->DataToggle;
+
+ if (*TransferResult == EFI_USB_NOERROR) {
+ Status = EFI_SUCCESS;
+ }
+
+ON_EXIT:
+ Ehc->PciIo->Flush (Ehc->PciIo);
+ gBS->RestoreTPL (OldTpl);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
+ }
+
+ return Status;
+}
+
+
+/**
+ Submits isochronous transfer to a target USB device.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress End point address with its direction.
+ @param DeviceSpeed Device speed, Low speed device doesn't support this
+ type.
+ @param MaximumPacketLength Maximum packet size that the endpoint is capable of
+ sending or receiving.
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.
+ @param Data Array of pointers to the buffers of data that will
+ be transmitted to USB device or received from USB
+ device.
+ @param DataLength The size, in bytes, of the data buffer.
+ @param Translator Transaction translator to use.
+ @param TransferResult Variable to receive the transfer result.
+
+ @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Submits Async isochronous transfer to a target USB device.
+
+ @param This This EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress End point address with its direction.
+ @param DeviceSpeed Device speed, Low speed device doesn't support this
+ type.
+ @param MaximumPacketLength Maximum packet size that the endpoint is capable of
+ sending or receiving.
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.
+ @param Data Array of pointers to the buffers of data that will
+ be transmitted to USB device or received from USB
+ device.
+ @param DataLength The size, in bytes, of the data buffer.
+ @param Translator Transaction translator to use.
+ @param IsochronousCallBack Function to be called when the transfer complete.
+ @param Context Context passed to the call back function as
+ parameter.
+
+ @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcAsyncIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Entry point for EFI drivers.
+
+ @param ImageHandle EFI_HANDLE.
+ @param SystemTable EFI_SYSTEM_TABLE.
+
+ @return EFI_SUCCESS Success.
+ EFI_DEVICE_ERROR Fail.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gEhciDriverBinding,
+ ImageHandle,
+ &gEhciComponentName,
+ &gEhciComponentName2
+ );
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has Usb2HcProtocol installed will
+ be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_CLASSC UsbClassCReg;
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &UsbClassCReg
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Test whether the controller belongs to Ehci type
+ //
+ if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
+ || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface !=PCI_IF_UHCI))) {
+
+ Status = EFI_UNSUPPORTED;
+ }
+
+ON_EXIT:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+/**
+ Get the usb debug port related information.
+
+ @param Ehc The EHCI device.
+
+ @retval RETURN_SUCCESS Get debug port number, bar and offset successfully.
+ @retval Others The usb host controller does not supported usb debug port capability.
+
+**/
+EFI_STATUS
+EhcGetUsbDebugPortInfo (
+ IN USB2_HC_DEV *Ehc
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT16 PciStatus;
+ UINT8 CapabilityPtr;
+ UINT8 CapabilityId;
+ UINT16 DebugPort;
+ EFI_STATUS Status;
+
+ ASSERT (Ehc->PciIo != NULL);
+ PciIo = Ehc->PciIo;
+
+ //
+ // Detect if the EHCI host controller support Capaility Pointer.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_PRIMARY_STATUS_OFFSET,
+ sizeof (UINT16),
+ &PciStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
+ //
+ // The Pci Device Doesn't Support Capability Pointer.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get Pointer To Capability List
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CAPBILITY_POINTER_OFFSET,
+ 1,
+ &CapabilityPtr
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Find Capability ID 0xA, Which Is For Debug Port
+ //
+ while (CapabilityPtr != 0) {
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ CapabilityPtr,
+ 1,
+ &CapabilityId
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) {
+ break;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ CapabilityPtr + 1,
+ 1,
+ &CapabilityPtr
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // No Debug Port Capability Found
+ //
+ if (CapabilityPtr == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get The Base Address Of Debug Port Register In Debug Port Capability Register
+ //
+ Status = PciIo->Pci.Read (
+ Ehc->PciIo,
+ EfiPciIoWidthUint8,
+ CapabilityPtr + 2,
+ sizeof (UINT16),
+ &DebugPort
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ehc->DebugPortOffset = DebugPort & 0x1FFF;
+ Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1);
+ Ehc->DebugPortNum = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Create and initialize a USB2_HC_DEV.
+
+ @param PciIo The PciIo on this device.
+ @param DevicePath The device path of host controller.
+ @param OriginalPciAttributes Original PCI attributes.
+
+ @return The allocated and initialized USB2_HC_DEV structure if created,
+ otherwise NULL.
+
+**/
+USB2_HC_DEV *
+EhcCreateUsb2Hc (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN UINT64 OriginalPciAttributes
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_STATUS Status;
+
+ Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
+
+ if (Ehc == NULL) {
+ return NULL;
+ }
+
+ //
+ // Init EFI_USB2_HC_PROTOCOL interface and private data structure
+ //
+ Ehc->Signature = USB2_HC_DEV_SIGNATURE;
+
+ Ehc->Usb2Hc.GetCapability = EhcGetCapability;
+ Ehc->Usb2Hc.Reset = EhcReset;
+ Ehc->Usb2Hc.GetState = EhcGetState;
+ Ehc->Usb2Hc.SetState = EhcSetState;
+ Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;
+ Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;
+ Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;
+ Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;
+ Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;
+ Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;
+ Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;
+ Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;
+ Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
+ Ehc->Usb2Hc.MajorRevision = 0x2;
+ Ehc->Usb2Hc.MinorRevision = 0x0;
+
+ Ehc->PciIo = PciIo;
+ Ehc->DevicePath = DevicePath;
+ Ehc->OriginalPciAttributes = OriginalPciAttributes;
+
+ InitializeListHead (&Ehc->AsyncIntTransfers);
+
+ Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
+ Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
+ Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
+
+ DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
+
+ //
+ // EHCI Controllers with a CapLen of 0 are ignored.
+ //
+ if (Ehc->CapLen == 0) {
+ gBS->FreePool (Ehc);
+ return NULL;
+ }
+
+ EhcGetUsbDebugPortInfo (Ehc);
+
+ //
+ // Create AsyncRequest Polling Timer
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ EhcMonitorAsyncRequests,
+ Ehc,
+ &Ehc->PollTimer
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Ehc);
+ return NULL;
+ }
+
+ return Ehc;
+}
+
+/**
+ One notified function to stop the Host Controller when gBS->ExitBootServices() called.
+
+ @param Event Pointer to this event
+ @param Context Event hanlder private data
+
+**/
+VOID
+EFIAPI
+EhcExitBootService (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+
+{
+ USB2_HC_DEV *Ehc;
+
+ Ehc = (USB2_HC_DEV *) Context;
+
+ //
+ // Reset the Host Controller
+ //
+ EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
+}
+
+
+/**
+ Starting the Usb EHCI Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS supports this device.
+ @return EFI_UNSUPPORTED do not support this device.
+ @return EFI_DEVICE_ERROR cannot be started due to device Error.
+ @return EFI_OUT_OF_RESOURCES cannot allocate resources.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ USB2_HC_DEV *Ehc;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_PCI_IO_PROTOCOL *Instance;
+ UINT64 Supports;
+ UINT64 OriginalPciAttributes;
+ BOOLEAN PciAttributesSaved;
+ USB_CLASSC UsbClassCReg;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ UINTN Index;
+ UINTN UhciSegmentNumber;
+ UINTN UhciBusNumber;
+ UINTN UhciDeviceNumber;
+ UINTN UhciFunctionNumber;
+ UINTN EhciSegmentNumber;
+ UINTN EhciBusNumber;
+ UINTN EhciDeviceNumber;
+ UINTN EhciFunctionNumber;
+ UINT32 State;
+ EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;
+
+ //
+ // Open the PciIo Protocol, then enable the USB host controller
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open Device Path Protocol for on USB host controller
+ //
+ HcDevicePath = NULL;
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &HcDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ PciAttributesSaved = FALSE;
+ //
+ // Save original PCI attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &OriginalPciAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto CLOSE_PCIIO;
+ }
+ PciAttributesSaved = TRUE;
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
+ goto CLOSE_PCIIO;
+ }
+
+ //
+ // Get the Pci device class code.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &UsbClassCReg
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto CLOSE_PCIIO;
+ }
+ //
+ // determine if the device is UHCI host controller or not. If yes, then find out the
+ // companion usb ehci host controller and force EHCI driver get attached to it before
+ // UHCI driver attaches to UHCI host controller.
+ //
+ if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI) &&
+ (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
+ (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
+ Status = PciIo->GetLocation (
+ PciIo,
+ &UhciSegmentNumber,
+ &UhciBusNumber,
+ &UhciDeviceNumber,
+ &UhciFunctionNumber
+ );
+ if (EFI_ERROR (Status)) {
+ goto CLOSE_PCIIO;
+ }
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto CLOSE_PCIIO;
+ }
+
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ //
+ // Get the device path on this handle
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&Instance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Instance->Pci.Read (
+ Instance,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &UsbClassCReg
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto CLOSE_PCIIO;
+ }
+
+ if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&
+ (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
+ (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
+ Status = Instance->GetLocation (
+ Instance,
+ &EhciSegmentNumber,
+ &EhciBusNumber,
+ &EhciDeviceNumber,
+ &EhciFunctionNumber
+ );
+ if (EFI_ERROR (Status)) {
+ goto CLOSE_PCIIO;
+ }
+ //
+ // Currently, the judgment on the companion usb host controller is through the
+ // same bus number, which may vary on different platform.
+ //
+ if (EhciBusNumber == UhciBusNumber) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ EhcDriverBindingStart(This, HandleBuffer[Index], NULL);
+ }
+ }
+ }
+ Status = EFI_NOT_FOUND;
+ goto CLOSE_PCIIO;
+ }
+
+ //
+ // Create then install USB2_HC_PROTOCOL
+ //
+ Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes);
+
+ if (Ehc == NULL) {
+ DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto CLOSE_PCIIO;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiUsb2HcProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Ehc->Usb2Hc
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
+ goto FREE_POOL;
+ }
+
+ //
+ // Robustnesss improvement such as for Duet platform
+ // Default is not required.
+ //
+ if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
+ EhcClearLegacySupport (Ehc);
+ }
+
+ if (Ehc->DebugPortNum != 0) {
+ State = EhcReadDbgRegister(Ehc, 0);
+ if ((State & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) != (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
+ EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
+ }
+ }
+
+ Status = EhcInitHC (Ehc);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
+ goto UNINSTALL_USBHC;
+ }
+
+ //
+ // Start the asynchronous interrupt monitor
+ //
+ Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
+
+ EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
+ goto UNINSTALL_USBHC;
+ }
+
+ //
+ // Create event to stop the HC when exit boot service.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ EhcExitBootService,
+ Ehc,
+ &gEfiEventExitBootServicesGuid,
+ &Ehc->ExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto UNINSTALL_USBHC;
+ }
+
+ //
+ // Install the component name protocol, don't fail the start
+ // because of something for display.
+ //
+ AddUnicodeString2 (
+ "eng",
+ gEhciComponentName.SupportedLanguages,
+ &Ehc->ControllerNameTable,
+ L"Enhanced Host Controller (USB 2.0)",
+ TRUE
+ );
+ AddUnicodeString2 (
+ "en",
+ gEhciComponentName2.SupportedLanguages,
+ &Ehc->ControllerNameTable,
+ L"Enhanced Host Controller (USB 2.0)",
+ FALSE
+ );
+
+
+ DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
+ return EFI_SUCCESS;
+
+UNINSTALL_USBHC:
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ &Ehc->Usb2Hc
+ );
+
+FREE_POOL:
+ EhcFreeSched (Ehc);
+ gBS->CloseEvent (Ehc->PollTimer);
+ gBS->FreePool (Ehc);
+
+CLOSE_PCIIO:
+ if (PciAttributesSaved) {
+ //
+ // Restore original PCI attributes
+ //
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSet,
+ OriginalPciAttributes,
+ NULL
+ );
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS Success.
+ @return EFI_DEVICE_ERROR Fail.
+
+**/
+EFI_STATUS
+EFIAPI
+EhcDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB2_HC_DEV *Ehc;
+
+ //
+ // Test whether the Controller handler passed in is a valid
+ // Usb controller handle that should be supported, if not,
+ // return the error status directly
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &Usb2Hc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ehc = EHC_FROM_THIS (Usb2Hc);
+ PciIo = Ehc->PciIo;
+
+ //
+ // Stop AsyncRequest Polling timer then stop the EHCI driver
+ // and uninstall the EHCI protocl.
+ //
+ gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
+ EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
+
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ Usb2Hc
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Ehc->PollTimer != NULL) {
+ gBS->CloseEvent (Ehc->PollTimer);
+ }
+
+ if (Ehc->ExitBootServiceEvent != NULL) {
+ gBS->CloseEvent (Ehc->ExitBootServiceEvent);
+ }
+
+ EhcFreeSched (Ehc);
+
+ if (Ehc->ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (Ehc->ControllerNameTable);
+ }
+
+ //
+ // Disable routing of all ports to EHCI controller, so all ports are
+ // routed back to the UHCI controller.
+ //
+ EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
+
+ //
+ // Restore original PCI attributes
+ //
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSet,
+ Ehc->OriginalPciAttributes,
+ NULL
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ FreePool (Ehc);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
new file mode 100644
index 0000000..efc8109
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
@@ -0,0 +1,100 @@
+## @file
+#
+# Component Description File For EhciDxe Module.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EhciDxe
+ FILE_GUID = BDFE430E-8F2A-4db0-9991-6F856594777E
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = EhcDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gEhciDriverBinding
+# COMPONENT_NAME = gEhciComponentName
+# COMPONENT_NAME2 = gEhciComponentName2
+#
+
+[Sources]
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.h
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.c
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.h
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c
+ EhciSched.c
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.c
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.h
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/ComponentName.c
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/ComponentName.h
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.h
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h
+ ../../../../../../MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.h
+ Ehci.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport ## SOMETIME_CONSUMES (enable/disable usb legacy support.)
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ ReportStatusCodeLib
+
+[Guids]
+ gEfiEventExitBootServicesGuid ## PRODUCES ## Event
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiUsb2HcProtocolGuid ## BY_START
+
+# [Event]
+# ##
+# # Periodic timer event for checking the result of interrupt transfer execution.
+# #
+# EVENT_TYPE_PERIODIC_TIMER ## PRODUCES
+#
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
new file mode 100644
index 0000000..93d0daa
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
@@ -0,0 +1,1071 @@
+/** @file
+
+ EHCI transfer scheduling routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Ehci.h"
+
+
+/**
+ Create helper QTD/QH for the EHCI device.
+
+ @param Ehc The EHCI device.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for helper QTD/QH.
+ @retval EFI_SUCCESS Helper QH/QTD are created.
+
+**/
+EFI_STATUS
+EhcCreateHelpQ (
+ IN USB2_HC_DEV *Ehc
+ )
+{
+ USB_ENDPOINT Ep;
+ EHC_QH *Qh;
+ QH_HW *QhHw;
+ EHC_QTD *Qtd;
+ EFI_PHYSICAL_ADDRESS PciAddr;
+
+ //
+ // Create an inactive Qtd to terminate the short packet read.
+ //
+ Qtd = EhcCreateQtd (Ehc, NULL, NULL, 0, QTD_PID_INPUT, 0, 64);
+
+ if (Qtd == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Qtd->QtdHw.Status = QTD_STAT_HALTED;
+ Ehc->ShortReadStop = Qtd;
+
+ //
+ // Create a QH to act as the EHC reclamation header.
+ // Set the header to loopback to itself.
+ //
+ Ep.DevAddr = 0;
+ Ep.EpAddr = 1;
+ Ep.Direction = EfiUsbDataIn;
+ Ep.DevSpeed = EFI_USB_SPEED_HIGH;
+ Ep.MaxPacket = 64;
+ Ep.HubAddr = 0;
+ Ep.HubPort = 0;
+ Ep.Toggle = 0;
+ Ep.Type = EHC_BULK_TRANSFER;
+ Ep.PollRate = 1;
+
+ Qh = EhcCreateQh (Ehc, &Ep);
+
+ if (Qh == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH));
+ QhHw = &Qh->QhHw;
+ QhHw->HorizonLink = QH_LINK (PciAddr + OFFSET_OF(EHC_QH, QhHw), EHC_TYPE_QH, FALSE);
+ QhHw->Status = QTD_STAT_HALTED;
+ QhHw->ReclaimHead = 1;
+ Qh->NextQh = Qh;
+ Ehc->ReclaimHead = Qh;
+
+ //
+ // Create a dummy QH to act as the terminator for periodical schedule
+ //
+ Ep.EpAddr = 2;
+ Ep.Type = EHC_INT_TRANSFER_SYNC;
+
+ Qh = EhcCreateQh (Ehc, &Ep);
+
+ if (Qh == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Qh->QhHw.Status = QTD_STAT_HALTED;
+ Ehc->PeriodOne = Qh;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize the schedule data structure such as frame list.
+
+ @param Ehc The EHCI device to init schedule data.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to init schedule data.
+ @retval EFI_SUCCESS The schedule data is initialized.
+
+**/
+EFI_STATUS
+EhcInitSched (
+ IN USB2_HC_DEV *Ehc
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ VOID *Buf;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ VOID *Map;
+ UINTN Pages;
+ UINTN Bytes;
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PciAddr;
+
+ //
+ // First initialize the periodical schedule data:
+ // 1. Allocate and map the memory for the frame list
+ // 2. Create the help QTD/QH
+ // 3. Initialize the frame entries
+ // 4. Set the frame list register
+ //
+ PciIo = Ehc->PciIo;
+
+ Bytes = 4096;
+ Pages = EFI_SIZE_TO_PAGES (Bytes);
+
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ &Buf,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ Buf,
+ &Bytes,
+ &PhyAddr,
+ &Map
+ );
+
+ if (EFI_ERROR (Status) || (Bytes != 4096)) {
+ PciIo->FreeBuffer (PciIo, Pages, Buf);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ehc->PeriodFrame = Buf;
+ Ehc->PeriodFrameMap = Map;
+
+ //
+ // Program the FRAMELISTBASE register with the low 32 bit addr
+ //
+ EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (PhyAddr));
+ //
+ // Program the CTRLDSSEGMENT register with the high 32 bit addr
+ //
+ EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, EHC_HIGH_32BIT (PhyAddr));
+
+ //
+ // Init memory pool management then create the helper
+ // QTD/QH. If failed, previously allocated resources
+ // will be freed by EhcFreeSched
+ //
+ Ehc->MemPool = UsbHcInitMemPool (
+ PciIo,
+ EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT),
+ EHC_HIGH_32BIT (PhyAddr)
+ );
+
+ if (Ehc->MemPool == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit1;
+ }
+
+ Status = EhcCreateHelpQ (Ehc);
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Initialize the frame list entries then set the registers
+ //
+ Ehc->PeriodFrameHost = AllocateZeroPool (EHC_FRAME_LEN * sizeof (UINTN));
+ if (Ehc->PeriodFrameHost == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH));
+
+ for (Index = 0; Index < EHC_FRAME_LEN; Index++) {
+ //
+ // Store the pci bus address of the QH in period frame list which will be accessed by pci bus master.
+ //
+ ((UINT32 *)(Ehc->PeriodFrame))[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);
+ //
+ // Store the host address of the QH in period frame list which will be accessed by host.
+ //
+ ((UINTN *)(Ehc->PeriodFrameHost))[Index] = (UINTN)Ehc->PeriodOne;
+ }
+
+ //
+ // Second initialize the asynchronous schedule:
+ // Only need to set the AsynListAddr register to
+ // the reclamation header
+ //
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (EHC_QH));
+ EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (PciAddr));
+ return EFI_SUCCESS;
+
+ErrorExit:
+ if (Ehc->PeriodOne != NULL) {
+ UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH));
+ Ehc->PeriodOne = NULL;
+ }
+
+ if (Ehc->ReclaimHead != NULL) {
+ UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (EHC_QH));
+ Ehc->ReclaimHead = NULL;
+ }
+
+ if (Ehc->ShortReadStop != NULL) {
+ UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD));
+ Ehc->ShortReadStop = NULL;
+ }
+
+ErrorExit1:
+ PciIo->FreeBuffer (PciIo, Pages, Buf);
+ PciIo->Unmap (PciIo, Map);
+
+ return Status;
+}
+
+
+/**
+ Free the schedule data. It may be partially initialized.
+
+ @param Ehc The EHCI device.
+
+**/
+VOID
+EhcFreeSched (
+ IN USB2_HC_DEV *Ehc
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, 0);
+ EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, 0);
+
+ if (Ehc->PeriodOne != NULL) {
+ UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH));
+ Ehc->PeriodOne = NULL;
+ }
+
+ if (Ehc->ReclaimHead != NULL) {
+ UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (EHC_QH));
+ Ehc->ReclaimHead = NULL;
+ }
+
+ if (Ehc->ShortReadStop != NULL) {
+ UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD));
+ Ehc->ShortReadStop = NULL;
+ }
+
+ if (Ehc->MemPool != NULL) {
+ UsbHcFreeMemPool (Ehc->MemPool);
+ Ehc->MemPool = NULL;
+ }
+
+ if (Ehc->PeriodFrame != NULL) {
+ PciIo = Ehc->PciIo;
+ ASSERT (PciIo != NULL);
+
+ PciIo->Unmap (PciIo, Ehc->PeriodFrameMap);
+
+ PciIo->FreeBuffer (
+ PciIo,
+ EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE),
+ Ehc->PeriodFrame
+ );
+
+ Ehc->PeriodFrame = NULL;
+ }
+
+ if (Ehc->PeriodFrameHost != NULL) {
+ FreePool (Ehc->PeriodFrameHost);
+ Ehc->PeriodFrameHost = NULL;
+ }
+}
+
+
+/**
+ Link the queue head to the asynchronous schedule list.
+ UEFI only supports one CTRL/BULK transfer at a time
+ due to its interfaces. This simplifies the AsynList
+ management: A reclamation header is always linked to
+ the AsyncListAddr, the only active QH is appended to it.
+
+ @param Ehc The EHCI device.
+ @param Qh The queue head to link.
+
+**/
+VOID
+EhcLinkQhToAsync (
+ IN USB2_HC_DEV *Ehc,
+ IN EHC_QH *Qh
+ )
+{
+ EHC_QH *Head;
+ EFI_PHYSICAL_ADDRESS PciAddr;
+
+ //
+ // Append the queue head after the reclaim header, then
+ // fix the hardware visiable parts (EHCI R1.0 page 72).
+ // ReclaimHead is always linked to the EHCI's AsynListAddr.
+ //
+ Head = Ehc->ReclaimHead;
+
+ Qh->NextQh = Head->NextQh;
+ Head->NextQh = Qh;
+
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh->NextQh, sizeof (EHC_QH));
+ Qh->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head->NextQh, sizeof (EHC_QH));
+ Head->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);
+}
+
+
+/**
+ Unlink a queue head from the asynchronous schedule list.
+ Need to synchronize with hardware.
+
+ @param Ehc The EHCI device.
+ @param Qh The queue head to unlink.
+
+**/
+VOID
+EhcUnlinkQhFromAsync (
+ IN USB2_HC_DEV *Ehc,
+ IN EHC_QH *Qh
+ )
+{
+ EHC_QH *Head;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PciAddr;
+
+ ASSERT (Ehc->ReclaimHead->NextQh == Qh);
+
+ //
+ // Remove the QH from reclamation head, then update the hardware
+ // visiable part: Only need to loopback the ReclaimHead. The Qh
+ // is pointing to ReclaimHead (which is staill in the list).
+ //
+ Head = Ehc->ReclaimHead;
+
+ Head->NextQh = Qh->NextQh;
+ Qh->NextQh = NULL;
+
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head->NextQh, sizeof (EHC_QH));
+ Head->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);
+
+ //
+ // Set and wait the door bell to synchronize with the hardware
+ //
+ Status = EhcSetAndWaitDoorBell (Ehc, EHC_GENERIC_TIMEOUT);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EhcUnlinkQhFromAsync: Failed to synchronize with doorbell\n"));
+ }
+}
+
+
+/**
+ Link a queue head for interrupt transfer to the periodic
+ schedule frame list. This code is very much the same as
+ that in UHCI.
+
+ @param Ehc The EHCI device.
+ @param Qh The queue head to link.
+
+**/
+VOID
+EhcLinkQhToPeriod (
+ IN USB2_HC_DEV *Ehc,
+ IN EHC_QH *Qh
+ )
+{
+ UINTN Index;
+ EHC_QH *Prev;
+ EHC_QH *Next;
+ EFI_PHYSICAL_ADDRESS PciAddr;
+
+ for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {
+ //
+ // First QH can't be NULL because we always keep PeriodOne
+ // heads on the frame list
+ //
+ ASSERT (!EHC_LINK_TERMINATED (((UINT32*)Ehc->PeriodFrame)[Index]));
+ Next = (EHC_QH*)((UINTN*)Ehc->PeriodFrameHost)[Index];
+ Prev = NULL;
+
+ //
+ // Now, insert the queue head (Qh) into this frame:
+ // 1. Find a queue head with the same poll interval, just insert
+ // Qh after this queue head, then we are done.
+ //
+ // 2. Find the position to insert the queue head into:
+ // Previous head's interval is bigger than Qh's
+ // Next head's interval is less than Qh's
+ // Then, insert the Qh between then
+ //
+ while (Next->Interval > Qh->Interval) {
+ Prev = Next;
+ Next = Next->NextQh;
+ }
+
+ ASSERT (Next != NULL);
+
+ //
+ // The entry may have been linked into the frame by early insertation.
+ // For example: if insert a Qh with Qh.Interval == 4, and there is a Qh
+ // with Qh.Interval == 8 on the frame. If so, we are done with this frame.
+ // It isn't necessary to compare all the QH with the same interval to
+ // Qh. This is because if there is other QH with the same interval, Qh
+ // should has been inserted after that at Frames[0] and at Frames[0] it is
+ // impossible for (Next == Qh)
+ //
+ if (Next == Qh) {
+ continue;
+ }
+
+ if (Next->Interval == Qh->Interval) {
+ //
+ // If there is a QH with the same interval, it locates at
+ // Frames[0], and we can simply insert it after this QH. We
+ // are all done.
+ //
+ ASSERT ((Index == 0) && (Qh->NextQh == NULL));
+
+ Prev = Next;
+ Next = Next->NextQh;
+
+ Qh->NextQh = Next;
+ Prev->NextQh = Qh;
+
+ Qh->QhHw.HorizonLink = Prev->QhHw.HorizonLink;
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH));
+ Prev->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);
+ break;
+ }
+
+ //
+ // OK, find the right position, insert it in. If Qh's next
+ // link has already been set, it is in position. This is
+ // guarranted by 2^n polling interval.
+ //
+ if (Qh->NextQh == NULL) {
+ Qh->NextQh = Next;
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Next, sizeof (EHC_QH));
+ Qh->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);
+ }
+
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH));
+
+ if (Prev == NULL) {
+ ((UINT32*)Ehc->PeriodFrame)[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);
+ ((UINTN*)Ehc->PeriodFrameHost)[Index] = (UINTN)Qh;
+ } else {
+ Prev->NextQh = Qh;
+ Prev->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);
+ }
+ }
+}
+
+
+/**
+ Unlink an interrupt queue head from the periodic
+ schedule frame list.
+
+ @param Ehc The EHCI device.
+ @param Qh The queue head to unlink.
+
+**/
+VOID
+EhcUnlinkQhFromPeriod (
+ IN USB2_HC_DEV *Ehc,
+ IN EHC_QH *Qh
+ )
+{
+ UINTN Index;
+ EHC_QH *Prev;
+ EHC_QH *This;
+
+ for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {
+ //
+ // Frame link can't be NULL because we always keep PeroidOne
+ // on the frame list
+ //
+ ASSERT (!EHC_LINK_TERMINATED (((UINT32*)Ehc->PeriodFrame)[Index]));
+ This = (EHC_QH*)((UINTN*)Ehc->PeriodFrameHost)[Index];
+ Prev = NULL;
+
+ //
+ // Walk through the frame's QH list to find the
+ // queue head to remove
+ //
+ while ((This != NULL) && (This != Qh)) {
+ Prev = This;
+ This = This->NextQh;
+ }
+
+ //
+ // Qh may have already been unlinked from this frame
+ // by early action. See the comments in EhcLinkQhToPeriod.
+ //
+ if (This == NULL) {
+ continue;
+ }
+
+ if (Prev == NULL) {
+ //
+ // Qh is the first entry in the frame
+ //
+ ((UINT32*)Ehc->PeriodFrame)[Index] = Qh->QhHw.HorizonLink;
+ ((UINTN*)Ehc->PeriodFrameHost)[Index] = (UINTN)Qh->NextQh;
+ } else {
+ Prev->NextQh = Qh->NextQh;
+ Prev->QhHw.HorizonLink = Qh->QhHw.HorizonLink;
+ }
+ }
+}
+
+
+/**
+ Check the URB's execution result and update the URB's
+ result accordingly.
+
+ @param Ehc The EHCI device.
+ @param Urb The URB to check result.
+
+ @return Whether the result of URB transfer is finialized.
+
+**/
+BOOLEAN
+EhcCheckUrbResult (
+ IN USB2_HC_DEV *Ehc,
+ IN URB *Urb
+ )
+{
+ LIST_ENTRY *Entry;
+ EHC_QTD *Qtd;
+ QTD_HW *QtdHw;
+ UINT8 State;
+ BOOLEAN Finished;
+ EFI_PHYSICAL_ADDRESS PciAddr;
+
+ ASSERT ((Ehc != NULL) && (Urb != NULL) && (Urb->Qh != NULL));
+
+ Finished = TRUE;
+ Urb->Completed = 0;
+
+ Urb->Result = EFI_USB_NOERROR;
+
+ if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
+ Urb->Result |= EFI_USB_ERR_SYSTEM;
+ goto ON_EXIT;
+ }
+
+ EFI_LIST_FOR_EACH (Entry, &Urb->Qh->Qtds) {
+ Qtd = EFI_LIST_CONTAINER (Entry, EHC_QTD, QtdList);
+ QtdHw = &Qtd->QtdHw;
+ State = (UINT8) QtdHw->Status;
+
+ if (EHC_BIT_IS_SET (State, QTD_STAT_HALTED)) {
+ //
+ // EHCI will halt the queue head when met some error.
+ // If it is halted, the result of URB is finialized.
+ //
+ if ((State & QTD_STAT_ERR_MASK) == 0) {
+ Urb->Result |= EFI_USB_ERR_STALL;
+ }
+
+ if (EHC_BIT_IS_SET (State, QTD_STAT_BABBLE_ERR)) {
+ Urb->Result |= EFI_USB_ERR_BABBLE;
+ }
+
+ if (EHC_BIT_IS_SET (State, QTD_STAT_BUFF_ERR)) {
+ Urb->Result |= EFI_USB_ERR_BUFFER;
+ }
+
+ if (EHC_BIT_IS_SET (State, QTD_STAT_TRANS_ERR) && (QtdHw->ErrCnt == 0)) {
+ Urb->Result |= EFI_USB_ERR_TIMEOUT;
+ }
+
+ Finished = TRUE;
+ goto ON_EXIT;
+
+ } else if (EHC_BIT_IS_SET (State, QTD_STAT_ACTIVE)) {
+ //
+ // The QTD is still active, no need to check furthur.
+ //
+ Urb->Result |= EFI_USB_ERR_NOTEXECUTE;
+
+ Finished = FALSE;
+ goto ON_EXIT;
+
+ } else {
+ //
+ // This QTD is finished OK or met short packet read. Update the
+ // transfer length if it isn't a setup.
+ //
+ if (QtdHw->Pid != QTD_PID_SETUP) {
+ Urb->Completed += Qtd->DataLen - QtdHw->TotalBytes;
+ }
+
+ if ((QtdHw->TotalBytes != 0) && (QtdHw->Pid == QTD_PID_INPUT)) {
+ EhcDumpQh (Urb->Qh, "Short packet read", FALSE);
+
+ //
+ // Short packet read condition. If it isn't a setup transfer,
+ // no need to check furthur: the queue head will halt at the
+ // ShortReadStop. If it is a setup transfer, need to check the
+ // Status Stage of the setup transfer to get the finial result
+ //
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD));
+ if (QtdHw->AltNext == QTD_LINK (PciAddr, FALSE)) {
+ DEBUG ((EFI_D_INFO, "EhcCheckUrbResult: Short packet read, break\n"));
+
+ Finished = TRUE;
+ goto ON_EXIT;
+ }
+
+ DEBUG ((EFI_D_INFO, "EhcCheckUrbResult: Short packet read, continue\n"));
+ }
+ }
+ }
+
+ON_EXIT:
+ //
+ // Return the data toggle set by EHCI hardware, bulk and interrupt
+ // transfer will use this to initialize the next transaction. For
+ // Control transfer, it always start a new data toggle sequence for
+ // new transfer.
+ //
+ // NOTICE: don't move DT update before the loop, otherwise there is
+ // a race condition that DT is wrong.
+ //
+ Urb->DataToggle = (UINT8) Urb->Qh->QhHw.DataToggle;
+
+ return Finished;
+}
+
+
+/**
+ Execute the transfer by polling the URB. This is a synchronous operation.
+
+ @param Ehc The EHCI device.
+ @param Urb The URB to execute.
+ @param TimeOut The time to wait before abort, in millisecond.
+
+ @return EFI_DEVICE_ERROR The transfer failed due to transfer error.
+ @return EFI_TIMEOUT The transfer failed due to time out.
+ @return EFI_SUCCESS The transfer finished OK.
+
+**/
+EFI_STATUS
+EhcExecTransfer (
+ IN USB2_HC_DEV *Ehc,
+ IN URB *Urb,
+ IN UINTN TimeOut
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Loop;
+ BOOLEAN Finished;
+ BOOLEAN InfiniteLoop;
+
+ Status = EFI_SUCCESS;
+ Loop = (TimeOut * EHC_1_MILLISECOND / EHC_SYNC_POLL_INTERVAL) + 1;
+ Finished = FALSE;
+ InfiniteLoop = FALSE;
+
+ //
+ // According to UEFI spec section 16.2.4, If Timeout is 0, then the caller
+ // must wait for the function to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR
+ // is returned.
+ //
+ if (TimeOut == 0) {
+ InfiniteLoop = TRUE;
+ }
+
+ for (Index = 0; InfiniteLoop || (Index < Loop); Index++) {
+ Finished = EhcCheckUrbResult (Ehc, Urb);
+
+ if (Finished) {
+ break;
+ }
+
+ gBS->Stall (EHC_SYNC_POLL_INTERVAL);
+ }
+
+ if (!Finished) {
+ DEBUG ((EFI_D_ERROR, "EhcExecTransfer: transfer not finished in %dms\n", (UINT32)TimeOut));
+ EhcDumpQh (Urb->Qh, NULL, FALSE);
+
+ Status = EFI_TIMEOUT;
+
+ } else if (Urb->Result != EFI_USB_NOERROR) {
+ DEBUG ((EFI_D_INFO, "EhcExecTransfer: transfer failed with %x\n", Urb->Result));
+ EhcDumpQh (Urb->Qh, NULL, FALSE);
+
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+
+/**
+ Delete a single asynchronous interrupt transfer for
+ the device and endpoint.
+
+ @param Ehc The EHCI device.
+ @param DevAddr The address of the target device.
+ @param EpNum The endpoint of the target.
+ @param DataToggle Return the next data toggle to use.
+
+ @retval EFI_SUCCESS An asynchronous transfer is removed.
+ @retval EFI_NOT_FOUND No transfer for the device is found.
+
+**/
+EFI_STATUS
+EhciDelAsyncIntTransfer (
+ IN USB2_HC_DEV *Ehc,
+ IN UINT8 DevAddr,
+ IN UINT8 EpNum,
+ OUT UINT8 *DataToggle
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ URB *Urb;
+ EFI_USB_DATA_DIRECTION Direction;
+
+ Direction = (((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut);
+ EpNum &= 0x0F;
+
+ EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {
+ Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);
+
+ if ((Urb->Ep.DevAddr == DevAddr) && (Urb->Ep.EpAddr == EpNum) &&
+ (Urb->Ep.Direction == Direction)) {
+ //
+ // Check the URB status to retrieve the next data toggle
+ // from the associated queue head.
+ //
+ EhcCheckUrbResult (Ehc, Urb);
+ *DataToggle = Urb->DataToggle;
+
+ EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
+ RemoveEntryList (&Urb->UrbList);
+
+ gBS->FreePool (Urb->Data);
+ EhcFreeUrb (Ehc, Urb);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Remove all the asynchronous interrutp transfers.
+
+ @param Ehc The EHCI device.
+
+**/
+VOID
+EhciDelAllAsyncIntTransfers (
+ IN USB2_HC_DEV *Ehc
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ URB *Urb;
+
+ EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {
+ Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);
+
+ EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
+ RemoveEntryList (&Urb->UrbList);
+
+ gBS->FreePool (Urb->Data);
+ EhcFreeUrb (Ehc, Urb);
+ }
+}
+
+
+/**
+ Flush data from PCI controller specific address to mapped system
+ memory address.
+
+ @param Ehc The EHCI device.
+ @param Urb The URB to unmap.
+
+ @retval EFI_SUCCESS Success to flush data to mapped system memory.
+ @retval EFI_DEVICE_ERROR Fail to flush data to mapped system memory.
+
+**/
+EFI_STATUS
+EhcFlushAsyncIntMap (
+ IN USB2_HC_DEV *Ehc,
+ IN URB *Urb
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Len;
+ VOID *Map;
+
+ PciIo = Ehc->PciIo;
+ Len = Urb->DataLen;
+
+ if (Urb->Ep.Direction == EfiUsbDataIn) {
+ MapOp = EfiPciIoOperationBusMasterWrite;
+ } else {
+ MapOp = EfiPciIoOperationBusMasterRead;
+ }
+
+ Status = PciIo->Unmap (PciIo, Urb->DataMap);
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Urb->DataMap = NULL;
+
+ Status = PciIo->Map (PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);
+ if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {
+ goto ON_ERROR;
+ }
+
+ Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);
+ Urb->DataMap = Map;
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ return EFI_DEVICE_ERROR;
+}
+
+
+/**
+ Update the queue head for next round of asynchronous transfer.
+
+ @param Ehc The EHCI device.
+ @param Urb The URB to update.
+
+**/
+VOID
+EhcUpdateAsyncRequest (
+ IN USB2_HC_DEV *Ehc,
+ IN URB *Urb
+ )
+{
+ LIST_ENTRY *Entry;
+ EHC_QTD *FirstQtd;
+ QH_HW *QhHw;
+ EHC_QTD *Qtd;
+ QTD_HW *QtdHw;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS PciAddr;
+
+ Qtd = NULL;
+
+ if (Urb->Result == EFI_USB_NOERROR) {
+ FirstQtd = NULL;
+
+ EFI_LIST_FOR_EACH (Entry, &Urb->Qh->Qtds) {
+ Qtd = EFI_LIST_CONTAINER (Entry, EHC_QTD, QtdList);
+
+ if (FirstQtd == NULL) {
+ FirstQtd = Qtd;
+ }
+
+ //
+ // Update the QTD for next round of transfer. Host control
+ // may change dt/Total Bytes to Transfer/C_Page/Cerr/Status/
+ // Current Offset. These fields need to be updated. DT isn't
+ // used by interrupt transfer. It uses DT in queue head.
+ // Current Offset is in Page[0], only need to reset Page[0]
+ // to initial data buffer.
+ //
+ QtdHw = &Qtd->QtdHw;
+ QtdHw->Status = QTD_STAT_ACTIVE;
+ QtdHw->ErrCnt = QTD_MAX_ERR;
+ QtdHw->CurPage = 0;
+ QtdHw->TotalBytes = (UINT32) Qtd->DataLen;
+ //
+ // calculate physical address by offset.
+ //
+ PciAddr = (UINTN)Urb->DataPhy + ((UINTN)Qtd->Data - (UINTN)Urb->Data);
+ QtdHw->Page[0] = EHC_LOW_32BIT (PciAddr);
+ QtdHw->PageHigh[0]= EHC_HIGH_32BIT (PciAddr);
+ }
+
+ //
+ // Update QH for next round of transfer. Host control only
+ // touch the fields in transfer overlay area. Only need to
+ // zero out the overlay area and set NextQtd to the first
+ // QTD. DateToggle bit is left untouched.
+ //
+ QhHw = &Urb->Qh->QhHw;
+ QhHw->CurQtd = QTD_LINK (0, TRUE);
+ QhHw->AltQtd = 0;
+
+ QhHw->Status = 0;
+ QhHw->Pid = 0;
+ QhHw->ErrCnt = 0;
+ QhHw->CurPage = 0;
+ QhHw->Ioc = 0;
+ QhHw->TotalBytes = 0;
+
+ for (Index = 0; Index < 5; Index++) {
+ QhHw->Page[Index] = 0;
+ QhHw->PageHigh[Index] = 0;
+ }
+
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, FirstQtd, sizeof (EHC_QTD));
+ QhHw->NextQtd = QTD_LINK (PciAddr, FALSE);
+ }
+
+ return ;
+}
+
+
+/**
+ Interrupt transfer periodic check handler.
+
+ @param Event Interrupt event.
+ @param Context Pointer to USB2_HC_DEV.
+
+**/
+VOID
+EFIAPI
+EhcMonitorAsyncRequests (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ USB2_HC_DEV *Ehc;
+ EFI_TPL OldTpl;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ BOOLEAN Finished;
+ UINT8 *ProcBuf;
+ URB *Urb;
+ EFI_STATUS Status;
+
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ Ehc = (USB2_HC_DEV *) Context;
+
+ EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {
+ Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);
+
+ //
+ // Check the result of URB execution. If it is still
+ // active, check the next one.
+ //
+ Finished = EhcCheckUrbResult (Ehc, Urb);
+
+ if (!Finished) {
+ continue;
+ }
+
+ //
+ // Flush any PCI posted write transactions from a PCI host
+ // bridge to system memory.
+ //
+ Status = EhcFlushAsyncIntMap (Ehc, Urb);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));
+ }
+
+ //
+ // Allocate a buffer then copy the transferred data for user.
+ // If failed to allocate the buffer, update the URB for next
+ // round of transfer. Ignore the data of this round.
+ //
+ ProcBuf = NULL;
+
+ if (Urb->Result == EFI_USB_NOERROR) {
+ ASSERT (Urb->Completed <= Urb->DataLen);
+
+ ProcBuf = AllocatePool (Urb->Completed);
+
+ if (ProcBuf == NULL) {
+ EhcUpdateAsyncRequest (Ehc, Urb);
+ continue;
+ }
+
+ CopyMem (ProcBuf, Urb->Data, Urb->Completed);
+ }
+
+ EhcUpdateAsyncRequest (Ehc, Urb);
+
+ //
+ // Leave error recovery to its related device driver. A
+ // common case of the error recovery is to re-submit the
+ // interrupt transfer which is linked to the head of the
+ // list. This function scans from head to tail. So the
+ // re-submitted interrupt transfer's callback function
+ // will not be called again in this round. Don't touch this
+ // URB after the callback, it may have been removed by the
+ // callback.
+ //
+ if (Urb->Callback != NULL) {
+ //
+ // Restore the old TPL, USB bus maybe connect device in
+ // his callback. Some drivers may has a lower TPL restriction.
+ //
+ gBS->RestoreTPL (OldTpl);
+ (Urb->Callback) (ProcBuf, Urb->Completed, Urb->Context, Urb->Result);
+ OldTpl = gBS->RaiseTPL (EHC_TPL);
+ }
+
+ if (ProcBuf != NULL) {
+ FreePool (ProcBuf);
+ }
+ }
+
+ gBS->RestoreTPL (OldTpl);
+}
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
new file mode 100755
index 0000000..5ad2294
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
@@ -0,0 +1,94 @@
+## @file
+#
+# Component Description File For UsbBus Dxe Module.
+#
+# Usb Bus Dxe driver is used to enumerate and manage all attached usb devices.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UsbBusDxe
+ FILE_GUID = 240612B7-A063-11d4-9A3A-0090273FC14D
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = UsbBusDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = mUsbBusDriverBinding
+# COMPONENT_NAME = mUsbBusComponentName
+# COMPONENT_NAME2 = mUsbBusComponentName2
+#
+
+[Sources]
+ UsbDesc.c
+ UsbEnumer.c
+ ../../../../../../MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h
+ ../../../../../../MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
+ UsbHub.c
+ ../../../../../../MdeModulePkg/Bus/Usb/UsbBusDxe/ComponentName.c
+ ../../../../../../MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.h
+ ../../../../../../MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h
+ ../../../../../../MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c
+ ../../../../../../MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h
+ ../../../../../../MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ DevicePathLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ ReportStatusCodeLib
+
+
+[Protocols]
+ gEfiUsbIoProtocolGuid ## BY_START
+ gEfiDevicePathProtocolGuid ## BY_START
+ gEfiUsb2HcProtocolGuid ## TO_START
+ gEfiUsbHcProtocolGuid ## TO_START
+
+# [Event]
+# ##
+# # Periodic timer event for monitoring attach/detach event in port and enumerate attached usb devices.
+# #
+# EVENT_TYPE_PERIODIC_TIMER ## PRODUCES
+#
+#
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
new file mode 100644
index 0000000..68b0462
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
@@ -0,0 +1,991 @@
+/** @file
+
+ Manage Usb Descriptor List
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "UsbBus.h"
+
+#define USB_AUDIO_ENDPOINT_DESC_LENGTH 9
+
+/**
+ Free the interface setting descriptor.
+
+ @param Setting The descriptor to free.
+
+**/
+VOID
+UsbFreeInterfaceDesc (
+ IN USB_INTERFACE_SETTING *Setting
+ )
+{
+ USB_ENDPOINT_DESC *Ep;
+ UINTN Index;
+
+ if (Setting->Endpoints != NULL) {
+ //
+ // Each interface setting may have several endpoints, free them first.
+ //
+ for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {
+ Ep = Setting->Endpoints[Index];
+
+ if (Ep != NULL) {
+ FreePool (Ep);
+ }
+ }
+
+ //
+ // Only call FreePool() if NumEndpoints > 0.
+ //
+ if (Setting->Desc.NumEndpoints > 0) {
+ FreePool (Setting->Endpoints);
+ }
+ }
+
+ FreePool (Setting);
+}
+
+
+/**
+ Free a configuration descriptor with its interface
+ descriptors. It may be initialized partially.
+
+ @param Config The configuration descriptor to free.
+
+**/
+VOID
+UsbFreeConfigDesc (
+ IN USB_CONFIG_DESC *Config
+ )
+{
+ USB_INTERFACE_DESC *Interface;
+ UINTN Index;
+ UINTN SetIndex;
+
+ if (Config->Interfaces != NULL) {
+ //
+ // A configuration may have several interfaces, free the interface
+ //
+ for (Index = 0; Index < Config->Desc.NumInterfaces; Index++) {
+ Interface = Config->Interfaces[Index];
+
+ if (Interface == NULL) {
+ continue;
+ }
+
+ //
+ // Each interface may have several settings, free the settings
+ //
+ for (SetIndex = 0; SetIndex < Interface->NumOfSetting; SetIndex++) {
+ if (Interface->Settings[SetIndex] != NULL) {
+ UsbFreeInterfaceDesc (Interface->Settings[SetIndex]);
+ }
+ }
+
+ FreePool (Interface);
+ }
+
+ FreePool (Config->Interfaces);
+ }
+
+ FreePool (Config);
+
+}
+
+
+/**
+ Free a device descriptor with its configurations.
+
+ @param DevDesc The device descriptor.
+
+**/
+VOID
+UsbFreeDevDesc (
+ IN USB_DEVICE_DESC *DevDesc
+ )
+{
+ UINTN Index;
+
+ if (DevDesc->Configs != NULL) {
+ for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {
+ if (DevDesc->Configs[Index] != NULL) {
+ UsbFreeConfigDesc (DevDesc->Configs[Index]);
+ }
+ }
+
+ FreePool (DevDesc->Configs);
+ }
+
+ FreePool (DevDesc);
+}
+
+
+/**
+ Create a descriptor.
+
+ @param DescBuf The buffer of raw descriptor.
+ @param Len The length of the raw descriptor buffer.
+ @param Type The type of descriptor to create.
+ @param Consumed Number of bytes consumed.
+
+ @return Created descriptor or NULL.
+
+**/
+VOID *
+UsbCreateDesc (
+ IN UINT8 *DescBuf,
+ IN INTN Len,
+ IN UINT8 Type,
+ OUT INTN *Consumed
+ )
+{
+ USB_DESC_HEAD *Head;
+ INTN DescLen;
+ INTN CtrlLen;
+ INTN Offset;
+ VOID *Desc;
+
+ DescLen = 0;
+ CtrlLen = 0;
+ *Consumed = 0;
+
+ switch (Type) {
+ case USB_DESC_TYPE_DEVICE:
+ DescLen = sizeof (EFI_USB_DEVICE_DESCRIPTOR);
+ CtrlLen = sizeof (USB_DEVICE_DESC);
+ break;
+
+ case USB_DESC_TYPE_CONFIG:
+ DescLen = sizeof (EFI_USB_CONFIG_DESCRIPTOR);
+ CtrlLen = sizeof (USB_CONFIG_DESC);
+ break;
+
+ case USB_DESC_TYPE_INTERFACE:
+ DescLen = sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
+ CtrlLen = sizeof (USB_INTERFACE_SETTING);
+ break;
+
+ case USB_DESC_TYPE_ENDPOINT:
+ DescLen = sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
+ CtrlLen = sizeof (USB_ENDPOINT_DESC);
+ break;
+ }
+
+ //
+ // All the descriptor has a common LTV (Length, Type, Value)
+ // format. Skip the descriptor that isn't of this Type
+ //
+ Offset = 0;
+ Head = (USB_DESC_HEAD*)DescBuf;
+
+ while ((Offset < Len) && (Head->Type != Type)) {
+ Offset += Head->Len;
+ Head = (USB_DESC_HEAD*)(DescBuf + Offset);
+ }
+
+ if ((Len <= Offset) || (Len < Offset + DescLen) ||
+ (Head->Type != Type) || ((Head->Len != DescLen) && (Head->Len != USB_AUDIO_ENDPOINT_DESC_LENGTH))) {
+ DEBUG (( EFI_D_ERROR, "UsbCreateDesc: met mal-format descriptor\n"));
+ return NULL;
+ }
+
+ if(Head->Len != DescLen){
+ CtrlLen = DescLen;
+ }
+
+ Desc = AllocateZeroPool ((UINTN) CtrlLen);
+ if (Desc == NULL) {
+ return NULL;
+ }
+
+ CopyMem (Desc, Head, (UINTN) DescLen);
+
+ *Consumed = Offset + Head->Len;
+
+ return Desc;
+}
+
+
+/**
+ Parse an interface descriptor and its endpoints.
+
+ @param DescBuf The buffer of raw descriptor.
+ @param Len The length of the raw descriptor buffer.
+ @param Consumed The number of raw descriptor consumed.
+
+ @return The create interface setting or NULL if failed.
+
+**/
+USB_INTERFACE_SETTING *
+UsbParseInterfaceDesc (
+ IN UINT8 *DescBuf,
+ IN INTN Len,
+ OUT INTN *Consumed
+ )
+{
+ USB_INTERFACE_SETTING *Setting;
+ USB_ENDPOINT_DESC *Ep;
+ UINTN Index;
+ UINTN NumEp;
+ INTN Used;
+ INTN Offset;
+
+ *Consumed = 0;
+ Setting = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_INTERFACE, &Used);
+
+ if (Setting == NULL) {
+ DEBUG (( EFI_D_ERROR, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));
+ return NULL;
+ }
+
+ Offset = Used;
+
+ //
+ // Create an array to hold the interface's endpoints
+ //
+ NumEp = Setting->Desc.NumEndpoints;
+
+ DEBUG (( EFI_D_INFO, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
+ Setting->Desc.InterfaceNumber, Setting->Desc.AlternateSetting, (UINT32)NumEp));
+
+ if (NumEp == 0) {
+ goto ON_EXIT;
+ }
+
+ Setting->Endpoints = AllocateZeroPool (sizeof (USB_ENDPOINT_DESC *) * NumEp);
+
+ if (Setting->Endpoints == NULL) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Create the endpoints for this interface
+ //
+ for (Index = 0; Index < NumEp; Index++) {
+ Ep = UsbCreateDesc (DescBuf + Offset, Len - Offset, USB_DESC_TYPE_ENDPOINT, &Used);
+
+ if (Ep == NULL) {
+ DEBUG (( EFI_D_ERROR, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32)Index));
+ goto ON_ERROR;
+ }
+
+ Setting->Endpoints[Index] = Ep;
+ Offset += Used;
+ }
+
+
+ON_EXIT:
+ *Consumed = Offset;
+ return Setting;
+
+ON_ERROR:
+ UsbFreeInterfaceDesc (Setting);
+ return NULL;
+}
+
+
+/**
+ Parse the configuration descriptor and its interfaces.
+
+ @param DescBuf The buffer of raw descriptor.
+ @param Len The length of the raw descriptor buffer.
+
+ @return The created configuration descriptor.
+
+**/
+USB_CONFIG_DESC *
+UsbParseConfigDesc (
+ IN UINT8 *DescBuf,
+ IN INTN Len
+ )
+{
+ USB_CONFIG_DESC *Config;
+ USB_INTERFACE_SETTING *Setting;
+ USB_INTERFACE_DESC *Interface;
+ UINTN Index;
+ UINTN NumIf;
+ INTN Consumed;
+
+ ASSERT (DescBuf != NULL);
+
+ Config = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_CONFIG, &Consumed);
+
+ if (Config == NULL) {
+ return NULL;
+ }
+
+ //
+ // Initialize an array of setting for the configuration's interfaces.
+ //
+ NumIf = Config->Desc.NumInterfaces;
+ Config->Interfaces = AllocateZeroPool (sizeof (USB_INTERFACE_DESC *) * NumIf);
+
+ if (Config->Interfaces == NULL) {
+ goto ON_ERROR;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbParseConfigDesc: config %d has %d interfaces\n",
+ Config->Desc.ConfigurationValue, (UINT32)NumIf));
+
+ for (Index = 0; Index < NumIf; Index++) {
+ Interface = AllocateZeroPool (sizeof (USB_INTERFACE_DESC));
+
+ if (Interface == NULL) {
+ goto ON_ERROR;
+ }
+
+ Config->Interfaces[Index] = Interface;
+ }
+
+ //
+ // If a configuration has several interfaces, these interfaces are
+ // numbered from zero to n. If a interface has several settings,
+ // these settings are also number from zero to m. The interface
+ // setting must be organized as |interface 0, setting 0|interface 0
+ // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
+ // USB2.0 spec, page 267.
+ //
+ DescBuf += Consumed;
+ Len -= Consumed;
+
+ //
+ // Make allowances for devices that return extra data at the
+ // end of their config descriptors
+ //
+ while (Len >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) {
+ Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);
+
+ if (Setting == NULL) {
+ DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: failed to parse interface setting\n"));
+ goto ON_ERROR;
+
+ } else if (Setting->Desc.InterfaceNumber >= NumIf) {
+ DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
+
+ UsbFreeInterfaceDesc (Setting);
+ goto ON_ERROR;
+ }
+
+ //
+ // Insert the descriptor to the corresponding set.
+ //
+ Interface = Config->Interfaces[Setting->Desc.InterfaceNumber];
+
+ if (Interface->NumOfSetting >= USB_MAX_INTERFACE_SETTING) {
+ goto ON_ERROR;
+ }
+
+ Interface->Settings[Interface->NumOfSetting] = Setting;
+ Interface->NumOfSetting++;
+
+ DescBuf += Consumed;
+ Len -= Consumed;
+ }
+
+ return Config;
+
+ON_ERROR:
+ UsbFreeConfigDesc (Config);
+ return NULL;
+}
+
+
+/**
+ USB standard control transfer support routine. This
+ function is used by USB device. It is possible that
+ the device's interfaces are still waiting to be
+ enumerated.
+
+ @param UsbDev The usb device.
+ @param Direction The direction of data transfer.
+ @param Type Standard / class specific / vendor specific.
+ @param Target The receiving target.
+ @param Request Which request.
+ @param Value The wValue parameter of the request.
+ @param Index The wIndex parameter of the request.
+ @param Buf The buffer to receive data into / transmit from.
+ @param Length The length of the buffer.
+
+ @retval EFI_SUCCESS The control request is executed.
+ @retval EFI_DEVICE_ERROR Failed to execute the control transfer.
+
+**/
+EFI_STATUS
+UsbCtrlRequest (
+ IN USB_DEVICE *UsbDev,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINTN Type,
+ IN UINTN Target,
+ IN UINTN Request,
+ IN UINT16 Value,
+ IN UINT16 Index,
+ IN OUT VOID *Buf,
+ IN UINTN Length
+ )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS Status;
+ UINT32 Result;
+ UINTN Len;
+
+ ASSERT ((UsbDev != NULL) && (UsbDev->Bus != NULL));
+
+ DevReq.RequestType = USB_REQUEST_TYPE (Direction, Type, Target);
+ DevReq.Request = (UINT8) Request;
+ DevReq.Value = Value;
+ DevReq.Index = Index;
+ DevReq.Length = (UINT16) Length;
+
+ Len = Length;
+ Status = UsbHcControlTransfer (
+ UsbDev->Bus,
+ UsbDev->Address,
+ UsbDev->Speed,
+ UsbDev->MaxPacket0,
+ &DevReq,
+ Direction,
+ Buf,
+ &Len,
+ USB_GENERAL_DEVICE_REQUEST_TIMEOUT,
+ &UsbDev->Translator,
+ &Result
+ );
+
+ return Status;
+}
+
+
+/**
+ Get the standard descriptors.
+
+ @param UsbDev The USB device to read descriptor from.
+ @param DescType The type of descriptor to read.
+ @param DescIndex The index of descriptor to read.
+ @param LangId Language ID, only used to get string, otherwise set
+ it to 0.
+ @param Buf The buffer to hold the descriptor read.
+ @param Length The length of the buffer.
+
+ @retval EFI_SUCCESS The descriptor is read OK.
+ @retval Others Failed to retrieve the descriptor.
+
+**/
+EFI_STATUS
+UsbCtrlGetDesc (
+ IN USB_DEVICE *UsbDev,
+ IN UINTN DescType,
+ IN UINTN DescIndex,
+ IN UINT16 LangId,
+ OUT VOID *Buf,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ UsbDev,
+ EfiUsbDataIn,
+ USB_REQ_TYPE_STANDARD,
+ USB_TARGET_DEVICE,
+ USB_REQ_GET_DESCRIPTOR,
+ (UINT16) ((DescType << 8) | DescIndex),
+ LangId,
+ Buf,
+ Length
+ );
+
+ return Status;
+}
+
+
+/**
+ Return the max packet size for endpoint zero. This function
+ is the first function called to get descriptors during bus
+ enumeration.
+
+ @param UsbDev The usb device.
+
+ @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved.
+ @retval EFI_DEVICE_ERROR Failed to retrieve it.
+
+**/
+EFI_STATUS
+UsbGetMaxPacketSize0 (
+ IN USB_DEVICE *UsbDev
+ )
+{
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc;
+ EFI_STATUS Status;
+ UINTN Index;
+
+
+ //
+ // Get the first 8 bytes of the device descriptor which contains
+ // max packet size for endpoint 0, which is at least 8.
+ //
+ for (Index = 0; Index < 3; Index++) {
+ Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_DEVICE, 0, 0, &DevDesc, 8);
+
+ if (!EFI_ERROR (Status)) {
+ if ((DevDesc.BcdUSB == 0x0300) && (DevDesc.MaxPacketSize0 == 9)) {
+ UsbDev->MaxPacket0 = 1 << 9;
+ return EFI_SUCCESS;
+ }
+ UsbDev->MaxPacket0 = DevDesc.MaxPacketSize0;
+ return EFI_SUCCESS;
+ }
+
+ gBS->Stall (USB_RETRY_MAX_PACK_SIZE_STALL);
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+
+/**
+ Get the device descriptor for the device.
+
+ @param UsbDev The Usb device to retrieve descriptor from.
+
+ @retval EFI_SUCCESS The device descriptor is returned.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+
+**/
+EFI_STATUS
+UsbGetDevDesc (
+ IN USB_DEVICE *UsbDev
+ )
+{
+ USB_DEVICE_DESC *DevDesc;
+ EFI_STATUS Status;
+
+ DevDesc = AllocateZeroPool (sizeof (USB_DEVICE_DESC));
+
+ if (DevDesc == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = UsbCtrlGetDesc (
+ UsbDev,
+ USB_DESC_TYPE_DEVICE,
+ 0,
+ 0,
+ DevDesc,
+ sizeof (EFI_USB_DEVICE_DESCRIPTOR)
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (DevDesc);
+ } else {
+ UsbDev->DevDesc = DevDesc;
+ }
+
+ return Status;
+}
+
+
+/**
+ Retrieve the indexed string for the language. It requires two
+ steps to get a string, first to get the string's length. Then
+ the string itself.
+
+ @param UsbDev The usb device.
+ @param Index The index the string to retrieve.
+ @param LangId Language ID.
+
+ @return The created string descriptor or NULL.
+
+**/
+EFI_USB_STRING_DESCRIPTOR *
+UsbGetOneString (
+ IN USB_DEVICE *UsbDev,
+ IN UINT8 Index,
+ IN UINT16 LangId
+ )
+{
+ EFI_USB_STRING_DESCRIPTOR Desc;
+ EFI_STATUS Status;
+ UINT8 *Buf;
+
+ //
+ // First get two bytes which contains the string length.
+ //
+ Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2);
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Buf = AllocateZeroPool (Desc.Length);
+
+ if (Buf == NULL) {
+ return NULL;
+ }
+
+ Status = UsbCtrlGetDesc (
+ UsbDev,
+ USB_DESC_TYPE_STRING,
+ Index,
+ LangId,
+ Buf,
+ Desc.Length
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Buf);
+ return NULL;
+ }
+
+ return (EFI_USB_STRING_DESCRIPTOR *) Buf;
+}
+
+
+/**
+ Build the language ID table for string descriptors.
+
+ @param UsbDev The Usb device.
+
+ @retval EFI_UNSUPPORTED This device doesn't support string table.
+
+**/
+EFI_STATUS
+UsbBuildLangTable (
+ IN USB_DEVICE *UsbDev
+ )
+{
+ EFI_USB_STRING_DESCRIPTOR *Desc;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Max;
+ UINT16 *Point;
+
+ //
+ // The string of language ID zero returns the supported languages
+ //
+ Desc = UsbGetOneString (UsbDev, 0, 0);
+
+ if (Desc == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Desc->Length < 4) {
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ Status = EFI_SUCCESS;
+
+ Max = (Desc->Length - 2) / 2;
+ Max = MIN(Max, USB_MAX_LANG_ID);
+
+ Point = Desc->String;
+ for (Index = 0; Index < Max; Index++) {
+ UsbDev->LangId[Index] = *Point;
+ Point++;
+ }
+
+ UsbDev->TotalLangId = (UINT16)Max;
+
+ON_EXIT:
+ gBS->FreePool (Desc);
+ return Status;
+}
+
+
+/**
+ Retrieve the indexed configure for the device. USB device
+ returns the configuration together with the interfaces for
+ this configuration. Configuration descriptor is also of
+ variable length.
+
+ @param UsbDev The Usb interface.
+ @param Index The index of the configuration.
+
+ @return The created configuration descriptor.
+
+**/
+EFI_USB_CONFIG_DESCRIPTOR *
+UsbGetOneConfig (
+ IN USB_DEVICE *UsbDev,
+ IN UINT8 Index
+ )
+{
+ EFI_USB_CONFIG_DESCRIPTOR Desc;
+ EFI_STATUS Status;
+ VOID *Buf;
+
+ //
+ // First get four bytes which contains the total length
+ // for this configuration.
+ //
+ Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, &Desc, 8);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get descript length(%d) %r\n",
+ Desc.TotalLength, Status));
+
+ return NULL;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbGetOneConfig: total length is %d\n", Desc.TotalLength));
+
+ Buf = AllocateZeroPool (Desc.TotalLength);
+
+ if (Buf == NULL) {
+ return NULL;
+ }
+
+ Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, Buf, Desc.TotalLength);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get full descript %r\n", Status));
+
+ FreePool (Buf);
+ return NULL;
+ }
+
+ return Buf;
+}
+
+
+/**
+ Build the whole array of descriptors. This function must
+ be called after UsbGetMaxPacketSize0 returns the max packet
+ size correctly for endpoint 0.
+
+ @param UsbDev The Usb device.
+
+ @retval EFI_SUCCESS The descriptor table is build.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor.
+
+**/
+EFI_STATUS
+UsbBuildDescTable (
+ IN USB_DEVICE *UsbDev
+ )
+{
+ EFI_USB_CONFIG_DESCRIPTOR *Config;
+ USB_DEVICE_DESC *DevDesc;
+ USB_CONFIG_DESC *ConfigDesc;
+ UINT8 NumConfig;
+ EFI_STATUS Status;
+ UINT8 Index;
+
+ //
+ // Get the device descriptor, then allocate the configure
+ // descriptor pointer array to hold configurations.
+ //
+ Status = UsbGetDevDesc (UsbDev);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status));
+ return Status;
+ }
+
+ DevDesc = UsbDev->DevDesc;
+ NumConfig = DevDesc->Desc.NumConfigurations;
+ DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));
+
+ if (DevDesc->Configs == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbBuildDescTable: device has %d configures\n", NumConfig));
+
+ //
+ // Read each configurations, then parse them
+ //
+ for (Index = 0; Index < NumConfig; Index++) {
+ Config = UsbGetOneConfig (UsbDev, Index);
+
+ if (Config == NULL) {
+ DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to get configure (index %d)\n", Index));
+
+ //
+ // If we can get the default descriptor, it is likely that the
+ // device is still operational.
+ //
+ if (Index == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ break;
+ }
+
+ ConfigDesc = UsbParseConfigDesc ((UINT8 *) Config, Config->TotalLength);
+
+ FreePool (Config);
+
+ if (ConfigDesc == NULL) {
+ DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index));
+
+ //
+ // If we can get the default descriptor, it is likely that the
+ // device is still operational.
+ //
+ if (Index == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ break;
+ }
+
+ DevDesc->Configs[Index] = ConfigDesc;
+ }
+
+ //
+ // Don't return error even this function failed because
+ // it is possible for the device to not support strings.
+ //
+ Status = UsbBuildLangTable (UsbDev);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_INFO, "UsbBuildDescTable: get language ID table %r\n", Status));
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set the device's address.
+
+ @param UsbDev The device to set address to.
+ @param Address The address to set.
+
+ @retval EFI_SUCCESS The device is set to the address.
+ @retval Others Failed to set the device address.
+
+**/
+EFI_STATUS
+UsbSetAddress (
+ IN USB_DEVICE *UsbDev,
+ IN UINT8 Address
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ UsbDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_STANDARD,
+ USB_TARGET_DEVICE,
+ USB_REQ_SET_ADDRESS,
+ Address,
+ 0,
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ Set the device's configuration. This function changes
+ the device's internal state. UsbSelectConfig changes
+ the Usb bus's internal state.
+
+ @param UsbDev The USB device to set configure to.
+ @param ConfigIndex The configure index to set.
+
+ @retval EFI_SUCCESS The device is configured now.
+ @retval Others Failed to set the device configure.
+
+**/
+EFI_STATUS
+UsbSetConfig (
+ IN USB_DEVICE *UsbDev,
+ IN UINT8 ConfigIndex
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ UsbDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_STANDARD,
+ USB_TARGET_DEVICE,
+ USB_REQ_SET_CONFIG,
+ ConfigIndex,
+ 0,
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ Usb UsbIo interface to clear the feature. This is should
+ only be used by HUB which is considered a device driver
+ on top of the UsbIo interface.
+
+ @param UsbIo The UsbIo interface.
+ @param Target The target of the transfer: endpoint/device.
+ @param Feature The feature to clear.
+ @param Index The wIndex parameter.
+
+ @retval EFI_SUCCESS The device feature is cleared.
+ @retval Others Failed to clear the feature.
+
+**/
+EFI_STATUS
+UsbIoClearFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINTN Target,
+ IN UINT16 Feature,
+ IN UINT16 Index
+ )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ UINT32 UsbResult;
+ EFI_STATUS Status;
+
+ DevReq.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, Target);
+ DevReq.Request = USB_REQ_CLEAR_FEATURE;
+ DevReq.Value = Feature;
+ DevReq.Index = Index;
+ DevReq.Length = 0;
+
+ Status = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbNoData,
+ USB_CLEAR_FEATURE_REQUEST_TIMEOUT,
+ NULL,
+ 0,
+ &UsbResult
+ );
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
new file mode 100755
index 0000000..cffc2fa
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
@@ -0,0 +1,1037 @@
+/** @file
+
+ Usb bus enumeration support.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "UsbBus.h"
+
+/**
+ Return the endpoint descriptor in this interface.
+
+ @param UsbIf The interface to search in.
+ @param EpAddr The address of the endpoint to return.
+
+ @return The endpoint descriptor or NULL.
+
+**/
+USB_ENDPOINT_DESC *
+UsbGetEndpointDesc (
+ IN USB_INTERFACE *UsbIf,
+ IN UINT8 EpAddr
+ )
+{
+ USB_ENDPOINT_DESC *EpDesc;
+ UINT8 Index;
+ UINT8 NumEndpoints;
+
+ NumEndpoints = UsbIf->IfSetting->Desc.NumEndpoints;
+
+ for (Index = 0; Index < NumEndpoints; Index++) {
+ EpDesc = UsbIf->IfSetting->Endpoints[Index];
+
+ if (EpDesc->Desc.EndpointAddress == EpAddr) {
+ return EpDesc;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ Free the resource used by USB interface.
+
+ @param UsbIf The USB interface to free.
+
+**/
+VOID
+UsbFreeInterface (
+ IN USB_INTERFACE *UsbIf
+ )
+{
+ UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ UsbIf->Handle,
+ &gEfiDevicePathProtocolGuid,
+ UsbIf->DevicePath,
+ &gEfiUsbIoProtocolGuid,
+ &UsbIf->UsbIo,
+ NULL
+ );
+
+ if (UsbIf->DevicePath != NULL) {
+ FreePool (UsbIf->DevicePath);
+ }
+
+ FreePool (UsbIf);
+}
+
+
+/**
+ Create an interface for the descriptor IfDesc. Each
+ device's configuration can have several interfaces.
+
+ @param Device The device has the interface descriptor.
+ @param IfDesc The interface descriptor.
+
+ @return The created USB interface for the descriptor, or NULL.
+
+**/
+USB_INTERFACE *
+UsbCreateInterface (
+ IN USB_DEVICE *Device,
+ IN USB_INTERFACE_DESC *IfDesc
+ )
+{
+ USB_DEVICE_PATH UsbNode;
+ USB_INTERFACE *UsbIf;
+ USB_INTERFACE *HubIf;
+ EFI_STATUS Status;
+
+ UsbIf = AllocateZeroPool (sizeof (USB_INTERFACE));
+
+ if (UsbIf == NULL) {
+ return NULL;
+ }
+
+ UsbIf->Signature = USB_INTERFACE_SIGNATURE;
+ UsbIf->Device = Device;
+ UsbIf->IfDesc = IfDesc;
+ ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);
+ UsbIf->IfSetting = IfDesc->Settings[IfDesc->ActiveIndex];
+
+ CopyMem (
+ &(UsbIf->UsbIo),
+ &mUsbIoProtocol,
+ sizeof (EFI_USB_IO_PROTOCOL)
+ );
+
+ //
+ // Install protocols for USBIO and device path
+ //
+ UsbNode.Header.Type = MESSAGING_DEVICE_PATH;
+ UsbNode.Header.SubType = MSG_USB_DP;
+ UsbNode.ParentPortNumber = Device->ParentPort;
+ UsbNode.InterfaceNumber = UsbIf->IfSetting->Desc.InterfaceNumber;
+
+ SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
+
+ HubIf = Device->ParentIf;
+ ASSERT (HubIf != NULL);
+
+ UsbIf->DevicePath = AppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header);
+
+ if (UsbIf->DevicePath == NULL) {
+ DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to create device path\n"));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &UsbIf->Handle,
+ &gEfiDevicePathProtocolGuid,
+ UsbIf->DevicePath,
+ &gEfiUsbIoProtocolGuid,
+ &UsbIf->UsbIo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to install UsbIo - %r\n", Status));
+ goto ON_ERROR;
+ }
+
+ //
+ // Open USB Host Controller Protocol by Child
+ //
+ Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);
+
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ &UsbIf->Handle,
+ &gEfiDevicePathProtocolGuid,
+ UsbIf->DevicePath,
+ &gEfiUsbIoProtocolGuid,
+ &UsbIf->UsbIo,
+ NULL
+ );
+
+ DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to open host for child - %r\n", Status));
+ goto ON_ERROR;
+ }
+
+ return UsbIf;
+
+ON_ERROR:
+ if (UsbIf->DevicePath != NULL) {
+ FreePool (UsbIf->DevicePath);
+ }
+
+ FreePool (UsbIf);
+ return NULL;
+}
+
+
+/**
+ Free the resource used by this USB device.
+
+ @param Device The USB device to free.
+
+**/
+VOID
+UsbFreeDevice (
+ IN USB_DEVICE *Device
+ )
+{
+ if (Device->DevDesc != NULL) {
+ UsbFreeDevDesc (Device->DevDesc);
+ }
+
+ gBS->FreePool (Device);
+}
+
+
+/**
+ Create a device which is on the parent's ParentPort port.
+
+ @param ParentIf The parent HUB interface.
+ @param ParentPort The port on the HUB this device is connected to.
+
+ @return Created USB device, Or NULL.
+
+**/
+USB_DEVICE *
+UsbCreateDevice (
+ IN USB_INTERFACE *ParentIf,
+ IN UINT8 ParentPort
+ )
+{
+ USB_DEVICE *Device;
+
+ ASSERT (ParentIf != NULL);
+
+ Device = AllocateZeroPool (sizeof (USB_DEVICE));
+
+ if (Device == NULL) {
+ return NULL;
+ }
+
+ Device->Bus = ParentIf->Device->Bus;
+ Device->MaxPacket0 = 8;
+ Device->ParentAddr = ParentIf->Device->Address;
+ Device->ParentIf = ParentIf;
+ Device->ParentPort = ParentPort;
+ Device->Tier = (UINT8)(ParentIf->Device->Tier + 1);
+ return Device;
+}
+
+
+/**
+ Connect the USB interface with its driver. EFI USB bus will
+ create a USB interface for each separate interface descriptor.
+
+ @param UsbIf The interface to connect driver to.
+
+ @return EFI_SUCCESS Interface is managed by some driver.
+ @return Others Failed to locate a driver for this interface.
+
+**/
+EFI_STATUS
+UsbConnectDriver (
+ IN USB_INTERFACE *UsbIf
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Hub is maintained by the USB bus driver. Otherwise try to
+ // connect drivers with this interface
+ //
+ if (UsbIsHubInterface (UsbIf)) {
+ DEBUG ((EFI_D_INFO, "UsbConnectDriver: found a hub device\n"));
+ Status = mUsbHubApi.Init (UsbIf);
+
+ } else {
+ //
+ // This function is called in both UsbIoControlTransfer and
+ // the timer callback in hub enumeration. So, at least it is
+ // called at TPL_CALLBACK. Some driver sitting on USB has
+ // twisted TPL used. It should be no problem for us to connect
+ // or disconnect at CALLBACK.
+ //
+
+ //
+ // Only recursively wanted usb child device
+ //
+ if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {
+ OldTpl = UsbGetCurrentTpl ();
+ DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
+
+ gBS->RestoreTPL (TPL_CALLBACK);
+
+ Status = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
+ UsbIf->IsManaged = (BOOLEAN)!EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl()));
+ ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
+
+ gBS->RaiseTPL (OldTpl);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Select an alternate setting for the interface.
+ Each interface can have several mutually exclusive
+ settings. Only one setting is active. It will
+ also reset its endpoints' toggle to zero.
+
+ @param IfDesc The interface descriptor to set.
+ @param Alternate The alternate setting number to locate.
+
+ @retval EFI_NOT_FOUND There is no setting with this alternate index.
+ @retval EFI_SUCCESS The interface is set to Alternate setting.
+
+**/
+EFI_STATUS
+UsbSelectSetting (
+ IN USB_INTERFACE_DESC *IfDesc,
+ IN UINT8 Alternate
+ )
+{
+ USB_INTERFACE_SETTING *Setting;
+ UINT8 Index;
+
+ //
+ // Locate the active alternate setting
+ //
+ Setting = NULL;
+
+ for (Index = 0; Index < IfDesc->NumOfSetting; Index++) {
+ ASSERT (Index < USB_MAX_INTERFACE_SETTING);
+ Setting = IfDesc->Settings[Index];
+
+ if (Setting->Desc.AlternateSetting == Alternate) {
+ break;
+ }
+ }
+
+ if (Index == IfDesc->NumOfSetting) {
+ return EFI_NOT_FOUND;
+ }
+
+ IfDesc->ActiveIndex = Index;
+
+ ASSERT (Setting != NULL);
+ DEBUG ((EFI_D_INFO, "UsbSelectSetting: setting %d selected for interface %d\n",
+ Alternate, Setting->Desc.InterfaceNumber));
+
+ //
+ // Reset the endpoint toggle to zero
+ //
+ for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {
+ Setting->Endpoints[Index]->Toggle = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Select a new configuration for the device. Each
+ device may support several configurations.
+
+ @param Device The device to select configuration.
+ @param ConfigValue The index of the configuration ( != 0).
+
+ @retval EFI_NOT_FOUND There is no configuration with the index.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
+ @retval EFI_SUCCESS The configuration is selected.
+
+**/
+EFI_STATUS
+UsbSelectConfig (
+ IN USB_DEVICE *Device,
+ IN UINT8 ConfigValue
+ )
+{
+ USB_DEVICE_DESC *DevDesc;
+ USB_CONFIG_DESC *ConfigDesc;
+ USB_INTERFACE_DESC *IfDesc;
+ USB_INTERFACE *UsbIf;
+ EFI_STATUS Status;
+ UINT8 Index;
+
+ //
+ // Locate the active config, then set the device's pointer
+ //
+ DevDesc = Device->DevDesc;
+ ConfigDesc = NULL;
+
+ for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {
+ ConfigDesc = DevDesc->Configs[Index];
+
+ if (ConfigDesc->Desc.ConfigurationValue == ConfigValue) {
+ break;
+ }
+ }
+
+ if (Index == DevDesc->Desc.NumConfigurations) {
+ return EFI_NOT_FOUND;
+ }
+
+ Device->ActiveConfig = ConfigDesc;
+
+ DEBUG ((EFI_D_INFO, "UsbSelectConfig: config %d selected for device %d\n",
+ ConfigValue, Device->Address));
+
+ //
+ // Create interfaces for each USB interface descriptor.
+ //
+ for (Index = 0; Index < ConfigDesc->Desc.NumInterfaces; Index++) {
+ //
+ // First select the default interface setting, and reset
+ // the endpoint toggles to zero for its endpoints.
+ //
+ IfDesc = ConfigDesc->Interfaces[Index];
+ UsbSelectSetting (IfDesc, IfDesc->Settings[0]->Desc.AlternateSetting);
+
+ //
+ // Create a USB_INTERFACE and install USB_IO and other protocols
+ //
+ UsbIf = UsbCreateInterface (Device, ConfigDesc->Interfaces[Index]);
+
+ if (UsbIf == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ASSERT (Index < USB_MAX_INTERFACE);
+ Device->Interfaces[Index] = UsbIf;
+
+ //
+ // Connect the device to drivers, if it failed, ignore
+ // the error. Don't let the unsupported interfaces to block
+ // the supported interfaces.
+ //
+ Status = UsbConnectDriver (UsbIf);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "UsbSelectConfig: failed to connect driver %r, ignored\n", Status));
+ }
+ }
+
+ Device->NumOfInterface = Index;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Disconnect the USB interface with its driver.
+
+ @param UsbIf The interface to disconnect driver from.
+
+**/
+VOID
+UsbDisconnectDriver (
+ IN USB_INTERFACE *UsbIf
+ )
+{
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+
+ //
+ // Release the hub if it's a hub controller, otherwise
+ // disconnect the driver if it is managed by other drivers.
+ //
+ if (UsbIf->IsHub) {
+ UsbIf->HubApi->Release (UsbIf);
+
+ } else if (UsbIf->IsManaged) {
+ //
+ // This function is called in both UsbIoControlTransfer and
+ // the timer callback in hub enumeration. So, at least it is
+ // called at TPL_CALLBACK. Some driver sitting on USB has
+ // twisted TPL used. It should be no problem for us to connect
+ // or disconnect at CALLBACK.
+ //
+ OldTpl = UsbGetCurrentTpl ();
+ DEBUG ((EFI_D_INFO, "UsbDisconnectDriver: old TPL is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
+
+ gBS->RestoreTPL (TPL_CALLBACK);
+
+ Status = gBS->DisconnectController (UsbIf->Handle, NULL, NULL);
+ UsbIf->IsManaged = FALSE;
+
+ DEBUG (( EFI_D_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl(), Status));
+ ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
+
+ gBS->RaiseTPL (OldTpl);
+ }
+}
+
+
+/**
+ Remove the current device configuration.
+
+ @param Device The USB device to remove configuration from.
+
+**/
+VOID
+UsbRemoveConfig (
+ IN USB_DEVICE *Device
+ )
+{
+ USB_INTERFACE *UsbIf;
+ UINTN Index;
+
+ //
+ // Remove each interface of the device
+ //
+ for (Index = 0; Index < Device->NumOfInterface; Index++) {
+ ASSERT (Index < USB_MAX_INTERFACE);
+ UsbIf = Device->Interfaces[Index];
+
+ if (UsbIf == NULL) {
+ continue;
+ }
+
+ UsbDisconnectDriver (UsbIf);
+ UsbFreeInterface (UsbIf);
+ Device->Interfaces[Index] = NULL;
+ }
+
+ Device->ActiveConfig = NULL;
+ Device->NumOfInterface = 0;
+}
+
+
+/**
+ Remove the device and all its children from the bus.
+
+ @param Device The device to remove.
+
+ @retval EFI_SUCCESS The device is removed.
+
+**/
+EFI_STATUS
+UsbRemoveDevice (
+ IN USB_DEVICE *Device
+ )
+{
+ USB_BUS *Bus;
+ USB_DEVICE *Child;
+ EFI_STATUS Status;
+ UINTN Index;
+
+ Bus = Device->Bus;
+
+ //
+ // Remove all the devices on its downstream ports. Search from devices[1].
+ // Devices[0] is the root hub.
+ //
+ for (Index = 1; Index < Bus->MaxDevices; Index++) {
+ Child = Bus->Devices[Index];
+
+ if ((Child == NULL) || (Child->ParentAddr != Device->Address)) {
+ continue;
+ }
+
+ Status = UsbRemoveDevice (Child);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbRemoveDevice: failed to remove child, ignore error\n"));
+ Bus->Devices[Index] = NULL;
+ }
+ }
+
+ UsbRemoveConfig (Device);
+
+ DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address));
+
+ ASSERT (Device->Address < Bus->MaxDevices);
+ Bus->Devices[Device->Address] = NULL;
+ UsbFreeDevice (Device);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Find the child device on the hub's port.
+
+ @param HubIf The hub interface.
+ @param Port The port of the hub this child is connected to.
+
+ @return The device on the hub's port, or NULL if there is none.
+
+**/
+USB_DEVICE *
+UsbFindChild (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port
+ )
+{
+ USB_DEVICE *Device;
+ USB_BUS *Bus;
+ UINTN Index;
+
+ Bus = HubIf->Device->Bus;
+
+ //
+ // Start checking from device 1, device 0 is the root hub
+ //
+ for (Index = 1; Index < Bus->MaxDevices; Index++) {
+ Device = Bus->Devices[Index];
+
+ if ((Device != NULL) && (Device->ParentAddr == HubIf->Device->Address) &&
+ (Device->ParentPort == Port)) {
+
+ return Device;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ Enumerate and configure the new device on the port of this HUB interface.
+
+ @param HubIf The HUB that has the device connected.
+ @param Port The port index of the hub (started with zero).
+
+ @retval EFI_SUCCESS The device is enumerated (added or removed).
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device.
+ @retval Others Failed to enumerate the device.
+
+**/
+EFI_STATUS
+UsbEnumerateNewDev (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port
+ )
+{
+ USB_BUS *Bus;
+ USB_HUB_API *HubApi;
+ USB_DEVICE *Child;
+ USB_DEVICE *Parent;
+ EFI_USB_PORT_STATUS PortState;
+ UINTN Address;
+ UINT8 Config;
+ EFI_STATUS Status;
+
+ Parent = HubIf->Device;
+ Bus = Parent->Bus;
+ HubApi = HubIf->HubApi;
+ Address = Bus->MaxDevices;
+
+ gBS->Stall (USB_WAIT_PORT_STABLE_STALL);
+
+ //
+ // Hub resets the device for at least 10 milliseconds.
+ // Host learns device speed. If device is of low/full speed
+ // and the hub is a EHCI root hub, ResetPort will release
+ // the device to its companion UHCI and return an error.
+ //
+ Status = HubApi->ResetPort (HubIf, Port);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));
+
+ return Status;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port));
+
+ Child = UsbCreateDevice (HubIf, Port);
+
+ if (Child == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // OK, now identify the device speed. After reset, hub
+ // fully knows the actual device speed.
+ //
+ Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get speed of port %d\n", Port));
+ goto ON_ERROR;
+ }
+
+ if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: No device presented at port %d\n", Port));
+ goto ON_ERROR;
+ } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
+ Child->Speed = EFI_USB_SPEED_SUPER;
+ Child->MaxPacket0 = 512;
+ } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
+ Child->Speed = EFI_USB_SPEED_HIGH;
+ Child->MaxPacket0 = 64;
+ } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
+ Child->Speed = EFI_USB_SPEED_LOW;
+ Child->MaxPacket0 = 8;
+ } else {
+ Child->Speed = EFI_USB_SPEED_FULL;
+ Child->MaxPacket0 = 8;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));
+
+ if (((Child->Speed == EFI_USB_SPEED_LOW) || (Child->Speed == EFI_USB_SPEED_FULL)) &&
+ (Parent->Speed == EFI_USB_SPEED_HIGH)) {
+ //
+ // If the child is a low or full speed device, it is necessary to
+ // set the transaction translator. Port TT is 1-based.
+ // This is quite simple:
+ // 1. if parent is of high speed, then parent is our translator
+ // 2. otherwise use parent's translator.
+ //
+ Child->Translator.TranslatorHubAddress = Parent->Address;
+ Child->Translator.TranslatorPortNumber = (UINT8) (Port + 1);
+ } else {
+ Child->Translator = Parent->Translator;
+ }
+ DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device uses translator (%d, %d)\n",
+ Child->Translator.TranslatorHubAddress,
+ Child->Translator.TranslatorPortNumber));
+
+ //
+ // After port is reset, hub establishes a signal path between
+ // the device and host (DEFALUT state). Device's registers are
+ // reset, use default address 0 (host enumerates one device at
+ // a time) , and ready to respond to control transfer at EP 0.
+ //
+
+ //
+ // Host assigns an address to the device. Device completes the
+ // status stage with default address, then switches to new address.
+ // ADDRESS state. Address zero is reserved for root hub.
+ //
+ ASSERT (Bus->MaxDevices <= 256);
+ for (Address = 1; Address < Bus->MaxDevices; Address++) {
+ if (Bus->Devices[Address] == NULL) {
+ break;
+ }
+ }
+
+ if (Address >= Bus->MaxDevices) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: address pool is full for port %d\n", Port));
+
+ Status = EFI_ACCESS_DENIED;
+ goto ON_ERROR;
+ }
+
+ Status = UsbSetAddress (Child, (UINT8)Address);
+ Child->Address = (UINT8)Address;
+ Bus->Devices[Address] = Child;
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status));
+ goto ON_ERROR;
+ }
+
+ gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
+
+ DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));
+
+ //
+ // Host sends a Get_Descriptor request to learn the max packet
+ // size of default pipe (only part of the device's descriptor).
+ //
+ Status = UsbGetMaxPacketSize0 (Child);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status));
+ goto ON_ERROR;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0));
+
+ //
+ // Host learns about the device's abilities by requesting device's
+ // entire descriptions.
+ //
+ Status = UsbBuildDescTable (Child);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status));
+ goto ON_ERROR;
+ }
+
+ //
+ // Select a default configuration: UEFI must set the configuration
+ // before the driver can connect to the device.
+ //
+ Config = Child->DevDesc->Configs[0]->Desc.ConfigurationValue;
+ Status = UsbSetConfig (Child, Config);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status));
+ goto ON_ERROR;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address));
+
+ //
+ // Host assigns and loads a device driver.
+ //
+ Status = UsbSelectConfig (Child, Config);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to create interfaces - %r\n", Status));
+ goto ON_ERROR;
+ }
+
+ //
+ // Report Status Code to indicate USB device has been detected by hotplug
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG),
+ Bus->DevicePath
+ );
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ if (Address != Bus->MaxDevices) {
+ Bus->Devices[Address] = NULL;
+ }
+
+ if (Child != NULL) {
+ UsbFreeDevice (Child);
+ }
+
+ return Status;
+}
+
+
+/**
+ Process the events on the port.
+
+ @param HubIf The HUB that has the device connected.
+ @param Port The port index of the hub (started with zero).
+
+ @retval EFI_SUCCESS The device is enumerated (added or removed).
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device.
+ @retval Others Failed to enumerate the device.
+
+**/
+EFI_STATUS
+UsbEnumeratePort (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port
+ )
+{
+ USB_HUB_API *HubApi;
+ USB_DEVICE *Child;
+ EFI_USB_PORT_STATUS PortState;
+ EFI_STATUS Status;
+
+ Child = NULL;
+ HubApi = HubIf->HubApi;
+
+ //
+ // Host learns of the new device by polling the hub for port changes.
+ //
+ Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbEnumeratePort: failed to get state of port %d\n", Port));
+ return Status;
+ }
+
+ //
+ // Only handle connection/enable/overcurrent/reset change.
+ // Usb super speed hub may report other changes, such as warm reset change. Ignore them.
+ //
+ if ((PortState.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",
+ Port, PortState.PortStatus, PortState.PortChangeStatus, HubIf));
+
+ //
+ // This driver only process two kinds of events now: over current and
+ // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.
+ // ENABLE/RESET is used to reset port. SUSPEND isn't supported.
+ //
+
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {
+
+ if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
+ //
+ // Case1:
+ // Both OverCurrent and OverCurrentChange set, means over current occurs,
+ // which probably is caused by short circuit. It has to wait system hardware
+ // to perform recovery.
+ //
+ DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port));
+ return EFI_DEVICE_ERROR;
+
+ }
+ //
+ // Case2:
+ // Only OverCurrentChange set, means system has been recoveried from
+ // over current. As a result, all ports are nearly power-off, so
+ // it's necessary to detach and enumerate all ports again.
+ //
+ DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port));
+ }
+
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {
+ //
+ // Case3:
+ // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart
+ // on 2.0 roothub does. When over-current has influence on 1.1 device, the port
+ // would be disabled, so it's also necessary to detach and enumerate again.
+ //
+ DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port));
+ }
+
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
+ //
+ // Case4:
+ // Device connected or disconnected normally.
+ //
+ DEBUG ((EFI_D_INFO, "UsbEnumeratePort: Device Connect/Discount Normally\n", Port));
+ }
+
+ //
+ // Following as the above cases, it's safety to remove and create again.
+ //
+ Child = UsbFindChild (HubIf, Port);
+
+ if (Child != NULL) {
+ DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device at port %d removed from root hub %p\n", Port, HubIf));
+ UsbRemoveDevice (Child);
+ }
+
+ if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
+ //
+ // Now, new device connected, enumerate and configure the device
+ //
+ DEBUG (( EFI_D_INFO, "UsbEnumeratePort: new device connected at port %d\n", Port));
+ Status = UsbEnumerateNewDev (HubIf, Port);
+
+ } else {
+ DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device disconnected event on port %d\n", Port));
+ }
+
+ HubApi->ClearPortChange (HubIf, Port);
+ return Status;
+}
+
+
+/**
+ Enumerate all the changed hub ports.
+
+ @param Event The event that is triggered.
+ @param Context The context to the event.
+
+**/
+VOID
+EFIAPI
+UsbHubEnumeration (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ USB_INTERFACE *HubIf;
+ UINT8 Byte;
+ UINT8 Bit;
+ UINT8 Index;
+
+ ASSERT (Context != NULL);
+
+ HubIf = (USB_INTERFACE *) Context;
+
+ if (HubIf->ChangeMap == NULL) {
+ return ;
+ }
+
+ //
+ // HUB starts its port index with 1.
+ //
+ Byte = 0;
+ Bit = 1;
+
+ for (Index = 0; Index < HubIf->NumOfPort; Index++) {
+ if (USB_BIT_IS_SET (HubIf->ChangeMap[Byte], USB_BIT (Bit))) {
+ UsbEnumeratePort (HubIf, Index);
+ }
+
+ USB_NEXT_BIT (Byte, Bit);
+ }
+
+ UsbHubAckHubStatus (HubIf->Device);
+
+ gBS->FreePool (HubIf->ChangeMap);
+ HubIf->ChangeMap = NULL;
+ return ;
+}
+
+
+/**
+ Enumerate all the changed hub ports.
+
+ @param Event The event that is triggered.
+ @param Context The context to the event.
+
+**/
+VOID
+EFIAPI
+UsbRootHubEnumeration (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ USB_INTERFACE *RootHub;
+ UINT8 Index;
+
+ RootHub = (USB_INTERFACE *) Context;
+
+ for (Index = 0; Index < RootHub->NumOfPort; Index++) {
+ UsbEnumeratePort (RootHub, Index);
+ }
+}
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
new file mode 100755
index 0000000..8bac2ca
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
@@ -0,0 +1,1407 @@
+/** @file
+
+ Unified interface for RootHub and Hub.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "UsbBus.h"
+
+//
+// Array that maps the change bit to feature value which is
+// used to clear these change bit. USB HUB API will clear
+// these change bit automatically. For non-root hub, these
+// bits determine whether hub will report the port in changed
+// bit maps.
+//
+USB_CHANGE_FEATURE_MAP mHubFeatureMap[] = {
+ {USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},
+ {USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},
+ {USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},
+ {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},
+ {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange}
+};
+
+USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[] = {
+ {USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},
+ {USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},
+ {USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},
+ {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},
+ {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange},
+};
+
+//
+// USB hub class specific requests. Although USB hub
+// is related to an interface, these requests are sent
+// to the control endpoint of the device.
+//
+/**
+ USB hub control transfer to set the hub depth.
+
+ @param HubDev The device of the hub.
+ @param Depth The depth to set.
+
+ @retval EFI_SUCCESS Depth of the hub is set.
+ @retval Others Failed to set the depth.
+
+**/
+EFI_STATUS
+UsbHubCtrlSetHubDepth (
+ IN USB_DEVICE *HubDev,
+ IN UINT16 Depth
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_HUB,
+ USB_HUB_REQ_SET_DEPTH,
+ Depth,
+ 0,
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+/**
+ USB hub control transfer to clear the hub feature.
+
+ @param HubDev The device of the hub.
+ @param Feature The feature to clear.
+
+ @retval EFI_SUCCESS Feature of the hub is cleared.
+ @retval Others Failed to clear the feature.
+
+**/
+EFI_STATUS
+UsbHubCtrlClearHubFeature (
+ IN USB_DEVICE *HubDev,
+ IN UINT16 Feature
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_HUB,
+ USB_HUB_REQ_CLEAR_FEATURE,
+ Feature,
+ 0,
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ Clear the feature of the device's port.
+
+ @param HubDev The hub device.
+ @param Port The port to clear feature.
+ @param Feature The feature to clear.
+
+ @retval EFI_SUCCESS The feature of the port is cleared.
+ @retval Others Failed to clear the feature.
+
+**/
+EFI_STATUS
+UsbHubCtrlClearPortFeature (
+ IN USB_DEVICE *HubDev,
+ IN UINT8 Port,
+ IN UINT16 Feature
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // In USB bus, all the port index starts from 0. But HUB
+ // indexes its port from 1. So, port number is added one.
+ //
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_PORT,
+ USB_HUB_REQ_CLEAR_FEATURE,
+ Feature,
+ (UINT16) (Port + 1),
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ Clear the transaction translate buffer if full/low
+ speed control/bulk transfer failed and the transfer
+ uses this hub as translator.Remember to clear the TT
+ buffer of transaction translator, not that of the
+ parent.
+
+ @param HubDev The hub device.
+ @param Port The port of the hub.
+ @param DevAddr Address of the failed transaction.
+ @param EpNum The endpoint number of the failed transaction.
+ @param EpType The type of failed transaction.
+
+ @retval EFI_SUCCESS The TT buffer is cleared.
+ @retval Others Failed to clear the TT buffer.
+
+**/
+EFI_STATUS
+UsbHubCtrlClearTTBuffer (
+ IN USB_DEVICE *HubDev,
+ IN UINT8 Port,
+ IN UINT16 DevAddr,
+ IN UINT16 EpNum,
+ IN UINT16 EpType
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Value;
+
+ //
+ // Check USB2.0 spec page 424 for wValue's encoding
+ //
+ Value = (UINT16) ((EpNum & 0x0F) | (DevAddr << 4) |
+ ((EpType & 0x03) << 11) | ((EpNum & 0x80) << 15));
+
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_PORT,
+ USB_HUB_REQ_CLEAR_TT,
+ Value,
+ (UINT16) (Port + 1),
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+/**
+ Usb hub control transfer to get the super speed hub descriptor.
+
+ @param HubDev The hub device.
+ @param Buf The buffer to hold the descriptor.
+
+ @retval EFI_SUCCESS The hub descriptor is retrieved.
+ @retval Others Failed to retrieve the hub descriptor.
+
+**/
+EFI_STATUS
+UsbHubCtrlGetSuperSpeedHubDesc (
+ IN USB_DEVICE *HubDev,
+ OUT VOID *Buf
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_INVALID_PARAMETER;
+
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbDataIn,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_HUB,
+ USB_HUB_REQ_GET_DESC,
+ (UINT16) (USB_DESC_TYPE_HUB_SUPER_SPEED << 8),
+ 0,
+ Buf,
+ 32
+ );
+
+ return Status;
+}
+
+/**
+ Usb hub control transfer to get the hub descriptor.
+
+ @param HubDev The hub device.
+ @param Buf The buffer to hold the descriptor.
+ @param Len The length to retrieve.
+
+ @retval EFI_SUCCESS The hub descriptor is retrieved.
+ @retval Others Failed to retrieve the hub descriptor.
+
+**/
+EFI_STATUS
+UsbHubCtrlGetHubDesc (
+ IN USB_DEVICE *HubDev,
+ OUT VOID *Buf,
+ IN UINTN Len
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbDataIn,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_HUB,
+ USB_HUB_REQ_GET_DESC,
+ (UINT16) (USB_DESC_TYPE_HUB << 8),
+ 0,
+ Buf,
+ Len
+ );
+
+ return Status;
+}
+
+
+/**
+ Usb hub control transfer to get the hub status.
+
+ @param HubDev The hub device.
+ @param State The variable to return the status.
+
+ @retval EFI_SUCCESS The hub status is returned in State.
+ @retval Others Failed to get the hub status.
+
+**/
+EFI_STATUS
+UsbHubCtrlGetHubStatus (
+ IN USB_DEVICE *HubDev,
+ OUT UINT32 *State
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbDataIn,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_HUB,
+ USB_HUB_REQ_GET_STATUS,
+ 0,
+ 0,
+ State,
+ 4
+ );
+
+ return Status;
+}
+
+
+/**
+ Usb hub control transfer to get the port status.
+
+ @param HubDev The hub device.
+ @param Port The port of the hub.
+ @param State Variable to return the hub port state.
+
+ @retval EFI_SUCCESS The port state is returned in State.
+ @retval Others Failed to retrieve the port state.
+
+**/
+EFI_STATUS
+UsbHubCtrlGetPortStatus (
+ IN USB_DEVICE *HubDev,
+ IN UINT8 Port,
+ OUT VOID *State
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // In USB bus, all the port index starts from 0. But HUB
+ // indexes its port from 1. So, port number is added one.
+ // No need to convert the hub bit to UEFI definition, they
+ // are the same
+ //
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbDataIn,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_PORT,
+ USB_HUB_REQ_GET_STATUS,
+ 0,
+ (UINT16) (Port + 1),
+ State,
+ 4
+ );
+
+ return Status;
+}
+
+
+/**
+ Usb hub control transfer to reset the TT (Transaction Transaltor).
+
+ @param HubDev The hub device.
+ @param Port The port of the hub.
+
+ @retval EFI_SUCCESS The TT of the hub is reset.
+ @retval Others Failed to reset the port.
+
+**/
+EFI_STATUS
+UsbHubCtrlResetTT (
+ IN USB_DEVICE *HubDev,
+ IN UINT8 Port
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_HUB,
+ USB_HUB_REQ_RESET_TT,
+ 0,
+ (UINT16) (Port + 1),
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ Usb hub control transfer to set the hub feature.
+
+ @param HubDev The hub device.
+ @param Feature The feature to set.
+
+ @retval EFI_SUCESS The feature is set for the hub.
+ @retval Others Failed to set the feature.
+
+**/
+EFI_STATUS
+UsbHubCtrlSetHubFeature (
+ IN USB_DEVICE *HubDev,
+ IN UINT8 Feature
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_HUB,
+ USB_HUB_REQ_SET_FEATURE,
+ Feature,
+ 0,
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ Usb hub control transfer to set the port feature.
+
+ @param HubDev The Usb hub device.
+ @param Port The Usb port to set feature for.
+ @param Feature The feature to set.
+
+ @retval EFI_SUCCESS The feature is set for the port.
+ @retval Others Failed to set the feature.
+
+**/
+EFI_STATUS
+UsbHubCtrlSetPortFeature (
+ IN USB_DEVICE *HubDev,
+ IN UINT8 Port,
+ IN UINT8 Feature
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // In USB bus, all the port index starts from 0. But HUB
+ // indexes its port from 1. So, port number is added one.
+ //
+ Status = UsbCtrlRequest (
+ HubDev,
+ EfiUsbNoData,
+ USB_REQ_TYPE_CLASS,
+ USB_HUB_TARGET_PORT,
+ USB_HUB_REQ_SET_FEATURE,
+ Feature,
+ (UINT16) (Port + 1),
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ Read the whole usb hub descriptor. It is necessary
+ to do it in two steps because hub descriptor is of
+ variable length.
+
+ @param HubDev The hub device.
+ @param HubDesc The variable to return the descriptor.
+
+ @retval EFI_SUCCESS The hub descriptor is read.
+ @retval Others Failed to read the hub descriptor.
+
+**/
+EFI_STATUS
+UsbHubReadDesc (
+ IN USB_DEVICE *HubDev,
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDesc
+ )
+{
+ EFI_STATUS Status;
+
+ if (HubDev->Speed == EFI_USB_SPEED_SUPER) {
+ //
+ // Get the super speed hub descriptor
+ //
+ Status = UsbHubCtrlGetSuperSpeedHubDesc (HubDev, HubDesc);
+ } else {
+
+ //
+ // First get the hub descriptor length
+ //
+ Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the whole hub descriptor
+ //
+ Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);
+ }
+
+ return Status;
+}
+
+
+
+/**
+ Ack the hub change bits. If these bits are not ACKed, Hub will
+ always return changed bit map from its interrupt endpoint.
+
+ @param HubDev The hub device.
+
+ @retval EFI_SUCCESS The hub change status is ACKed.
+ @retval Others Failed to ACK the hub status.
+
+**/
+EFI_STATUS
+UsbHubAckHubStatus (
+ IN USB_DEVICE *HubDev
+ )
+{
+ EFI_USB_PORT_STATUS HubState;
+ EFI_STATUS Status;
+
+ Status = UsbHubCtrlGetHubStatus (HubDev, (UINT32 *) &HubState);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_LOCAL_POWER)) {
+ UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_LOCAL_POWER);
+ }
+
+ if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_OVER_CURRENT)) {
+ UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_OVER_CURRENT);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Test whether the interface is a hub interface.
+
+ @param UsbIf The interface to test.
+
+ @retval TRUE The interface is a hub interface.
+ @retval FALSE The interface isn't a hub interface.
+
+**/
+BOOLEAN
+UsbIsHubInterface (
+ IN USB_INTERFACE *UsbIf
+ )
+{
+ EFI_USB_INTERFACE_DESCRIPTOR *Setting;
+
+ //
+ // If the hub is a high-speed hub with multiple TT,
+ // the hub will has a default setting of single TT.
+ //
+ Setting = &UsbIf->IfSetting->Desc;
+
+ if ((Setting->InterfaceClass == USB_HUB_CLASS_CODE) &&
+ (Setting->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ The callback function to the USB hub status change
+ interrupt endpoint. It is called periodically by
+ the underlying host controller.
+
+ @param Data The data read.
+ @param DataLength The length of the data read.
+ @param Context The context.
+ @param Result The result of the last interrupt transfer.
+
+ @retval EFI_SUCCESS The process is OK.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbOnHubInterrupt (
+ IN VOID *Data,
+ IN UINTN DataLength,
+ IN VOID *Context,
+ IN UINT32 Result
+ )
+{
+ USB_INTERFACE *HubIf;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc;
+ EFI_STATUS Status;
+
+ HubIf = (USB_INTERFACE *) Context;
+ UsbIo = &(HubIf->UsbIo);
+ EpDesc = &(HubIf->HubEp->Desc);
+
+ if (Result != EFI_USB_NOERROR) {
+ //
+ // If endpoint is stalled, clear the stall. Use UsbIo to access
+ // the control transfer so internal status are maintained.
+ //
+ if (USB_BIT_IS_SET (Result, EFI_USB_ERR_STALL)) {
+ UsbIoClearFeature (
+ UsbIo,
+ USB_TARGET_ENDPOINT,
+ USB_FEATURE_ENDPOINT_HALT,
+ EpDesc->EndpointAddress
+ );
+ }
+
+ //
+ // Delete and submit a new async interrupt
+ //
+ Status = UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ EpDesc->EndpointAddress,
+ FALSE,
+ 0,
+ 0,
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to remove async transfer - %r\n", Status));
+ return Status;
+ }
+
+ Status = UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ EpDesc->EndpointAddress,
+ TRUE,
+ USB_HUB_POLL_INTERVAL,
+ HubIf->NumOfPort / 8 + 1,
+ UsbOnHubInterrupt,
+ HubIf
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to submit new async transfer - %r\n", Status));
+ }
+
+ return Status;
+ }
+
+ if ((DataLength == 0) || (Data == NULL)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // OK, actually something is changed, save the change map
+ // then signal the HUB to do enumeration. This is a good
+ // practise since UsbOnHubInterrupt is called in the context
+ // of host contrller's AsyncInterrupt monitor.
+ //
+ HubIf->ChangeMap = AllocateZeroPool (DataLength);
+
+ if (HubIf->ChangeMap == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (HubIf->ChangeMap, Data, DataLength);
+ gBS->SignalEvent (HubIf->HubNotify);
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+/**
+ Initialize the device for a non-root hub.
+
+ @param HubIf The USB hub interface.
+
+ @retval EFI_SUCCESS The hub is initialized.
+ @retval EFI_DEVICE_ERROR Failed to initialize the hub.
+
+**/
+EFI_STATUS
+UsbHubInit (
+ IN USB_INTERFACE *HubIf
+ )
+{
+ EFI_USB_HUB_DESCRIPTOR HubDesc;
+ USB_ENDPOINT_DESC *EpDesc;
+ USB_INTERFACE_SETTING *Setting;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ USB_DEVICE *HubDev;
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT8 NumEndpoints;
+ UINT16 Depth;
+
+ //
+ // Locate the interrupt endpoint for port change map
+ //
+ HubIf->IsHub = FALSE;
+ Setting = HubIf->IfSetting;
+ HubDev = HubIf->Device;
+ EpDesc = NULL;
+ NumEndpoints = Setting->Desc.NumEndpoints;
+
+ for (Index = 0; Index < NumEndpoints; Index++) {
+ ASSERT ((Setting->Endpoints != NULL) && (Setting->Endpoints[Index] != NULL));
+
+ EpDesc = Setting->Endpoints[Index];
+
+ if (USB_BIT_IS_SET (EpDesc->Desc.EndpointAddress, USB_ENDPOINT_DIR_IN) &&
+ (USB_ENDPOINT_TYPE (&EpDesc->Desc) == USB_ENDPOINT_INTERRUPT)) {
+ break;
+ }
+ }
+
+ if (Index == NumEndpoints) {
+ DEBUG (( EFI_D_ERROR, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev->Address));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = UsbHubReadDesc (HubDev, &HubDesc);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status));
+ return Status;
+ }
+
+ HubIf->NumOfPort = HubDesc.NumPorts;
+
+ DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort));
+
+ //
+ // OK, set IsHub to TRUE. Now usb bus can handle this device
+ // as a working HUB. If failed eariler, bus driver will not
+ // recognize it as a hub. Other parts of the bus should be able
+ // to work.
+ //
+ HubIf->IsHub = TRUE;
+ HubIf->HubApi = &mUsbHubApi;
+ HubIf->HubEp = EpDesc;
+
+ if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {
+ Depth = (UINT16)(HubIf->Device->Tier - 1);
+ DEBUG ((EFI_D_INFO, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth));
+ UsbHubCtrlSetHubDepth (HubIf->Device, Depth);
+
+ for (Index = 0; Index < HubDesc.NumPorts; Index++) {
+ UsbHubCtrlSetPortFeature (HubIf->Device, Index, USB_HUB_PORT_REMOTE_WAKE_MASK);
+ }
+ } else {
+ //
+ // Feed power to all the hub ports. It should be ok
+ // for both gang/individual powered hubs.
+ //
+ for (Index = 0; Index < HubDesc.NumPorts; Index++) {
+ UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);
+ }
+
+ //
+ // Update for the usb hub has no power on delay requirement
+ //
+ if (HubDesc.PwrOn2PwrGood > 0) {
+ gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
+ }
+ UsbHubAckHubStatus (HubIf->Device);
+ }
+
+ //
+ // Create an event to enumerate the hub's port. On
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ UsbHubEnumeration,
+ HubIf,
+ &HubIf->HubNotify
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to create signal for hub %d - %r\n",
+ HubDev->Address, Status));
+
+ return Status;
+ }
+
+ //
+ // Create AsyncInterrupt to query hub port change endpoint
+ // periodically. If the hub ports are changed, hub will return
+ // changed port map from the interrupt endpoint. The port map
+ // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for
+ // host change status).
+ //
+ UsbIo = &HubIf->UsbIo;
+ Status = UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ EpDesc->Desc.EndpointAddress,
+ TRUE,
+ USB_HUB_POLL_INTERVAL,
+ HubIf->NumOfPort / 8 + 1,
+ UsbOnHubInterrupt,
+ HubIf
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n",
+ HubDev->Address, Status));
+
+ gBS->CloseEvent (HubIf->HubNotify);
+ HubIf->HubNotify = NULL;
+
+ return Status;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address));
+ return Status;
+}
+
+
+
+/**
+ Get the port status. This function is required to
+ ACK the port change bits although it will return
+ the port changes in PortState. Bus enumeration code
+ doesn't need to ACK the port change bits.
+
+ @param HubIf The hub interface.
+ @param Port The port of the hub to get state.
+ @param PortState Variable to return the port state.
+
+ @retval EFI_SUCCESS The port status is successfully returned.
+ @retval Others Failed to return the status.
+
+**/
+EFI_STATUS
+UsbHubGetPortStatus (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port,
+ OUT EFI_USB_PORT_STATUS *PortState
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);
+
+ return Status;
+}
+
+
+
+/**
+ Clear the port change status.
+
+ @param HubIf The hub interface.
+ @param Port The hub port.
+
+**/
+VOID
+UsbHubClearPortChange (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port
+ )
+{
+ EFI_USB_PORT_STATUS PortState;
+ USB_CHANGE_FEATURE_MAP *Map;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
+
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // OK, get the usb port status, now ACK the change bits.
+ // Don't return error when failed to clear the change bits.
+ // It may lead to extra port state report. USB bus should
+ // be able to handle this.
+ //
+ for (Index = 0; Index < sizeof (mHubFeatureMap) / sizeof (mHubFeatureMap[0]); Index++) {
+ Map = &mHubFeatureMap[Index];
+
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {
+ UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT16) Map->Feature);
+ }
+ }
+}
+
+
+
+/**
+ Function to set the port feature for non-root hub.
+
+ @param HubIf The hub interface.
+ @param Port The port of the hub.
+ @param Feature The feature of the port to set.
+
+ @retval EFI_SUCCESS The hub port feature is set.
+ @retval Others Failed to set the port feature.
+
+**/
+EFI_STATUS
+UsbHubSetPortFeature (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port,
+ IN EFI_USB_PORT_FEATURE Feature
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbHubCtrlSetPortFeature (HubIf->Device, Port, (UINT8) Feature);
+
+ return Status;
+}
+
+
+/**
+ Interface function to clear the port feature for non-root hub.
+
+ @param HubIf The hub interface.
+ @param Port The port of the hub to clear feature for.
+ @param Feature The feature to clear.
+
+ @retval EFI_SUCCESS The port feature is cleared.
+ @retval Others Failed to clear the port feature.
+
+**/
+EFI_STATUS
+UsbHubClearPortFeature (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port,
+ IN EFI_USB_PORT_FEATURE Feature
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT8) Feature);
+
+ return Status;
+}
+
+
+/**
+ Interface function to reset the port.
+
+ @param HubIf The hub interface.
+ @param Port The port to reset.
+
+ @retval EFI_SUCCESS The hub port is reset.
+ @retval EFI_TIMEOUT Failed to reset the port in time.
+ @retval Others Failed to reset the port.
+
+**/
+EFI_STATUS
+UsbHubResetPort (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port
+ )
+{
+ EFI_USB_PORT_STATUS PortState;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ Status = UsbHubSetPortFeature (HubIf, Port, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_RESET);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Drive the reset signal for at least 10ms. Check USB 2.0 Spec
+ // section 7.1.7.5 for timing requirements.
+ //
+ gBS->Stall (USB_SET_PORT_RESET_STALL);
+
+ //
+ // USB hub will clear RESET bit if reset is actually finished.
+ //
+ ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));
+
+ for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
+ Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
+
+ if (!EFI_ERROR (Status) &&
+ !USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {
+
+ return EFI_SUCCESS;
+ }
+
+ gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
+ }
+
+ return EFI_TIMEOUT;
+}
+
+
+/**
+ Release the hub's control of the interface.
+
+ @param HubIf The hub interface.
+
+ @retval EFI_SUCCESS The interface is release of hub control.
+
+**/
+EFI_STATUS
+UsbHubRelease (
+ IN USB_INTERFACE *HubIf
+ )
+{
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_STATUS Status;
+
+ UsbIo = &HubIf->UsbIo;
+ Status = UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ HubIf->HubEp->Desc.EndpointAddress,
+ FALSE,
+ USB_HUB_POLL_INTERVAL,
+ 0,
+ NULL,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseEvent (HubIf->HubNotify);
+
+ HubIf->IsHub = FALSE;
+ HubIf->HubApi = NULL;
+ HubIf->HubEp = NULL;
+ HubIf->HubNotify = NULL;
+
+ DEBUG (( EFI_D_INFO, "UsbHubRelease: hub device %d released\n", HubIf->Device->Address));
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Initialize the interface for root hub.
+
+ @param HubIf The root hub interface.
+
+ @retval EFI_SUCCESS The interface is initialized for root hub.
+ @retval Others Failed to initialize the hub.
+
+**/
+EFI_STATUS
+UsbRootHubInit (
+ IN USB_INTERFACE *HubIf
+ )
+{
+ EFI_STATUS Status;
+ UINT8 MaxSpeed;
+ UINT8 NumOfPort;
+ UINT8 Support64;
+
+ Status = UsbHcGetCapability (HubIf->Device->Bus, &MaxSpeed, &NumOfPort, &Support64);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG (( EFI_D_INFO, "UsbRootHubInit: root hub %p - max speed %d, %d ports\n",
+ HubIf, MaxSpeed, NumOfPort));
+
+ HubIf->IsHub = TRUE;
+ HubIf->HubApi = &mUsbRootHubApi;
+ HubIf->HubEp = NULL;
+ HubIf->MaxSpeed = MaxSpeed;
+ HubIf->NumOfPort = NumOfPort;
+ HubIf->HubNotify = NULL;
+
+ //
+ // Create a timer to poll root hub ports periodically
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ UsbRootHubEnumeration,
+ HubIf,
+ &HubIf->HubNotify
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // It should signal the event immediately here, or device detection
+ // by bus enumeration might be delayed by the timer interval.
+ //
+ gBS->SignalEvent (HubIf->HubNotify);
+
+ Status = gBS->SetTimer (
+ HubIf->HubNotify,
+ TimerPeriodic,
+ USB_ROOTHUB_POLL_INTERVAL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (HubIf->HubNotify);
+ }
+
+ return Status;
+}
+
+
+/**
+ Get the port status. This function is required to
+ ACK the port change bits although it will return
+ the port changes in PortState. Bus enumeration code
+ doesn't need to ACK the port change bits.
+
+ @param HubIf The root hub interface.
+ @param Port The root hub port to get the state.
+ @param PortState Variable to return the port state.
+
+ @retval EFI_SUCCESS The port state is returned.
+ @retval Others Failed to retrieve the port state.
+
+**/
+EFI_STATUS
+UsbRootHubGetPortStatus (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port,
+ OUT EFI_USB_PORT_STATUS *PortState
+ )
+{
+ USB_BUS *Bus;
+ EFI_STATUS Status;
+
+ Bus = HubIf->Device->Bus;
+ Status = UsbHcGetRootHubPortStatus (Bus, Port, PortState);
+
+ return Status;
+}
+
+
+/**
+ Clear the port change status.
+
+ @param HubIf The root hub interface.
+ @param Port The root hub port.
+
+**/
+VOID
+UsbRootHubClearPortChange (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port
+ )
+{
+ EFI_USB_PORT_STATUS PortState;
+ USB_CHANGE_FEATURE_MAP *Map;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ Status = UsbRootHubGetPortStatus (HubIf, Port, &PortState);
+
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // OK, get the usb port status, now ACK the change bits.
+ // Don't return error when failed to clear the change bits.
+ // It may lead to extra port state report. USB bus should
+ // be able to handle this.
+ //
+ for (Index = 0; Index < sizeof (mRootHubFeatureMap) / sizeof (mRootHubFeatureMap[0]); Index++) {
+ Map = &mRootHubFeatureMap[Index];
+
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {
+ UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, (EFI_USB_PORT_FEATURE) Map->Feature);
+ }
+ }
+}
+
+
+/**
+ Set the root hub port feature.
+
+ @param HubIf The Usb hub interface.
+ @param Port The hub port.
+ @param Feature The feature to set.
+
+ @retval EFI_SUCCESS The root hub port is set with the feature.
+ @retval Others Failed to set the feature.
+
+**/
+EFI_STATUS
+UsbRootHubSetPortFeature (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port,
+ IN EFI_USB_PORT_FEATURE Feature
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbHcSetRootHubPortFeature (HubIf->Device->Bus, Port, Feature);
+
+ return Status;
+}
+
+
+/**
+ Clear the root hub port feature.
+
+ @param HubIf The root hub interface.
+ @param Port The root hub port.
+ @param Feature The feature to clear.
+
+ @retval EFI_SUCCESS The root hub port is cleared of the feature.
+ @retval Others Failed to clear the feature.
+
+**/
+EFI_STATUS
+UsbRootHubClearPortFeature (
+ IN USB_INTERFACE *HubIf,
+ IN UINT8 Port,
+ IN EFI_USB_PORT_FEATURE Feature
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, Feature);
+
+ return Status;
+}
+
+
+/**
+ Interface function to reset the root hub port.
+
+ @param RootIf The root hub interface.
+ @param Port The port to reset.
+
+ @retval EFI_SUCCESS The hub port is reset.
+ @retval EFI_TIMEOUT Failed to reset the port in time.
+ @retval EFI_NOT_FOUND The low/full speed device connected to high speed.
+ root hub is released to the companion UHCI.
+ @retval Others Failed to reset the port.
+
+**/
+EFI_STATUS
+UsbRootHubResetPort (
+ IN USB_INTERFACE *RootIf,
+ IN UINT8 Port
+ )
+{
+ USB_BUS *Bus;
+ EFI_STATUS Status;
+ EFI_USB_PORT_STATUS PortState;
+ UINTN Index;
+
+ //
+ // Notice: although EHCI requires that ENABLED bit be cleared
+ // when reset the port, we don't need to care that here. It
+ // should be handled in the EHCI driver.
+ //
+ Bus = RootIf->Device->Bus;
+ Status = UsbHcSetRootHubPortFeature (Bus, Port, EfiUsbPortReset);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to start reset on port %d\n", Port));
+ return Status;
+ }
+
+ //
+ // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
+ // section 7.1.7.5 for timing requirements.
+ //
+ gBS->Stall (USB_SET_ROOT_PORT_RESET_STALL);
+
+ Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to clear reset on port %d\n", Port));
+ return Status;
+ }
+
+ gBS->Stall (USB_CLR_ROOT_PORT_RESET_STALL);
+
+ //
+ // USB host controller won't clear the RESET bit until
+ // reset is actually finished.
+ //
+ ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));
+
+ for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
+ Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {
+ break;
+ }
+
+ gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
+ }
+
+ if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
+ DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port));
+ return EFI_TIMEOUT;
+ }
+
+ if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_ENABLE)) {
+ //
+ // OK, the port is reset. If root hub is of high speed and
+ // the device is of low/full speed, release the ownership to
+ // companion UHCI. If root hub is of full speed, it won't
+ // automatically enable the port, we need to enable it manually.
+ //
+ if (RootIf->MaxSpeed == EFI_USB_SPEED_HIGH) {
+ DEBUG (( EFI_D_INFO, "UsbRootHubResetPort: release low/full speed device (%d) to UHCI\n", Port));
+
+ UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortOwner);
+ return EFI_NOT_FOUND;
+
+ } else {
+
+ Status = UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortEnable);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to enable port %d for UHCI\n", Port));
+ return Status;
+ }
+
+ gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Release the root hub's control of the interface.
+
+ @param HubIf The root hub interface.
+
+ @retval EFI_SUCCESS The root hub's control of the interface is
+ released.
+
+**/
+EFI_STATUS
+UsbRootHubRelease (
+ IN USB_INTERFACE *HubIf
+ )
+{
+ DEBUG (( EFI_D_INFO, "UsbRootHubRelease: root hub released for hub %p\n", HubIf));
+
+ gBS->SetTimer (HubIf->HubNotify, TimerCancel, USB_ROOTHUB_POLL_INTERVAL);
+ gBS->CloseEvent (HubIf->HubNotify);
+
+ return EFI_SUCCESS;
+}
+
+USB_HUB_API mUsbHubApi = {
+ UsbHubInit,
+ UsbHubGetPortStatus,
+ UsbHubClearPortChange,
+ UsbHubSetPortFeature,
+ UsbHubClearPortFeature,
+ UsbHubResetPort,
+ UsbHubRelease
+};
+
+USB_HUB_API mUsbRootHubApi = {
+ UsbRootHubInit,
+ UsbRootHubGetPortStatus,
+ UsbRootHubClearPortChange,
+ UsbRootHubSetPortFeature,
+ UsbRootHubClearPortFeature,
+ UsbRootHubResetPort,
+ UsbRootHubRelease
+};
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
new file mode 100755
index 0000000..4c721b4
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -0,0 +1,144 @@
+## @file
+# Last PEIM executed in PEI phase to load DXE Core from a Firmware Volume.
+#
+# This module produces a special PPI named the DXE Initial Program Load (IPL)
+# PPI to discover and dispatch the DXE Foundation and components that are
+# needed to run the DXE Foundation.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeIpl
+ FILE_GUID = 86D70125-BAA3-4296-A62F-602BEBBB9081
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PeimInitializeDxeIpl
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only)
+#
+
+[Sources]
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
+ DxeLoad.c
+
+[Sources.Ia32]
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h ||||gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c ||||gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/Ia32/IdtVectorAsm.asm||||gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/Ia32/IdtVectorAsm.S ||||gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+
+[Sources.X64]
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
+
+[Sources.IPF]
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c
+
+[Sources.EBC]
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/Ebc/DxeLoadFunc.c
+
+[Sources.ARM]
+ ../../../../../MdeModulePkg/Core/DxeIplPeim/Arm/DxeLoadFunc.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ ExtractGuidedSectionLib
+ UefiDecompressLib
+ ReportStatusCodeLib
+ PeiServicesLib
+ HobLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ DebugAgentLib
+ PeiServicesTablePointerLib
+
+[Ppis]
+ gEfiDxeIplPpiGuid ## PRODUCES
+ gEfiEndOfPeiSignalPpiGuid ## SOMETIMES_PRODUCES(Not produced on S3 boot path)
+ gEfiPeiDecompressPpiGuid ## SOMETIMES_PRODUCES
+ gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_CONSUMES
+ gEfiPeiLoadFilePpiGuid ## CONSUMES
+ gEfiPeiS3Resume2PpiGuid ## SOMETIMES_CONSUMES(Consumed on S3 boot path)
+ gEfiPeiRecoveryModulePpiGuid ## SOMETIMES_CONSUMES(Consumed on recovery boot path)
+
+[Guids]
+ gEfiMemoryTypeInformationGuid ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation"
+ gEfiMemoryTypeInformationGuid ## SOMETIMES_PRODUCES ## HOB
+
+[FeaturePcd.IA32]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+
+[FeaturePcd.X64]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress
+
+[Pcd.IA32,Pcd.X64]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiLoadFilePpiGuid AND gEfiPeiMasterBootModePpiGuid
+
+#
+# [BootMode]
+# S3_RESUME ## SOMETIMES_CONSUMES
+# RECOVERY ## SOMETIMES_CONSUMES
+#
+#
+# [Hob]
+# ##
+# # New Stack HoB
+# MEMORY_ALLOCATION ## PRODUCES
+# ##
+# # Old Stack HOB
+# MEMORY_ALLOCATION ## CONSUMES
+#
+# [Hob.IPF]
+# ##
+# # BSP Stack HOB for IPF
+# MEMORY_ALLOCATION ## PRODUCES
+#
+#
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
new file mode 100755
index 0000000..de38ad7
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -0,0 +1,780 @@
+/** @file
+ Last PEIM.
+ Responsibility of this module is to load the DXE Core from a Firmware Volume.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "DxeIpl.h"
+
+
+//
+// Module Globals used in the DXE to PEI hand off
+// These must be module globals, so the stack can be switched
+//
+CONST EFI_DXE_IPL_PPI mDxeIplPpi = {
+ DxeLoadCore
+};
+
+CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {
+ CustomGuidedSectionExtract
+};
+
+CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {
+ Decompress
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiDxeIplPpiGuid,
+ (VOID *) &mDxeIplPpi
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiDecompressPpiGuid,
+ (VOID *) &mDecompressPpi
+ }
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ NULL
+};
+
+/**
+ Entry point of DXE IPL PEIM.
+
+ This function installs DXE IPL PPI and Decompress PPI. It also reloads
+ itself to memory on non-S3 resume boot path.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
+ @retval Others Some error occurs during the execution of this function.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimInitializeDxeIpl (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ EFI_GUID *ExtractHandlerGuidTable;
+ UINTN ExtractHandlerNumber;
+ EFI_PEI_PPI_DESCRIPTOR *GuidPpi;
+
+ BootMode = GetBootModeHob ();
+
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ Status = PeiServicesRegisterForShadow (FileHandle);
+ if (Status == EFI_SUCCESS) {
+ //
+ // EFI_SUCESS means it is the first time to call register for shadow.
+ //
+ return Status;
+ }
+
+ //
+ // Ensure that DXE IPL is shadowed to permanent memory.
+ //
+ ASSERT (Status == EFI_ALREADY_STARTED);
+ }
+
+ //
+ // Get custom extract guided section method guid list
+ //
+ ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
+
+ //
+ // Install custom extraction guid PPI
+ //
+ if (ExtractHandlerNumber > 0) {
+ GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ ASSERT (GuidPpi != NULL);
+ while (ExtractHandlerNumber-- > 0) {
+ GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ GuidPpi->Ppi = (VOID *) &mCustomGuidedSectionExtractionPpi;
+ GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];
+ Status = PeiServicesInstallPpi (GuidPpi++);
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+
+ //
+ // Install DxeIpl and Decompress PPIs.
+ //
+ Status = PeiServicesInstallPpi (mPpiList);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+/**
+ Validate variable data for the MemoryTypeInformation.
+
+ @param MemoryData Variable data.
+ @param MemoryDataSize Variable data length.
+
+ @return TRUE The variable data is valid.
+ @return FALSE The variable data is invalid.
+
+**/
+BOOLEAN
+ValidateMemoryTypeInfoVariable (
+ IN EFI_MEMORY_TYPE_INFORMATION *MemoryData,
+ IN UINTN MemoryDataSize
+ )
+{
+ UINTN Count;
+ UINTN Index;
+
+ // Check the input parameter.
+ if (MemoryData == NULL) {
+ return FALSE;
+ }
+
+ // Get Count
+ Count = MemoryDataSize / sizeof (*MemoryData);
+
+ // Check Size
+ if (Count * sizeof(*MemoryData) != MemoryDataSize) {
+ return FALSE;
+ }
+
+ // Check last entry type filed.
+ if (MemoryData[Count - 1].Type != EfiMaxMemoryType) {
+ return FALSE;
+ }
+
+ // Check the type filed.
+ for (Index = 0; Index < Count - 1; Index++) {
+ if (MemoryData[Index].Type >= EfiMaxMemoryType) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Main entry point to last PEIM.
+
+ This function finds DXE Core in the firmware volume and transfer the control to
+ DXE core.
+
+ @param This Entry point for DXE IPL PPI.
+ @param PeiServices General purpose services available to every PEIM.
+ @param HobList Address to the Pei HOB list.
+
+ @return EFI_SUCCESS DXE core was successfully loaded.
+ @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeLoadCore (
+ IN CONST EFI_DXE_IPL_PPI *This,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_HOB_POINTERS HobList
+ )
+{
+ EFI_STATUS Status;
+ EFI_FV_FILE_INFO DxeCoreFileInfo;
+ EFI_PHYSICAL_ADDRESS DxeCoreAddress;
+ UINT64 DxeCoreSize;
+ EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;
+ EFI_BOOT_MODE BootMode;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
+ EFI_PEI_LOAD_FILE_PPI *LoadFile;
+ UINTN Instance;
+ UINT32 AuthenticationState;
+ UINTN DataSize;
+ EFI_PEI_S3_RESUME2_PPI *S3Resume;
+ EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery;
+ EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1];
+
+ //
+ // if in S3 Resume, restore configure
+ //
+ BootMode = GetBootModeHob ();
+
+ if (BootMode == BOOT_ON_S3_RESUME) {
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiS3Resume2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &S3Resume
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Report Status code that S3Resume PPI can not be found
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND)
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ Status = S3Resume->S3RestoreConfig2 (S3Resume);
+ ASSERT_EFI_ERROR (Status);
+ } else if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_RECOVERY_BEGIN));
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiRecoveryModulePpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PeiRecovery
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Report Status code the failure of locating Recovery PPI
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_LOAD));
+ Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));
+ //
+ // Report Status code that S3Resume PPI can not be found
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
+ );
+ CpuDeadLoop ();
+ }
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START));
+ //
+ // Now should have a HOB with the DXE core
+ //
+ }
+
+ //
+ // Setup MemoryTypeInformation hob for all boot modes except recovery.
+ // For PEI stage don't trust variable store on recovery,
+ // we expect platform package to setup MemoryTypeInformation on recovery.
+ //
+ if (BootMode != BOOT_IN_RECOVERY_MODE) {
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **)&Variable
+ );
+ if (!EFI_ERROR (Status)) {
+ DataSize = sizeof (MemoryData);
+ Status = Variable->GetVariable (
+ Variable,
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+ &gEfiMemoryTypeInformationGuid,
+ NULL,
+ &DataSize,
+ &MemoryData
+ );
+ if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) {
+ //
+ // Build the GUID'd HOB for DXE
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ MemoryData,
+ DataSize
+ );
+ }
+ }
+ }
+
+ //
+ // Look in all the FVs present in PEI and find the DXE Core FileHandle
+ //
+ FileHandle = DxeIplFindDxeCore ();
+
+ //
+ // Load the DXE Core from a Firmware Volume.
+ //
+ Instance = 0;
+ do {
+ Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile);
+ //
+ // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully.
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ Status = LoadFile->LoadFile (
+ LoadFile,
+ FileHandle,
+ &DxeCoreAddress,
+ &DxeCoreSize,
+ &DxeCoreEntryPoint,
+ &AuthenticationState
+ );
+ } while (EFI_ERROR (Status));
+
+ //
+ // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.
+ //
+ Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Add HOB for the DXE Core
+ //
+ BuildModuleHob (
+ &DxeCoreFileInfo.FileName,
+ DxeCoreAddress,
+ ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),
+ DxeCoreEntryPoint
+ );
+
+ //
+ // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
+ //
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT));
+
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));
+
+ //
+ // Transfer control to the DXE Core
+ // The hand off state is simply a pointer to the HOB list
+ //
+ HandOffToDxeCore (DxeCoreEntryPoint, HobList);
+ //
+ // If we get here, then the DXE Core returned. This is an error
+ // DxeCore should not return.
+ //
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+
+/**
+ Searches DxeCore in all firmware Volumes and loads the first
+ instance that contains DxeCore.
+
+ @return FileHandle of DxeCore to load DxeCore.
+
+**/
+EFI_PEI_FILE_HANDLE
+DxeIplFindDxeCore (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Instance;
+ EFI_PEI_FV_HANDLE VolumeHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+
+ Instance = 0;
+ while (TRUE) {
+ //
+ // Traverse all firmware volume instances
+ //
+ Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);
+ //
+ // If some error occurs here, then we cannot find any firmware
+ // volume that may contain DxeCore.
+ //
+ if (EFI_ERROR (Status)) {
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT));
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find the DxeCore file type from the beginning in this firmware volume.
+ //
+ FileHandle = NULL;
+ Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Find DxeCore FileHandle in this volume, then we skip other firmware volume and
+ // return the FileHandle.
+ //
+ return FileHandle;
+ }
+ //
+ // We cannot find DxeCore in this firmware volume, then search the next volume.
+ //
+ Instance++;
+ }
+}
+
+
+
+/**
+ The ExtractSection() function processes the input section and
+ returns a pointer to the section contents. If the section being
+ extracted does not require processing (if the section
+ GuidedSectionHeader.Attributes has the
+ EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
+ OutputBuffer is just updated to point to the start of the
+ section's contents. Otherwise, *Buffer must be allocated
+ from PEI permanent memory.
+
+ @param This Indicates the
+ EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
+ Buffer containing the input GUIDed section to be
+ processed. OutputBuffer OutputBuffer is
+ allocated from PEI permanent memory and contains
+ the new section stream.
+ @param InputSection A pointer to the input buffer, which contains
+ the input section to be processed.
+ @param OutputBuffer A pointer to a caller-allocated buffer, whose
+ size is specified by the contents of OutputSize.
+ @param OutputSize A pointer to a caller-allocated
+ UINTN in which the size of *OutputBuffer
+ allocation is stored. If the function
+ returns anything other than EFI_SUCCESS,
+ the value of OutputSize is undefined.
+ @param AuthenticationStatus A pointer to a caller-allocated
+ UINT32 that indicates the
+ authentication status of the
+ output buffer. If the input
+ section's GuidedSectionHeader.
+ Attributes field has the
+ EFI_GUIDED_SECTION_AUTH_STATUS_VALID
+ bit as clear,
+ AuthenticationStatus must return
+ zero. These bits reflect the
+ status of the extraction
+ operation. If the function
+ returns anything other than
+ EFI_SUCCESS, the value of
+ AuthenticationStatus is
+ undefined.
+
+ @retval EFI_SUCCESS The InputSection was
+ successfully processed and the
+ section contents were returned.
+
+ @retval EFI_OUT_OF_RESOURCES The system has insufficient
+ resources to process the request.
+
+ @retval EFI_INVALID_PARAMETER The GUID in InputSection does
+ not match this instance of the
+ GUIDed Section Extraction PPI.
+
+**/
+EFI_STATUS
+EFIAPI
+CustomGuidedSectionExtract (
+ IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
+ IN CONST VOID *InputSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize,
+ OUT UINT32 *AuthenticationStatus
+)
+{
+ EFI_STATUS Status;
+ UINT8 *ScratchBuffer;
+ UINT32 ScratchBufferSize;
+ UINT32 OutputBufferSize;
+ UINT16 SectionAttribute;
+
+ //
+ // Init local variable
+ //
+ ScratchBuffer = NULL;
+
+ //
+ // Call GetInfo to get the size and attribute of input guided section data.
+ //
+ Status = ExtractGuidedSectionGetInfo (
+ InputSection,
+ &OutputBufferSize,
+ &ScratchBufferSize,
+ &SectionAttribute
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
+ return Status;
+ }
+
+ if (ScratchBufferSize != 0) {
+ //
+ // Allocate scratch buffer
+ //
+ ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
+ if (ScratchBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
+ //
+ // Allocate output buffer
+ //
+ *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
+ if (*OutputBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
+ //
+ // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
+ // skip EFI section header to make section data at page alignment.
+ //
+ *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
+ }
+
+ Status = ExtractGuidedSectionDecode (
+ InputSection,
+ OutputBuffer,
+ ScratchBuffer,
+ AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Decode failed
+ //
+ DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
+ return Status;
+ }
+
+ *OutputSize = (UINTN) OutputBufferSize;
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Decompresses a section to the output buffer.
+
+ This function looks up the compression type field in the input section and
+ applies the appropriate compression algorithm to compress the section to a
+ callee allocated buffer.
+
+ @param This Points to this instance of the
+ EFI_PEI_DECOMPRESS_PEI PPI.
+ @param CompressionSection Points to the compressed section.
+ @param OutputBuffer Holds the returned pointer to the decompressed
+ sections.
+ @param OutputSize Holds the returned size of the decompress
+ section streams.
+
+ @retval EFI_SUCCESS The section was decompressed successfully.
+ OutputBuffer contains the resulting data and
+ OutputSize contains the resulting size.
+
+**/
+EFI_STATUS
+EFIAPI
+Decompress (
+ IN CONST EFI_PEI_DECOMPRESS_PPI *This,
+ IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *DstBuffer;
+ UINT8 *ScratchBuffer;
+ UINT32 DstBufferSize;
+ UINT32 ScratchBufferSize;
+ VOID *CompressionSource;
+ UINT32 CompressionSourceSize;
+ UINT32 UncompressedLength;
+ UINT8 CompressionType;
+
+ if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IS_SECTION2 (CompressionSection)) {
+ CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));
+ CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));
+ UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;
+ CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;
+ } else {
+ CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));
+ CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));
+ UncompressedLength = CompressionSection->UncompressedLength;
+ CompressionType = CompressionSection->CompressionType;
+ }
+
+ //
+ // This is a compression set, expand it
+ //
+ switch (CompressionType) {
+ case EFI_STANDARD_COMPRESSION:
+ if (FeaturePcdGet(PcdDxeIplSupportUefiDecompress)) {
+ //
+ // Load EFI standard compression.
+ // For compressed data, decompress them to destination buffer.
+ //
+ Status = UefiDecompressGetInfo (
+ CompressionSource,
+ CompressionSourceSize,
+ &DstBufferSize,
+ &ScratchBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // GetInfo failed
+ //
+ DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Allocate scratch buffer
+ //
+ ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
+ if (ScratchBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Allocate destination buffer, extra one page for adjustment
+ //
+ DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
+ if (DstBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
+ // to make section data at page alignment.
+ //
+ DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
+ //
+ // Call decompress function
+ //
+ Status = UefiDecompress (
+ CompressionSource,
+ DstBuffer,
+ ScratchBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Decompress failed
+ //
+ DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
+ return EFI_NOT_FOUND;
+ }
+ break;
+ } else {
+ //
+ // PcdDxeIplSupportUefiDecompress is FALSE
+ // Don't support UEFI decompression algorithm.
+ //
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+
+ case EFI_NOT_COMPRESSED:
+ //
+ // Allocate destination buffer
+ //
+ DstBufferSize = UncompressedLength;
+ DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
+ if (DstBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Adjust DstBuffer offset, skip EFI section header
+ // to make section data at page alignment.
+ //
+ DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
+ //
+ // stream is not actually compressed, just encapsulated. So just copy it.
+ //
+ CopyMem (DstBuffer, CompressionSource, DstBufferSize);
+ break;
+
+ default:
+ //
+ // Don't support other unknown compression type.
+ //
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+
+ *OutputSize = DstBufferSize;
+ *OutputBuffer = DstBuffer;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Updates the Stack HOB passed to DXE phase.
+
+ This function traverses the whole HOB list and update the stack HOB to
+ reflect the real stack that is used by DXE core.
+
+ @param BaseAddress The lower address of stack used by DxeCore.
+ @param Length The length of stack used by DxeCore.
+
+**/
+VOID
+UpdateStackHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+
+ Hob.Raw = GetHobList ();
+ while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
+ if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
+ //
+ // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to
+ // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some
+ // PEIMs may also keep key information on stack
+ //
+ BuildMemoryAllocationHob (
+ Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
+ Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
+ EfiBootServicesData
+ );
+ //
+ // Update the BSP Stack Hob to reflect the new stack info.
+ //
+ Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+ Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;
+ break;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+}
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
new file mode 100755
index 0000000..70448d9
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
@@ -0,0 +1,90 @@
+## @file
+# This driver installs Fault Tolerant Write (FTW) protocol,
+# which provides fault tolerant write capability for block devices.
+# Its implementation depends on the full functionality FVB protocol that support read, write/erase flash access.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FaultTolerantWriteDxe
+ FILE_GUID = FE5CEA76-4F72-49e8-986F-2CD899DFFE5D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FaultTolerantWriteInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ FtwMisc.c
+ UpdateWorkingBlock.c
+ ../../../../../MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c
+ ../../../../../MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.c
+ ../../../../../MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ DebugLib
+ UefiLib
+
+[Guids]
+ gEfiSystemNvDataFvGuid ## CONSUMES ## FV Signature of Working Space Header
+
+[Protocols]
+ gEfiSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
+ gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES
+ gEfiFaultTolerantWriteProtocolGuid ## PRODUCES
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Depex]
+ gEfiFirmwareVolumeBlockProtocolGuid
+
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
new file mode 100755
index 0000000..4dc0c0d
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
@@ -0,0 +1,93 @@
+## @file
+# This driver installs SMM Fault Tolerant Write (FTW) protocol, which provides fault
+# tolerant write capability in SMM environment for block devices. Its implementation
+# depends on the full functionality SMM FVB protocol that support read, write/erase
+# flash access.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmFaultTolerantWriteDxe
+ FILE_GUID = 470CB248-E8AC-473c-BB4F-81069A1FE6FD
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SmmFaultTolerantWriteInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FtwMisc.c
+ UpdateWorkingBlock.c
+ ../../../../../MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c
+ ../../../../../MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
+ ../../../../../MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h
+ ../../../../../MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmCommon.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ SmmServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ DebugLib
+ UefiLib
+
+[Guids]
+ gEfiSystemNvDataFvGuid ## CONSUMES ## FV Signature of Working Space Header
+
+[Protocols]
+ gEfiSmmSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
+ gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES
+ gEfiSmmFaultTolerantWriteProtocolGuid ## PRODUCES
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Depex]
+ gEfiSmmFirmwareVolumeBlockProtocolGuid
+
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
new file mode 100755
index 0000000..0cbec53
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
@@ -0,0 +1,1326 @@
+/** @file
+
+ Internal generic functions to operate flash block.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "FaultTolerantWrite.h"
+
+/**
+
+ Check whether a flash buffer is erased.
+
+ @param Buffer Buffer to check
+ @param BufferSize Size of the buffer
+
+ @return A BOOLEAN value indicating erased or not.
+
+**/
+BOOLEAN
+IsErasedFlashBuffer (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize
+ )
+{
+ BOOLEAN IsEmpty;
+ UINT8 *Ptr;
+ UINTN Index;
+
+ Ptr = Buffer;
+ IsEmpty = TRUE;
+ for (Index = 0; Index < BufferSize; Index += 1) {
+ if (*Ptr++ != FTW_ERASED_BYTE) {
+ IsEmpty = FALSE;
+ break;
+ }
+ }
+
+ return IsEmpty;
+}
+
+/**
+ To erase the block with the spare block size.
+
+
+ @param FtwDevice The private data of FTW driver
+ @param FvBlock FVB Protocol interface
+ @param Lba Lba of the firmware block
+
+ @retval EFI_SUCCESS Block LBA is Erased successfully
+ @retval Others Error occurs
+
+**/
+EFI_STATUS
+FtwEraseBlock (
+ IN EFI_FTW_DEVICE *FtwDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+{
+ return FvBlock->EraseBlocks (
+ FvBlock,
+ Lba,
+ FtwDevice->NumberOfSpareBlock,
+ EFI_LBA_LIST_TERMINATOR
+ );
+}
+
+/**
+ Erase spare block.
+
+ @param FtwDevice The private data of FTW driver
+
+ @retval EFI_SUCCESS The erase request was successfully completed.
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+ @retval EFI_DEVICE_ERROR The block device is not functioning
+ correctly and could not be written.
+ The firmware device may have been
+ partially erased.
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
+ in the variable argument list do
+ not exist in the firmware volume.
+
+
+**/
+EFI_STATUS
+FtwEraseSpareBlock (
+ IN EFI_FTW_DEVICE *FtwDevice
+ )
+{
+ return FtwDevice->FtwBackupFvb->EraseBlocks (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba,
+ FtwDevice->NumberOfSpareBlock,
+ EFI_LBA_LIST_TERMINATOR
+ );
+}
+
+/**
+
+ Is it in working block?
+
+ @param FtwDevice The private data of FTW driver
+ @param FvBlock Fvb protocol instance
+ @param Lba The block specified
+
+ @return A BOOLEAN value indicating in working block or not.
+
+**/
+BOOLEAN
+IsWorkingBlock (
+ EFI_FTW_DEVICE *FtwDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+{
+ //
+ // If matching the following condition, the target block is in working block.
+ // 1. Target block is on the FV of working block (Using the same FVB protocol instance).
+ // 2. Lba falls into the range of working block.
+ //
+ return (BOOLEAN)
+ (
+ (FvBlock == FtwDevice->FtwFvBlock) &&
+ (Lba >= FtwDevice->FtwWorkBlockLba) &&
+ (Lba <= FtwDevice->FtwWorkSpaceLba)
+ );
+}
+
+/**
+
+ Get firmware block by address.
+
+
+ @param Address Address specified the block
+ @param FvBlock The block caller wanted
+
+ @retval EFI_SUCCESS The protocol instance if found.
+ @retval EFI_NOT_FOUND Block not found
+
+**/
+EFI_HANDLE
+GetFvbByAddress (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS FvbBaseAddress;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_HANDLE FvbHandle;
+
+ *FvBlock = NULL;
+ FvbHandle = NULL;
+ //
+ // Locate all handles of Fvb protocol
+ //
+ Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ //
+ // Get the FVB to access variable store
+ //
+ for (Index = 0; Index < HandleCount; Index += 1) {
+ Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Compare the address and select the right one
+ //
+ Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
+ if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + (FwVolHeader->FvLength - 1)))) {
+ *FvBlock = Fvb;
+ FvbHandle = HandleBuffer[Index];
+ break;
+ }
+ }
+
+ FreePool (HandleBuffer);
+ return FvbHandle;
+}
+
+/**
+
+ Is it in boot block?
+
+ @param FtwDevice The private data of FTW driver
+ @param FvBlock Fvb protocol instance
+ @param Lba The block specified
+
+ @return A BOOLEAN value indicating in boot block or not.
+
+**/
+BOOLEAN
+IsBootBlock (
+ EFI_FTW_DEVICE *FtwDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+{
+ EFI_STATUS Status;
+ EFI_SWAP_ADDRESS_RANGE_PROTOCOL *SarProtocol;
+ EFI_PHYSICAL_ADDRESS BootBlockBase;
+ UINTN BootBlockSize;
+ EFI_PHYSICAL_ADDRESS BackupBlockBase;
+ UINTN BackupBlockSize;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
+ BOOLEAN IsSwapped;
+ EFI_HANDLE FvbHandle;
+
+ if (!FeaturePcdGet(PcdFullFtwServiceEnable)) {
+ return FALSE;
+ }
+
+ Status = FtwGetSarProtocol ((VOID **) &SarProtocol);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ //
+ // Get the boot block range
+ //
+ Status = SarProtocol->GetRangeLocation (
+ SarProtocol,
+ &BootBlockBase,
+ &BootBlockSize,
+ &BackupBlockBase,
+ &BackupBlockSize
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = SarProtocol->GetSwapState (SarProtocol, &IsSwapped);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ //
+ // Get FVB by address
+ //
+ if (!IsSwapped) {
+ FvbHandle = GetFvbByAddress (BootBlockBase, &BootFvb);
+ } else {
+ FvbHandle = GetFvbByAddress (BackupBlockBase, &BootFvb);
+ }
+
+ if (FvbHandle == NULL) {
+ return FALSE;
+ }
+ //
+ // Compare the Fvb
+ //
+ return (BOOLEAN) (FvBlock == BootFvb);
+}
+
+/**
+ Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW working FVB protocol interface. LBA is 1.
+ Target block is accessed by FvbBlock protocol interface. LBA is Lba.
+
+ FTW will do extra work on boot block update.
+ FTW should depend on a protocol of EFI_ADDRESS_RANGE_SWAP_PROTOCOL,
+ which is produced by a chipset driver.
+ FTW updating boot block steps may be:
+ 1. GetRangeLocation(), if the Range is inside the boot block, FTW know
+ that boot block will be update. It shall add a FLAG in the working block.
+ 2. When spare block is ready,
+ 3. SetSwapState(EFI_SWAPPED)
+ 4. erasing boot block,
+ 5. programming boot block until the boot block is ok.
+ 6. SetSwapState(UNSWAPPED)
+ FTW shall not allow to update boot block when battery state is error.
+
+ @param FtwDevice The private data of FTW driver
+
+ @retval EFI_SUCCESS Spare block content is copied to boot block
+ @retval EFI_INVALID_PARAMETER Input parameter error
+ @retval EFI_OUT_OF_RESOURCES Allocate memory error
+ @retval EFI_ABORTED The function could not complete successfully
+
+**/
+EFI_STATUS
+FlushSpareBlockToBootBlock (
+ EFI_FTW_DEVICE *FtwDevice
+ )
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Buffer;
+ UINTN Count;
+ UINT8 *Ptr;
+ UINTN Index;
+ BOOLEAN TopSwap;
+ EFI_SWAP_ADDRESS_RANGE_PROTOCOL *SarProtocol;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
+ EFI_LBA BootLba;
+
+ if (!FeaturePcdGet(PcdFullFtwServiceEnable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Locate swap address range protocol
+ //
+ Status = FtwGetSarProtocol ((VOID **) &SarProtocol);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate a memory buffer
+ //
+ Length = FtwDevice->SpareAreaLength;
+ Buffer = AllocatePool (Length);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Get TopSwap bit state
+ //
+ Status = SarProtocol->GetSwapState (SarProtocol, &TopSwap);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Get Top Swapped status - %r\n", Status));
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+
+ if (TopSwap) {
+ //
+ // Get FVB of current boot block
+ //
+ if (GetFvbByAddress (FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength, &BootFvb) == NULL) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Read data from current boot block
+ //
+ BootLba = 0;
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwDevice->BlockSize;
+ Status = BootFvb->Read (
+ BootFvb,
+ BootLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ } else {
+ //
+ // Read data from spare block
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwBackupFvb->Read (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Set TopSwap bit
+ //
+ Status = SarProtocol->SetSwapState (SarProtocol, TRUE);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+ }
+ //
+ // Erase current spare block
+ // Because TopSwap is set, this actually erase the top block (boot block)!
+ //
+ Status = FtwEraseSpareBlock (FtwDevice);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Write memory buffer currenet spare block. Still top block.
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwBackupFvb->Write (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Ftw: FVB Write boot block - %r\n", Status));
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+
+ FreePool (Buffer);
+
+ //
+ // Clear TopSwap bit
+ //
+ Status = SarProtocol->SetSwapState (SarProtocol, FALSE);
+
+ return Status;
+}
+
+/**
+ Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is 1.
+ Target block is accessed by FvbBlock protocol interface. LBA is Lba.
+
+
+ @param FtwDevice The private data of FTW driver
+ @param FvBlock FVB Protocol interface to access target block
+ @param Lba Lba of the target block
+
+ @retval EFI_SUCCESS Spare block content is copied to target block
+ @retval EFI_INVALID_PARAMETER Input parameter error
+ @retval EFI_OUT_OF_RESOURCES Allocate memory error
+ @retval EFI_ABORTED The function could not complete successfully
+
+**/
+EFI_STATUS
+FlushSpareBlockToTargetBlock (
+ EFI_FTW_DEVICE *FtwDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Buffer;
+ UINTN Count;
+ UINT8 *Ptr;
+ UINTN Index;
+
+ if ((FtwDevice == NULL) || (FvBlock == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Allocate a memory buffer
+ //
+ Length = FtwDevice->SpareAreaLength;
+ Buffer = AllocatePool (Length);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Read all content of spare block to memory buffer
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwBackupFvb->Read (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Erase the target block
+ //
+ Status = FtwEraseBlock (FtwDevice, FvBlock, Lba);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Write memory buffer to block, using the FvbBlock protocol interface
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwDevice->BlockSize;
+ Status = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Ftw: FVB Write block - %r\n", Status));
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+
+ FreePool (Buffer);
+
+ return Status;
+}
+
+/**
+ Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwDevice->FtwSpareLba.
+ Working block is accessed by FTW working FVB protocol interface. LBA is
+ FtwDevice->FtwWorkBlockLba.
+
+ Since the working block header is important when FTW initializes, the
+ state of the operation should be handled carefully. The Crc value is
+ calculated without STATE element.
+
+ @param FtwDevice The private data of FTW driver
+
+ @retval EFI_SUCCESS Spare block content is copied to target block
+ @retval EFI_OUT_OF_RESOURCES Allocate memory error
+ @retval EFI_ABORTED The function could not complete successfully
+
+**/
+EFI_STATUS
+FlushSpareBlockToWorkingBlock (
+ EFI_FTW_DEVICE *FtwDevice
+ )
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Buffer;
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
+ UINTN Count;
+ UINT8 *Ptr;
+ UINTN Index;
+ EFI_LBA WorkSpaceLbaOffset;
+
+ //
+ // Allocate a memory buffer
+ //
+ Length = FtwDevice->SpareAreaLength;
+ Buffer = AllocatePool (Length);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;
+
+ //
+ // To guarantee that the WorkingBlockValid is set on spare block
+ //
+ // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
+ // WorkingBlockValid);
+ // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
+ //
+ FtwUpdateFvState (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + WorkSpaceLbaOffset,
+ FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
+ WORKING_BLOCK_VALID
+ );
+ //
+ // Read from spare block to memory buffer
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwBackupFvb->Read (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Clear the CRC and STATE, copy data from spare to working block.
+ //
+ WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (Buffer + (UINTN) WorkSpaceLbaOffset * FtwDevice->BlockSize + FtwDevice->FtwWorkSpaceBase);
+ InitWorkSpaceHeader (WorkingBlockHeader);
+ WorkingBlockHeader->WorkingBlockValid = FTW_ERASE_POLARITY;
+ WorkingBlockHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;
+
+ //
+ // target block is working block, then
+ // Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
+ // before erase the working block.
+ //
+ // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
+ // WorkingBlockInvalid);
+ // So hardcode offset as sizeof(EFI_GUID)+sizeof(UINT32) to
+ // skip Signature and Crc.
+ //
+ Status = FtwUpdateFvState (
+ FtwDevice->FtwFvBlock,
+ FtwDevice->FtwWorkSpaceLba,
+ FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
+ WORKING_BLOCK_INVALID
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+
+ FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;
+
+ //
+ // Erase the working block
+ //
+ Status = FtwEraseBlock (FtwDevice, FtwDevice->FtwFvBlock, FtwDevice->FtwWorkBlockLba);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Write memory buffer to working block, using the FvbBlock protocol interface
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwFvBlock->Write (
+ FtwDevice->FtwFvBlock,
+ FtwDevice->FtwWorkBlockLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Ftw: FVB Write block - %r\n", Status));
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Since the memory buffer will not be used, free memory Buffer.
+ //
+ FreePool (Buffer);
+
+ //
+ // Update the VALID of the working block
+ //
+ // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER, WorkingBlockValid);
+ // So hardcode offset as sizeof(EFI_GUID)+sizeof(UINT32) to skip Signature and Crc.
+ //
+ Status = FtwUpdateFvState (
+ FtwDevice->FtwFvBlock,
+ FtwDevice->FtwWorkSpaceLba,
+ FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
+ WORKING_BLOCK_VALID
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ FtwDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update a bit of state on a block device. The location of the bit is
+ calculated by the (Lba, Offset, bit). Here bit is determined by the
+ the name of a certain bit.
+
+
+ @param FvBlock FVB Protocol interface to access SrcBlock and DestBlock
+ @param Lba Lba of a block
+ @param Offset Offset on the Lba
+ @param NewBit New value that will override the old value if it can be change
+
+ @retval EFI_SUCCESS A state bit has been updated successfully
+ @retval Others Access block device error.
+ Notes:
+ Assume all bits of State are inside the same BYTE.
+ @retval EFI_ABORTED Read block fail
+
+**/
+EFI_STATUS
+FtwUpdateFvState (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINT8 NewBit
+ )
+{
+ EFI_STATUS Status;
+ UINT8 State;
+ UINTN Length;
+
+ //
+ // Read state from device, assume State is only one byte.
+ //
+ Length = sizeof (UINT8);
+ Status = FvBlock->Read (FvBlock, Lba, Offset, &Length, &State);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ State ^= FTW_POLARITY_REVERT;
+ State = (UINT8) (State | NewBit);
+ State ^= FTW_POLARITY_REVERT;
+
+ //
+ // Write state back to device
+ //
+ Length = sizeof (UINT8);
+ Status = FvBlock->Write (FvBlock, Lba, Offset, &Length, &State);
+
+ return Status;
+}
+
+/**
+ Get the last Write Header pointer.
+ The last write header is the header whose 'complete' state hasn't been set.
+ After all, this header may be a EMPTY header entry for next Allocate.
+
+
+ @param FtwWorkSpaceHeader Pointer of the working block header
+ @param FtwWorkSpaceSize Size of the work space
+ @param FtwWriteHeader Pointer to retrieve the last write header
+
+ @retval EFI_SUCCESS Get the last write record successfully
+ @retval EFI_ABORTED The FTW work space is damaged
+
+**/
+EFI_STATUS
+FtwGetLastWriteHeader (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader,
+ IN UINTN FtwWorkSpaceSize,
+ OUT EFI_FAULT_TOLERANT_WRITE_HEADER **FtwWriteHeader
+ )
+{
+ UINTN Offset;
+ EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
+
+ *FtwWriteHeader = NULL;
+ FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) (FtwWorkSpaceHeader + 1);
+ Offset = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
+
+ while (FtwHeader->Complete == FTW_VALID_STATE) {
+ Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
+ //
+ // If Offset exceed the FTW work space boudary, return error.
+ //
+ if (Offset >= FtwWorkSpaceSize) {
+ *FtwWriteHeader = FtwHeader;
+ return EFI_ABORTED;
+ }
+
+ FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) ((UINT8 *) FtwWorkSpaceHeader + Offset);
+ }
+ //
+ // Last write header is found
+ //
+ *FtwWriteHeader = FtwHeader;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the last Write Record pointer. The last write Record is the Record
+ whose DestinationCompleted state hasn't been set. After all, this Record
+ may be a EMPTY record entry for next write.
+
+
+ @param FtwWriteHeader Pointer to the write record header
+ @param FtwWriteRecord Pointer to retrieve the last write record
+
+ @retval EFI_SUCCESS Get the last write record successfully
+ @retval EFI_ABORTED The FTW work space is damaged
+
+**/
+EFI_STATUS
+FtwGetLastWriteRecord (
+ IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwWriteHeader,
+ OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwWriteRecord
+ )
+{
+ UINTN Index;
+ EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord;
+
+ *FtwWriteRecord = NULL;
+ FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) (FtwWriteHeader + 1);
+
+ //
+ // Try to find the last write record "that has not completed"
+ //
+ for (Index = 0; Index < FtwWriteHeader->NumberOfWrites; Index += 1) {
+ if (FtwRecord->DestinationComplete != FTW_VALID_STATE) {
+ //
+ // The last write record is found
+ //
+ *FtwWriteRecord = FtwRecord;
+ return EFI_SUCCESS;
+ }
+
+ FtwRecord++;
+
+ if (FtwWriteHeader->PrivateDataSize != 0) {
+ FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + FtwWriteHeader->PrivateDataSize);
+ }
+ }
+ //
+ // if Index == NumberOfWrites, then
+ // the last record has been written successfully,
+ // but the Header->Complete Flag has not been set.
+ // also return the last record.
+ //
+ if (Index == FtwWriteHeader->NumberOfWrites) {
+ *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
+ return EFI_SUCCESS;
+ }
+
+ return EFI_ABORTED;
+}
+
+/**
+ To check if FtwRecord is the first record of FtwHeader.
+
+ @param FtwHeader Pointer to the write record header
+ @param FtwRecord Pointer to the write record
+
+ @retval TRUE FtwRecord is the first Record of the FtwHeader
+ @retval FALSE FtwRecord is not the first Record of the FtwHeader
+
+**/
+BOOLEAN
+IsFirstRecordOfWrites (
+ IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
+ IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord
+ )
+{
+ UINT8 *Head;
+ UINT8 *Ptr;
+
+ Head = (UINT8 *) FtwHeader;
+ Ptr = (UINT8 *) FtwRecord;
+
+ Head += sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER);
+ return (BOOLEAN) (Head == Ptr);
+}
+
+/**
+ To check if FtwRecord is the last record of FtwHeader. Because the
+ FtwHeader has NumberOfWrites & PrivateDataSize, the FtwRecord can be
+ determined if it is the last record of FtwHeader.
+
+ @param FtwHeader Pointer to the write record header
+ @param FtwRecord Pointer to the write record
+
+ @retval TRUE FtwRecord is the last Record of the FtwHeader
+ @retval FALSE FtwRecord is not the last Record of the FtwHeader
+
+**/
+BOOLEAN
+IsLastRecordOfWrites (
+ IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
+ IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord
+ )
+{
+ UINT8 *Head;
+ UINT8 *Ptr;
+
+ Head = (UINT8 *) FtwHeader;
+ Ptr = (UINT8 *) FtwRecord;
+
+ Head += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);
+ return (BOOLEAN) (Head == Ptr);
+}
+
+/**
+ To check if FtwRecord is the first record of FtwHeader.
+
+ @param FtwHeader Pointer to the write record header
+ @param FtwRecord Pointer to retrieve the previous write record
+
+ @retval EFI_ACCESS_DENIED Input record is the first record, no previous record is return.
+ @retval EFI_SUCCESS The previous write record is found.
+
+**/
+EFI_STATUS
+GetPreviousRecordOfWrites (
+ IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
+ IN OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwRecord
+ )
+{
+ UINT8 *Ptr;
+
+ if (IsFirstRecordOfWrites (FtwHeader, *FtwRecord)) {
+ *FtwRecord = NULL;
+ return EFI_ACCESS_DENIED;
+ }
+
+ Ptr = (UINT8 *) (*FtwRecord);
+ Ptr -= RECORD_SIZE (FtwHeader->PrivateDataSize);
+ *FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) Ptr;
+ return EFI_SUCCESS;
+}
+
+/**
+ Allocate private data for FTW driver and initialize it.
+
+ @param[out] FtwData Pointer to the FTW device structure
+
+ @retval EFI_SUCCESS Initialize the FTW device successfully.
+ @retval EFI_OUT_OF_RESOURCES Allocate memory error
+ @retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
+
+**/
+EFI_STATUS
+InitFtwDevice (
+ OUT EFI_FTW_DEVICE **FtwData
+ )
+{
+ EFI_FTW_DEVICE *FtwDevice;
+
+ //
+ // Allocate private data of this driver,
+ // Including the FtwWorkSpace[FTW_WORK_SPACE_SIZE].
+ //
+ FtwDevice = AllocateZeroPool (sizeof (EFI_FTW_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize));
+ if (FtwDevice == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
+ //
+ FtwDevice->WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+ FtwDevice->SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+ if ((FtwDevice->WorkSpaceLength == 0) || (FtwDevice->SpareAreaLength == 0)) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));
+ FreePool (FtwDevice);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FtwDevice->Signature = FTW_DEVICE_SIGNATURE;
+ FtwDevice->FtwFvBlock = NULL;
+ FtwDevice->FtwBackupFvb = NULL;
+ FtwDevice->FtwWorkSpaceLba = (EFI_LBA) (-1);
+ FtwDevice->FtwSpareLba = (EFI_LBA) (-1);
+
+ FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwWorkingBase64);
+ if (FtwDevice->WorkSpaceAddress == 0) {
+ FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
+ }
+
+ FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwSpareBase64);
+ if (FtwDevice->SpareAreaAddress == 0) {
+ FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);
+ }
+
+ *FtwData = FtwDevice;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Find the proper Firmware Volume Block protocol for FTW operation.
+
+ @param[in, out] FtwDevice Pointer to the FTW device structure
+
+ @retval EFI_SUCCESS Find the FVB protocol successfully.
+ @retval EFI_NOT_FOUND No proper FVB protocol was found.
+ @retval EFI_ABORTED Some data can not be got or be invalid.
+
+**/
+EFI_STATUS
+FindFvbForFtw (
+ IN OUT EFI_FTW_DEVICE *FtwDevice
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS FvbBaseAddress;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+ EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
+ UINT32 LbaIndex;
+
+ //
+ // Get all FVB handle.
+ //
+ Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the FVB to access variable store
+ //
+ Fvb = NULL;
+ for (Index = 0; Index < HandleCount; Index += 1) {
+ Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ //
+ // Ensure this FVB protocol support Write operation.
+ //
+ Status = Fvb->GetAttributes (Fvb, &Attributes);
+ if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
+ continue;
+ }
+ //
+ // Compare the address and select the right one
+ //
+ Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
+ if ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) &&
+ ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + FwVolHeader->FvLength))
+ ) {
+ FtwDevice->FtwFvBlock = Fvb;
+ //
+ // To get the LBA of work space
+ //
+ if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
+ //
+ // Now, one FV has one type of BlockLength
+ //
+ FvbMapEntry = &FwVolHeader->BlockMap[0];
+ for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
+ if ((FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))
+ && (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {
+ FtwDevice->FtwWorkSpaceLba = LbaIndex - 1;
+ //
+ // Get the Work space size and Base(Offset)
+ //
+ FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength;
+ FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
+ break;
+ }
+ }
+ }
+ }
+
+ if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) &&
+ ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + FwVolHeader->FvLength))
+ ) {
+ FtwDevice->FtwBackupFvb = Fvb;
+ //
+ // To get the LBA of spare
+ //
+ if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
+ //
+ // Now, one FV has one type of BlockLength
+ //
+ FvbMapEntry = &FwVolHeader->BlockMap[0];
+ for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
+ if ((FtwDevice->SpareAreaAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))
+ && (FtwDevice->SpareAreaAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {
+ //
+ // Get the NumberOfSpareBlock and BlockSize
+ //
+ FtwDevice->FtwSpareLba = LbaIndex - 1;
+ FtwDevice->BlockSize = FvbMapEntry->Length;
+ FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->BlockSize;
+ //
+ // Check the range of spare area to make sure that it's in FV range
+ //
+ if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > FvbMapEntry->NumBlocks) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Spare area is out of FV range\n"));
+ FreePool (HandleBuffer);
+ ASSERT (FALSE);
+ return EFI_ABORTED;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ FreePool (HandleBuffer);
+
+ if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) ||
+ (FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) {
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialization for Fault Tolerant Write protocol.
+
+ @param[in, out] FtwDevice Pointer to the FTW device structure
+
+ @retval EFI_SUCCESS Initialize the FTW protocol successfully.
+ @retval EFI_NOT_FOUND No proper FVB protocol was found.
+
+**/
+EFI_STATUS
+InitFtwProtocol (
+ IN OUT EFI_FTW_DEVICE *FtwDevice
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ UINTN Length;
+ EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
+ UINTN Offset;
+ EFI_HANDLE FvbHandle;
+
+ //
+ // Find the right SMM Fvb protocol instance for FTW.
+ //
+ Status = FindFvbForFtw (FtwDevice);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Calculate the start LBA of working block. Working block is an area which
+ // contains working space in its last block(s) and has the same size as spare
+ // block, unless there are not enough blocks before the block that contains
+ // working space.
+ //
+ if (FtwDevice->BlockSize > FtwDevice->FtwWorkSpaceSize) {
+ FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + 1;
+ } else {
+ FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + (FtwDevice->FtwWorkSpaceSize/FtwDevice->BlockSize);
+ }
+ ASSERT ((INT64) (FtwDevice->FtwWorkBlockLba) >= 0);
+
+ //
+ // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
+ //
+ FtwDevice->FtwWorkSpace = (UINT8 *) (FtwDevice + 1);
+ FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwDevice->FtwWorkSpace;
+
+ FtwDevice->FtwLastWriteHeader = NULL;
+ FtwDevice->FtwLastWriteRecord = NULL;
+
+ //
+ // Refresh the working space data from working block
+ //
+ Status = WorkSpaceRefresh (FtwDevice);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // If the working block workspace is not valid, try the spare block
+ //
+ if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
+ //
+ // Read from spare block
+ //
+ Length = FtwDevice->FtwWorkSpaceSize;
+ Status = FtwDevice->FtwBackupFvb->Read (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba,
+ FtwDevice->FtwWorkSpaceBase,
+ &Length,
+ FtwDevice->FtwWorkSpace
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // If spare block is valid, then replace working block content.
+ //
+ if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
+ Status = FlushSpareBlockToWorkingBlock (FtwDevice);
+ DEBUG ((EFI_D_ERROR, "Ftw: Restart working block update in InitFtwProtocol() - %r\n", Status));
+ FtwAbort (&FtwDevice->FtwInstance);
+ //
+ // Refresh work space.
+ //
+ Status = WorkSpaceRefresh (FtwDevice);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n"));
+ //
+ // If both are invalid, then initialize work space.
+ //
+ SetMem (
+ FtwDevice->FtwWorkSpace,
+ FtwDevice->FtwWorkSpaceSize,
+ FTW_ERASED_BYTE
+ );
+ InitWorkSpaceHeader (FtwDevice->FtwWorkSpaceHeader);
+ //
+ // Initialize the work space
+ //
+ Status = FtwReclaimWorkSpace (FtwDevice, FALSE);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ //
+ // If the FtwDevice->FtwLastWriteRecord is 1st record of write header &&
+ // (! SpareComplete) THEN call Abort().
+ //
+ if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) &&
+ (FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) &&
+ IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
+ ) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n"));
+ FtwAbort (&FtwDevice->FtwInstance);
+ }
+ //
+ // If Header is incompleted and the last record has completed, then
+ // call Abort() to set the Header->Complete FLAG.
+ //
+ if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
+ (FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) &&
+ IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
+ ) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n"));
+ FtwAbort (&FtwDevice->FtwInstance);
+ }
+ //
+ // To check the workspace buffer following last Write header/records is EMPTY or not.
+ // If it's not EMPTY, FTW also need to call reclaim().
+ //
+ FtwHeader = FtwDevice->FtwLastWriteHeader;
+ Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace;
+ if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
+ Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
+ }
+
+ if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {
+ Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Restart if it's boot block
+ //
+ if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
+ (FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE)
+ ) {
+ if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) {
+ Status = FlushSpareBlockToBootBlock (FtwDevice);
+ DEBUG ((EFI_D_ERROR, "Ftw: Restart boot block update - %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ FtwAbort (&FtwDevice->FtwInstance);
+ } else {
+ //
+ // if (SpareCompleted) THEN Restart to fault tolerant write.
+ //
+ FvbHandle = NULL;
+ FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb);
+ if (FvbHandle != NULL) {
+ Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);
+ DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ FtwAbort (&FtwDevice->FtwInstance);
+ }
+ }
+ //
+ // Hook the protocol API
+ //
+ FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize;
+ FtwDevice->FtwInstance.Allocate = FtwAllocate;
+ FtwDevice->FtwInstance.Write = FtwWrite;
+ FtwDevice->FtwInstance.Restart = FtwRestart;
+ FtwDevice->FtwInstance.Abort = FtwAbort;
+ FtwDevice->FtwInstance.GetLastWrite = FtwGetLastWrite;
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
new file mode 100755
index 0000000..913df1a
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
@@ -0,0 +1,553 @@
+/** @file
+
+ Internal functions to operate Working Block Space.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "FaultTolerantWrite.h"
+
+/**
+ Check to see if it is a valid work space.
+
+
+ @param WorkingHeader Pointer of working block header
+
+ @retval TRUE The work space is valid.
+ @retval FALSE The work space is invalid.
+
+**/
+BOOLEAN
+IsValidWorkSpace (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER WorkingBlockHeader;
+
+ if (WorkingHeader == NULL) {
+ return FALSE;
+ }
+
+ if (WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Work block header valid bit check error\n"));
+ return FALSE;
+ }
+ //
+ // Check signature with gEfiSystemNvDataFvGuid
+ //
+ if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Work block header signature check error\n"));
+ return FALSE;
+ }
+ //
+ // Check the CRC of header
+ //
+ CopyMem (
+ &WorkingBlockHeader,
+ WorkingHeader,
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
+ );
+
+ //
+ // Filter out the Crc and State fields
+ //
+ SetMem (
+ &WorkingBlockHeader.Crc,
+ sizeof (UINT32),
+ FTW_ERASED_BYTE
+ );
+ WorkingBlockHeader.WorkingBlockValid = FTW_ERASE_POLARITY;
+ WorkingBlockHeader.WorkingBlockInvalid = FTW_ERASE_POLARITY;
+
+ //
+ // Calculate the Crc of woking block header
+ //
+ Status = gBS->CalculateCrc32 (
+ (UINT8 *) &WorkingBlockHeader,
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
+ &WorkingBlockHeader.Crc
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ if (WorkingBlockHeader.Crc != WorkingHeader->Crc) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Work block header CRC check error\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Initialize a work space when there is no work space.
+
+ @param WorkingHeader Pointer of working block header
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_ABORTED The function could not complete successfully.
+
+**/
+EFI_STATUS
+InitWorkSpaceHeader (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
+ )
+{
+ EFI_STATUS Status;
+
+ if (WorkingHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Here using gEfiSystemNvDataFvGuid as the signature.
+ //
+ CopyMem (
+ &WorkingHeader->Signature,
+ &gEfiSystemNvDataFvGuid,
+ sizeof (EFI_GUID)
+ );
+ WorkingHeader->WriteQueueSize = (UINT64) (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
+
+ //
+ // Crc is calculated with all the fields except Crc and STATE
+ //
+ WorkingHeader->WorkingBlockValid = FTW_ERASE_POLARITY;
+ WorkingHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;
+
+ SetMem (
+ &WorkingHeader->Crc,
+ sizeof (UINT32),
+ FTW_ERASED_BYTE
+ );
+
+ //
+ // Calculate the CRC value
+ //
+ Status = gBS->CalculateCrc32 (
+ (UINT8 *) WorkingHeader,
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
+ &WorkingHeader->Crc
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Restore the WorkingBlockValid flag to VALID state
+ //
+ WorkingHeader->WorkingBlockValid = FTW_VALID_STATE;
+ WorkingHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read from working block to refresh the work space in memory.
+
+ @param FtwDevice Point to private data of FTW driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_ABORTED The function could not complete successfully.
+
+**/
+EFI_STATUS
+WorkSpaceRefresh (
+ IN EFI_FTW_DEVICE *FtwDevice
+ )
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Ptr;
+ UINT8 LbaIndex;
+ UINTN Base;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Initialize WorkSpace as FTW_ERASED_BYTE
+ //
+ SetMem (
+ FtwDevice->FtwWorkSpace,
+ FtwDevice->FtwWorkSpaceSize,
+ FTW_ERASED_BYTE
+ );
+
+ //
+ // Read from working block
+ //
+ Ptr = FtwDevice->FtwWorkSpace;
+ for (LbaIndex = 0; LbaIndex < (FtwDevice->FtwWorkSpaceSize/FtwDevice->BlockSize); LbaIndex++) {
+ Base = 0;
+ if (LbaIndex == ((FtwDevice->FtwWorkSpaceSize/FtwDevice->BlockSize) - 1)) {
+ if ((FtwDevice->FtwWorkSpaceSize%FtwDevice->BlockSize) == 0) {
+ Length = FtwDevice->BlockSize;
+ } else {
+ Length = FtwDevice->FtwWorkSpaceSize%FtwDevice->BlockSize;
+ }
+ } else if (LbaIndex == 0) {
+ Length = (FtwDevice->BlockSize - FtwDevice->FtwWorkSpaceBase);
+ Base = FtwDevice->FtwWorkSpaceBase;
+ } else {
+ Length = FtwDevice->BlockSize;
+ }
+
+ Status = FtwDevice->FtwFvBlock->Read (
+ FtwDevice->FtwFvBlock,
+ (FtwDevice->FtwWorkSpaceLba + LbaIndex),
+ Base,
+ &Length,
+ Ptr
+ );
+ Ptr += Length;
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Refresh the FtwLastWriteHeader
+ //
+ Status = FtwGetLastWriteHeader (
+ FtwDevice->FtwWorkSpaceHeader,
+ FtwDevice->FtwWorkSpaceSize,
+ &FtwDevice->FtwLastWriteHeader
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // reclaim work space in working block.
+ //
+ Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Reclaim workspace - %r\n", Status));
+ return EFI_ABORTED;
+ }
+ //
+ // Read from working block again
+ //
+ Ptr = FtwDevice->FtwWorkSpace;
+ for (LbaIndex = 0; LbaIndex < (FtwDevice->FtwWorkSpaceSize/FtwDevice->BlockSize); LbaIndex++) {
+ Base = 0;
+ if (LbaIndex == ((FtwDevice->FtwWorkSpaceSize/FtwDevice->BlockSize) - 1)) {
+ if ((FtwDevice->FtwWorkSpaceSize%FtwDevice->BlockSize) == 0) {
+ Length = FtwDevice->BlockSize;
+ } else {
+ Length = FtwDevice->FtwWorkSpaceSize%FtwDevice->BlockSize;
+ }
+ } else if (LbaIndex == 0) {
+ Length = (FtwDevice->BlockSize - FtwDevice->FtwWorkSpaceBase);
+ Base = FtwDevice->FtwWorkSpaceBase;
+ } else {
+ Length = FtwDevice->BlockSize;
+ }
+
+ Status = FtwDevice->FtwFvBlock->Read (
+ FtwDevice->FtwFvBlock,
+ (FtwDevice->FtwWorkSpaceLba + LbaIndex),
+ Base,
+ &Length,
+ Ptr
+ );
+ Ptr += Length;
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ Status = FtwGetLastWriteHeader (
+ FtwDevice->FtwWorkSpaceHeader,
+ FtwDevice->FtwWorkSpaceSize,
+ &FtwDevice->FtwLastWriteHeader
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Refresh the FtwLastWriteRecord
+ //
+ Status = FtwGetLastWriteRecord (
+ FtwDevice->FtwLastWriteHeader,
+ &FtwDevice->FtwLastWriteRecord
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reclaim the work space on the working block.
+
+ @param FtwDevice Point to private data of FTW driver
+ @param PreserveRecord Whether to preserve the working record is needed
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Allocate memory error
+ @retval EFI_ABORTED The function could not complete successfully
+
+**/
+EFI_STATUS
+FtwReclaimWorkSpace (
+ IN EFI_FTW_DEVICE *FtwDevice,
+ IN BOOLEAN PreserveRecord
+ )
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ EFI_FAULT_TOLERANT_WRITE_HEADER *Header;
+ UINT8 *TempBuffer;
+ UINTN TempBufferSize;
+ UINTN SpareBufferSize;
+ UINT8 *SpareBuffer;
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
+ UINTN Index;
+ UINT8 *Ptr;
+ EFI_LBA WorkSpaceLbaOffset;
+
+ DEBUG ((EFI_D_ERROR, "Ftw: start to reclaim work space\n"));
+
+ WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;
+
+ //
+ // Read all original data from working block to a memory buffer
+ //
+ TempBufferSize = FtwDevice->SpareAreaLength;
+ TempBuffer = AllocateZeroPool (TempBufferSize);
+ if (TempBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = TempBuffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Length = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwFvBlock->Read (
+ FtwDevice->FtwFvBlock,
+ FtwDevice->FtwWorkBlockLba + Index,
+ 0,
+ &Length,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (TempBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+ //
+ // Clean up the workspace, remove all the completed records.
+ //
+ Ptr = TempBuffer +
+ (UINTN) WorkSpaceLbaOffset * FtwDevice->BlockSize +
+ FtwDevice->FtwWorkSpaceBase;
+
+ //
+ // Clear the content of buffer that will save the new work space data
+ //
+ SetMem (Ptr, FtwDevice->FtwWorkSpaceSize, FTW_ERASED_BYTE);
+
+ //
+ // Copy EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER to buffer
+ //
+ CopyMem (
+ Ptr,
+ FtwDevice->FtwWorkSpaceHeader,
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
+ );
+ if (PreserveRecord) {
+ //
+ // Get the last record following the header,
+ //
+ Status = FtwGetLastWriteHeader (
+ FtwDevice->FtwWorkSpaceHeader,
+ FtwDevice->FtwWorkSpaceSize,
+ &FtwDevice->FtwLastWriteHeader
+ );
+ Header = FtwDevice->FtwLastWriteHeader;
+ if (!EFI_ERROR (Status) && (Header != NULL) && (Header->Complete != FTW_VALID_STATE) && (Header->HeaderAllocated == FTW_VALID_STATE)) {
+ CopyMem (
+ Ptr + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
+ FtwDevice->FtwLastWriteHeader,
+ WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)
+ );
+ }
+ }
+
+ CopyMem (
+ FtwDevice->FtwWorkSpace,
+ Ptr,
+ FtwDevice->FtwWorkSpaceSize
+ );
+
+ FtwGetLastWriteHeader (
+ FtwDevice->FtwWorkSpaceHeader,
+ FtwDevice->FtwWorkSpaceSize,
+ &FtwDevice->FtwLastWriteHeader
+ );
+
+ FtwGetLastWriteRecord (
+ FtwDevice->FtwLastWriteHeader,
+ &FtwDevice->FtwLastWriteRecord
+ );
+
+ //
+ // Set the WorkingBlockValid and WorkingBlockInvalid as INVALID
+ //
+ WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (TempBuffer +
+ (UINTN) WorkSpaceLbaOffset * FtwDevice->BlockSize +
+ FtwDevice->FtwWorkSpaceBase);
+ WorkingBlockHeader->WorkingBlockValid = FTW_INVALID_STATE;
+ WorkingBlockHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
+
+ //
+ // Try to keep the content of spare block
+ // Save spare block into a spare backup memory buffer (Sparebuffer)
+ //
+ SpareBufferSize = FtwDevice->SpareAreaLength;
+ SpareBuffer = AllocatePool (SpareBufferSize);
+ if (SpareBuffer == NULL) {
+ FreePool (TempBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = SpareBuffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Length = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwBackupFvb->Read (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + Index,
+ 0,
+ &Length,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (TempBuffer);
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+ //
+ // Write the memory buffer to spare block
+ //
+ Status = FtwEraseSpareBlock (FtwDevice);
+ Ptr = TempBuffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Length = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwBackupFvb->Write (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + Index,
+ 0,
+ &Length,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (TempBuffer);
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+ //
+ // Free TempBuffer
+ //
+ FreePool (TempBuffer);
+
+ //
+ // Set the WorkingBlockValid in spare block
+ //
+ Status = FtwUpdateFvState (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + WorkSpaceLbaOffset,
+ FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
+ WORKING_BLOCK_VALID
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Before erase the working block, set WorkingBlockInvalid in working block.
+ //
+ // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
+ // WorkingBlockInvalid);
+ //
+ Status = FtwUpdateFvState (
+ FtwDevice->FtwFvBlock,
+ FtwDevice->FtwWorkSpaceLba,
+ FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
+ WORKING_BLOCK_INVALID
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;
+
+ //
+ // Write the spare block to working block
+ //
+ Status = FlushSpareBlockToWorkingBlock (FtwDevice);
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return Status;
+ }
+ //
+ // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
+ //
+ Status = FtwEraseSpareBlock (FtwDevice);
+ Ptr = SpareBuffer;
+ for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
+ Length = FtwDevice->BlockSize;
+ Status = FtwDevice->FtwBackupFvb->Write (
+ FtwDevice->FtwBackupFvb,
+ FtwDevice->FtwSpareLba + Index,
+ 0,
+ &Length,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+
+ FreePool (SpareBuffer);
+
+ DEBUG ((EFI_D_ERROR, "Ftw: reclaim work space successfully\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
new file mode 100755
index 0000000..3fd4773
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
@@ -0,0 +1,407 @@
+/** @file
+ LockBox SMM driver.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - communicate buffer in SMM mode.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave()
+ will receive untrusted input and do basic validation.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiSmm.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/LockBoxLib.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <Protocol/SmmCommunication.h>
+#include <Protocol/SmmAccess2.h>
+#include <Protocol/LockBox.h>
+#include <Guid/SmmLockBox.h>
+
+BOOLEAN mLocked = FALSE;
+
+EFI_SMRAM_DESCRIPTOR *mSmramRanges;
+UINTN mSmramRangeCount;
+
+/**
+ This function check if the address is in SMRAM.
+
+ @param Buffer the buffer address to be checked.
+ @param Length the buffer length to be checked.
+
+ @retval TRUE this address is in SMRAM.
+ @retval FALSE this address is NOT in SMRAM.
+**/
+BOOLEAN
+IsAddressInSmram (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < mSmramRangeCount; Index ++) {
+ if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||
+ ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Dispatch function for SMM lock box save.
+
+ @param LockBoxParameterSave parameter of lock box save
+**/
+VOID
+SmmLockBoxSave (
+ IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sanity check
+ //
+ if (mLocked) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));
+ LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
+ return ;
+ }
+
+ //
+ // Save data
+ //
+ Status = SaveLockBox (
+ &LockBoxParameterSave->Guid,
+ (VOID *)(UINTN)LockBoxParameterSave->Buffer,
+ (UINTN)LockBoxParameterSave->Length
+ );
+ LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status;
+ return ;
+}
+
+/**
+ Dispatch function for SMM lock box set attributes.
+
+ @param LockBoxParameterSetAttributes parameter of lock box set attributes
+**/
+VOID
+SmmLockBoxSetAttributes (
+ IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sanity check
+ //
+ if (mLocked) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));
+ LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
+ return ;
+ }
+
+ //
+ // Update data
+ //
+ Status = SetLockBoxAttributes (
+ &LockBoxParameterSetAttributes->Guid,
+ LockBoxParameterSetAttributes->Attributes
+ );
+ LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status;
+ return ;
+}
+
+/**
+ Dispatch function for SMM lock box update.
+
+ @param LockBoxParameterUpdate parameter of lock box update
+**/
+VOID
+SmmLockBoxUpdate (
+ IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sanity check
+ //
+ if (mLocked) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));
+ LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
+ return ;
+ }
+
+ //
+ // Update data
+ //
+ Status = UpdateLockBox (
+ &LockBoxParameterUpdate->Guid,
+ (UINTN)LockBoxParameterUpdate->Offset,
+ (VOID *)(UINTN)LockBoxParameterUpdate->Buffer,
+ (UINTN)LockBoxParameterUpdate->Length
+ );
+ LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status;
+ return ;
+}
+
+/**
+ Dispatch function for SMM lock box restore.
+
+ @param LockBoxParameterRestore parameter of lock box restore
+**/
+VOID
+SmmLockBoxRestore (
+ IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sanity check
+ //
+ if (IsAddressInSmram (LockBoxParameterRestore->Buffer, LockBoxParameterRestore->Length)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM!\n"));
+ LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
+ return ;
+ }
+
+ //
+ // Restore data
+ //
+ if ((LockBoxParameterRestore->Length == 0) && (LockBoxParameterRestore->Buffer == 0)) {
+ Status = RestoreLockBox (
+ &LockBoxParameterRestore->Guid,
+ NULL,
+ NULL
+ );
+ } else {
+ Status = RestoreLockBox (
+ &LockBoxParameterRestore->Guid,
+ (VOID *)(UINTN)LockBoxParameterRestore->Buffer,
+ (UINTN *)&LockBoxParameterRestore->Length
+ );
+ }
+ LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;
+ return ;
+}
+
+/**
+ Dispatch function for SMM lock box restore all in place.
+
+ @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place
+**/
+VOID
+SmmLockBoxRestoreAllInPlace (
+ IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RestoreAllLockBoxInPlace ();
+ LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status;
+ return ;
+}
+
+/**
+ Dispatch function for a Software SMI handler.
+
+ @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param Context Points to an optional handler context which was specified when the
+ handler was registered.
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS Command is handled successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader;
+
+ DEBUG ((EFI_D_INFO, "SmmLockBox SmmLockBoxHandler Enter\n"));
+
+ LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer);
+
+ LockBoxParameterHeader->ReturnStatus = (UINT64)-1;
+
+ DEBUG ((EFI_D_INFO, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader));
+
+ DEBUG ((EFI_D_INFO, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command));
+
+ switch (LockBoxParameterHeader->Command) {
+ case EFI_SMM_LOCK_BOX_COMMAND_SAVE:
+ SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader);
+ break;
+ case EFI_SMM_LOCK_BOX_COMMAND_UPDATE:
+ SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader);
+ break;
+ case EFI_SMM_LOCK_BOX_COMMAND_RESTORE:
+ SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader);
+ break;
+ case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES:
+ SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader);
+ break;
+ case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE:
+ SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)(UINTN)LockBoxParameterHeader);
+ break;
+ default:
+ break;
+ }
+
+ LockBoxParameterHeader->Command = (UINT32)-1;
+
+ DEBUG ((EFI_D_INFO, "SmmLockBox SmmLockBoxHandler Exit\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Smm Ready To Lock event notification handler.
+
+ It sets a flag indicating that SMRAM has been locked.
+
+ @param[in] Protocol Points to the protocol's unique identifier.
+ @param[in] Interface Points to the interface instance.
+ @param[in] Handle The handle on which the interface was installed.
+
+ @retval EFI_SUCCESS Notification handler runs successfully.
+ **/
+EFI_STATUS
+EFIAPI
+SmmReadyToLockEventNotify (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ mLocked = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Entry Point for LockBox SMM driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCEESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DispatchHandle;
+ VOID *Registration;
+ EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
+ UINTN Size;
+
+ //
+ // Get SMRAM information
+ //
+ Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
+ ASSERT_EFI_ERROR (Status);
+
+ Size = 0;
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ Size,
+ (VOID **)&mSmramRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);
+ ASSERT_EFI_ERROR (Status);
+
+ mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+
+ //
+ // Register LockBox communication handler
+ //
+ Status = gSmst->SmiHandlerRegister (
+ SmmLockBoxHandler,
+ &gEfiSmmLockBoxCommunicationGuid,
+ &DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register SMM Ready To Lock Protocol notification
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmReadyToLockProtocolGuid,
+ SmmReadyToLockEventNotify,
+ &Registration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install NULL to DXE data base as notify
+ //
+ ImageHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gEfiLockBoxProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
new file mode 100755
index 0000000..9296c01
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
@@ -0,0 +1,79 @@
+## @file
+# Component description file for LockBox SMM driver.
+#
+# Caution: This module requires additional review when modified.
+# This driver will have external input - communicate buffer in SMM mode.
+# This external input must be validated carefully to avoid security issue like
+# buffer overflow, integer overflow.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmLockBox
+ FILE_GUID = 33FB3535-F15E-4c17-B303-5EB94595ECB6
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SmmLockBoxEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SmmLockBox.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ SmmServicesTableLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ LockBoxLib
+
+[Guids]
+ gEfiSmmLockBoxCommunicationGuid ## PRODUCED
+
+[Protocols]
+ gEfiSmmReadyToLockProtocolGuid ## CONSUMED
+ gEfiSmmAccess2ProtocolGuid ## CONSUMED
+ gEfiLockBoxProtocolGuid ## PRODUCED
+
+[Depex]
+ gEfiSmmSwDispatch2ProtocolGuid
+
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
new file mode 100644
index 0000000..0ccb49a
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -0,0 +1,2778 @@
+/** @file
+
+ The common variable operation routines shared by DXE_RUNTIME variable
+ module and DXE_SMM variable module.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Variable.h"
+#include <Guid/MemoryConfigData.h>
+#include <Guid/QuarkVariableLock.h>
+
+
+VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
+
+///
+/// Define a memory cache that improves the search performance for a variable.
+///
+VARIABLE_STORE_HEADER *mNvVariableCache = NULL;
+
+///
+/// The memory entry used for variable statistics data.
+///
+VARIABLE_INFO_ENTRY *gVariableInfo = NULL;
+
+//
+// Set to TRUE on SetVar for QUARK_VARIABLE_LOCK_NAME / gQuarkVariableLockGuid.
+//
+BOOLEAN mIsQuarkVariableLockEnabled = FALSE;
+
+/**
+
+ Handle Quark Variable lock conditions on SetVariable.
+
+ @param VariableName Name of Variable been set.
+ @param VendorGuid Variable vendor GUID of variable been set.
+
+ @retval TRUE QuarkVariableLock Condition handled.
+ @retval FALSE No QuarkVariableLock Condition for this variable.
+
+**/
+BOOLEAN
+QuarkVariableLockHandler (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ //
+ // See if Set variable for trigger variable to indicated variables
+ // are locked from now on.
+ //
+ if (CompareGuid (&gQuarkVariableLockGuid, VendorGuid) && (StrCmp (QUARK_VARIABLE_LOCK_NAME, VariableName) == 0)) {
+ mIsQuarkVariableLockEnabled = TRUE;
+ return TRUE;
+ }
+
+ //
+ // If disabled do nothing.
+ //
+ if (!mIsQuarkVariableLockEnabled) {
+ return FALSE;
+ }
+
+ //
+ // Memory Config Data not writiable if Quark Variable Lock Enabled.
+ //
+
+ if (CompareGuid (&gEfiMemoryConfigDataGuid, VendorGuid) && (StrCmp (EFI_MEMORY_CONFIG_DATA_NAME, VariableName) == 0)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Routine used to track statistical information about variable usage.
+ The data is stored in the EFI system table so it can be accessed later.
+ VariableInfo.efi can dump out the table. Only Boot Services variable
+ accesses are tracked by this code. The PcdVariableCollectStatistics
+ build flag controls if this feature is enabled.
+
+ A read that hits in the cache will have Read and Cache true for
+ the transaction. Data is allocated by this routine, but never
+ freed.
+
+ @param[in] VariableName Name of the Variable to track.
+ @param[in] VendorGuid Guid of the Variable to track.
+ @param[in] Volatile TRUE if volatile FALSE if non-volatile.
+ @param[in] Read TRUE if GetVariable() was called.
+ @param[in] Write TRUE if SetVariable() was called.
+ @param[in] Delete TRUE if deleted via SetVariable().
+ @param[in] Cache TRUE for a cache hit.
+
+**/
+VOID
+UpdateVariableInfo (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN BOOLEAN Volatile,
+ IN BOOLEAN Read,
+ IN BOOLEAN Write,
+ IN BOOLEAN Delete,
+ IN BOOLEAN Cache
+ )
+{
+ VARIABLE_INFO_ENTRY *Entry;
+
+ if (FeaturePcdGet (PcdVariableCollectStatistics)) {
+
+ if (AtRuntime ()) {
+ // Don't collect statistics at runtime.
+ return;
+ }
+
+ if (gVariableInfo == NULL) {
+ //
+ // On the first call allocate a entry and place a pointer to it in
+ // the EFI System Table.
+ //
+ gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
+ ASSERT (gVariableInfo != NULL);
+
+ CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);
+ gVariableInfo->Name = AllocatePool (StrSize (VariableName));
+ ASSERT (gVariableInfo->Name != NULL);
+ StrCpy (gVariableInfo->Name, VariableName);
+ gVariableInfo->Volatile = Volatile;
+ }
+
+
+ for (Entry = gVariableInfo; Entry != NULL; Entry = Entry->Next) {
+ if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {
+ if (StrCmp (VariableName, Entry->Name) == 0) {
+ if (Read) {
+ Entry->ReadCount++;
+ }
+ if (Write) {
+ Entry->WriteCount++;
+ }
+ if (Delete) {
+ Entry->DeleteCount++;
+ }
+ if (Cache) {
+ Entry->CacheCount++;
+ }
+
+ return;
+ }
+ }
+
+ if (Entry->Next == NULL) {
+ //
+ // If the entry is not in the table add it.
+ // Next iteration of the loop will fill in the data.
+ //
+ Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
+ ASSERT (Entry->Next != NULL);
+
+ CopyGuid (&Entry->Next->VendorGuid, VendorGuid);
+ Entry->Next->Name = AllocatePool (StrSize (VariableName));
+ ASSERT (Entry->Next->Name != NULL);
+ StrCpy (Entry->Next->Name, VariableName);
+ Entry->Next->Volatile = Volatile;
+ }
+
+ }
+ }
+}
+
+
+/**
+
+ This code checks if variable header is valid or not.
+
+ @param Variable Pointer to the Variable Header.
+
+ @retval TRUE Variable header is valid.
+ @retval FALSE Variable header is not valid.
+
+**/
+BOOLEAN
+IsValidVariableHeader (
+ IN VARIABLE_HEADER *Variable
+ )
+{
+ if (Variable == NULL || Variable->StartId != VARIABLE_DATA) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+
+ This function writes data to the FWH at the correct LBA even if the LBAs
+ are fragmented.
+
+ @param Global Pointer to VARAIBLE_GLOBAL structure.
+ @param Volatile Point out the Variable is Volatile or Non-Volatile.
+ @param SetByIndex TRUE if target pointer is given as index.
+ FALSE if target pointer is absolute.
+ @param Fvb Pointer to the writable FVB protocol.
+ @param DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
+ structure.
+ @param DataSize Size of data to be written.
+ @param Buffer Pointer to the buffer from which data is written.
+
+ @retval EFI_INVALID_PARAMETER Parameters not valid.
+ @retval EFI_SUCCESS Variable store successfully updated.
+
+**/
+EFI_STATUS
+UpdateVariableStore (
+ IN VARIABLE_GLOBAL *Global,
+ IN BOOLEAN Volatile,
+ IN BOOLEAN SetByIndex,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
+ IN UINTN DataPtrIndex,
+ IN UINT32 DataSize,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
+ UINTN BlockIndex2;
+ UINTN LinearOffset;
+ UINTN CurrWriteSize;
+ UINTN CurrWritePtr;
+ UINT8 *CurrBuffer;
+ EFI_LBA LbaNumber;
+ UINTN Size;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ VARIABLE_STORE_HEADER *VolatileBase;
+ EFI_PHYSICAL_ADDRESS FvVolHdr;
+ EFI_PHYSICAL_ADDRESS DataPtr;
+ EFI_STATUS Status;
+
+ FwVolHeader = NULL;
+ DataPtr = DataPtrIndex;
+
+ //
+ // Check if the Data is Volatile.
+ //
+ if (!Volatile) {
+ ASSERT (Fvb != NULL);
+ Status = Fvb->GetPhysicalAddress(Fvb, &FvVolHdr);
+ ASSERT_EFI_ERROR (Status);
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);
+ //
+ // Data Pointer should point to the actual Address where data is to be
+ // written.
+ //
+ if (SetByIndex) {
+ DataPtr += mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
+ }
+
+ if ((DataPtr + DataSize) >= ((EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) FwVolHeader + FwVolHeader->FvLength))) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // Data Pointer should point to the actual Address where data is to be
+ // written.
+ //
+ VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
+ if (SetByIndex) {
+ DataPtr += mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;
+ }
+
+ if ((DataPtr + DataSize) >= ((UINTN) ((UINT8 *) VolatileBase + VolatileBase->Size))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If Volatile Variable just do a simple mem copy.
+ //
+ CopyMem ((UINT8 *)(UINTN)DataPtr, Buffer, DataSize);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If we are here we are dealing with Non-Volatile Variables.
+ //
+ LinearOffset = (UINTN) FwVolHeader;
+ CurrWritePtr = (UINTN) DataPtr;
+ CurrWriteSize = DataSize;
+ CurrBuffer = Buffer;
+ LbaNumber = 0;
+
+ if (CurrWritePtr < LinearOffset) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
+ for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
+ //
+ // Check to see if the Variable Writes are spanning through multiple
+ // blocks.
+ //
+ if ((CurrWritePtr >= LinearOffset) && (CurrWritePtr < LinearOffset + PtrBlockMapEntry->Length)) {
+ if ((CurrWritePtr + CurrWriteSize) <= (LinearOffset + PtrBlockMapEntry->Length)) {
+ Status = Fvb->Write (
+ Fvb,
+ LbaNumber,
+ (UINTN) (CurrWritePtr - LinearOffset),
+ &CurrWriteSize,
+ CurrBuffer
+ );
+ return Status;
+ } else {
+ Size = (UINT32) (LinearOffset + PtrBlockMapEntry->Length - CurrWritePtr);
+ Status = Fvb->Write (
+ Fvb,
+ LbaNumber,
+ (UINTN) (CurrWritePtr - LinearOffset),
+ &Size,
+ CurrBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CurrWritePtr = LinearOffset + PtrBlockMapEntry->Length;
+ CurrBuffer = CurrBuffer + Size;
+ CurrWriteSize = CurrWriteSize - Size;
+ }
+ }
+
+ LinearOffset += PtrBlockMapEntry->Length;
+ LbaNumber++;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ This code gets the current status of Variable Store.
+
+ @param VarStoreHeader Pointer to the Variable Store Header.
+
+ @retval EfiRaw Variable store status is raw.
+ @retval EfiValid Variable store status is valid.
+ @retval EfiInvalid Variable store status is invalid.
+
+**/
+VARIABLE_STORE_STATUS
+GetVariableStoreStatus (
+ IN VARIABLE_STORE_HEADER *VarStoreHeader
+ )
+{
+ if (CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid) &&
+ VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
+ VarStoreHeader->State == VARIABLE_STORE_HEALTHY
+ ) {
+
+ return EfiValid;
+ } else if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&
+ ((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&
+ ((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&
+ ((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&
+ VarStoreHeader->Size == 0xffffffff &&
+ VarStoreHeader->Format == 0xff &&
+ VarStoreHeader->State == 0xff
+ ) {
+
+ return EfiRaw;
+ } else {
+ return EfiInvalid;
+ }
+}
+
+
+/**
+
+ This code gets the size of name of variable.
+
+ @param Variable Pointer to the Variable Header.
+
+ @return UINTN Size of variable in bytes.
+
+**/
+UINTN
+NameSizeOfVariable (
+ IN VARIABLE_HEADER *Variable
+ )
+{
+ if (Variable->State == (UINT8) (-1) ||
+ Variable->DataSize == (UINT32) (-1) ||
+ Variable->NameSize == (UINT32) (-1) ||
+ Variable->Attributes == (UINT32) (-1)) {
+ return 0;
+ }
+ return (UINTN) Variable->NameSize;
+}
+
+/**
+
+ This code gets the size of variable data.
+
+ @param Variable Pointer to the Variable Header.
+
+ @return Size of variable in bytes.
+
+**/
+UINTN
+DataSizeOfVariable (
+ IN VARIABLE_HEADER *Variable
+ )
+{
+ if (Variable->State == (UINT8) (-1) ||
+ Variable->DataSize == (UINT32) (-1) ||
+ Variable->NameSize == (UINT32) (-1) ||
+ Variable->Attributes == (UINT32) (-1)) {
+ return 0;
+ }
+ return (UINTN) Variable->DataSize;
+}
+
+/**
+
+ This code gets the pointer to the variable name.
+
+ @param Variable Pointer to the Variable Header.
+
+ @return Pointer to Variable Name which is Unicode encoding.
+
+**/
+CHAR16 *
+GetVariableNamePtr (
+ IN VARIABLE_HEADER *Variable
+ )
+{
+
+ return (CHAR16 *) (Variable + 1);
+}
+
+/**
+
+ This code gets the pointer to the variable data.
+
+ @param Variable Pointer to the Variable Header.
+
+ @return Pointer to Variable Data.
+
+**/
+UINT8 *
+GetVariableDataPtr (
+ IN VARIABLE_HEADER *Variable
+ )
+{
+ UINTN Value;
+
+ //
+ // Be careful about pad size for alignment.
+ //
+ Value = (UINTN) GetVariableNamePtr (Variable);
+ Value += NameSizeOfVariable (Variable);
+ Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
+
+ return (UINT8 *) Value;
+}
+
+
+/**
+
+ This code gets the pointer to the next variable header.
+
+ @param Variable Pointer to the Variable Header.
+
+ @return Pointer to next variable header.
+
+**/
+VARIABLE_HEADER *
+GetNextVariablePtr (
+ IN VARIABLE_HEADER *Variable
+ )
+{
+ UINTN Value;
+
+ if (!IsValidVariableHeader (Variable)) {
+ return NULL;
+ }
+
+ Value = (UINTN) GetVariableDataPtr (Variable);
+ Value += DataSizeOfVariable (Variable);
+ Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
+
+ //
+ // Be careful about pad size for alignment.
+ //
+ return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
+}
+
+/**
+
+ Gets the pointer to the first variable header in given variable store area.
+
+ @param VarStoreHeader Pointer to the Variable Store Header.
+
+ @return Pointer to the first variable header.
+
+**/
+VARIABLE_HEADER *
+GetStartPointer (
+ IN VARIABLE_STORE_HEADER *VarStoreHeader
+ )
+{
+ //
+ // The end of variable store.
+ //
+ return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
+}
+
+/**
+
+ Gets the pointer to the end of the variable storage area.
+
+ This function gets pointer to the end of the variable storage
+ area, according to the input variable store header.
+
+ @param VarStoreHeader Pointer to the Variable Store Header.
+
+ @return Pointer to the end of the variable storage area.
+
+**/
+VARIABLE_HEADER *
+GetEndPointer (
+ IN VARIABLE_STORE_HEADER *VarStoreHeader
+ )
+{
+ //
+ // The end of variable store
+ //
+ return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
+}
+
+
+/**
+
+ Variable store garbage collection and reclaim operation.
+
+ @param VariableBase Base address of variable store.
+ @param LastVariableOffset Offset of last variable.
+ @param IsVolatile The variable store is volatile or not;
+ if it is non-volatile, need FTW.
+ @param UpdatingVariable Pointer to updating variable.
+
+ @return EFI_OUT_OF_RESOURCES
+ @return EFI_SUCCESS
+ @return Others
+
+**/
+EFI_STATUS
+Reclaim (
+ IN EFI_PHYSICAL_ADDRESS VariableBase,
+ OUT UINTN *LastVariableOffset,
+ IN BOOLEAN IsVolatile,
+ IN VARIABLE_HEADER *UpdatingVariable
+ )
+{
+ VARIABLE_HEADER *Variable;
+ VARIABLE_HEADER *AddedVariable;
+ VARIABLE_HEADER *NextVariable;
+ VARIABLE_HEADER *NextAddedVariable;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINT8 *ValidBuffer;
+ UINTN MaximumBufferSize;
+ UINTN VariableSize;
+ UINTN VariableNameSize;
+ UINTN UpdatingVariableNameSize;
+ UINTN NameSize;
+ UINT8 *CurrPtr;
+ VOID *Point0;
+ VOID *Point1;
+ BOOLEAN FoundAdded;
+ EFI_STATUS Status;
+ CHAR16 *VariableNamePtr;
+ CHAR16 *UpdatingVariableNamePtr;
+ UINTN CommonVariableTotalSize;
+ UINTN HwErrVariableTotalSize;
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
+
+ CommonVariableTotalSize = 0;
+ HwErrVariableTotalSize = 0;
+
+ //
+ // Start Pointers for the variable.
+ //
+ Variable = GetStartPointer (VariableStoreHeader);
+ MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);
+
+ while (IsValidVariableHeader (Variable)) {
+ NextVariable = GetNextVariablePtr (Variable);
+ if (Variable->State == VAR_ADDED ||
+ Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
+ ) {
+ VariableSize = (UINTN) NextVariable - (UINTN) Variable;
+ MaximumBufferSize += VariableSize;
+ }
+
+ Variable = NextVariable;
+ }
+
+ //
+ // Reserve the 1 Bytes with Oxff to identify the
+ // end of the variable buffer.
+ //
+ MaximumBufferSize += 1;
+ ValidBuffer = AllocatePool (MaximumBufferSize);
+ if (ValidBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetMem (ValidBuffer, MaximumBufferSize, 0xff);
+
+ //
+ // Copy variable store header.
+ //
+ CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));
+ CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
+
+ //
+ // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
+ //
+ Variable = GetStartPointer (VariableStoreHeader);
+ while (IsValidVariableHeader (Variable)) {
+ NextVariable = GetNextVariablePtr (Variable);
+ if (Variable->State == VAR_ADDED) {
+ if (UpdatingVariable != NULL) {
+ if (UpdatingVariable == Variable) {
+ Variable = NextVariable;
+ continue;
+ }
+
+ VariableNameSize = NameSizeOfVariable(Variable);
+ UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);
+
+ VariableNamePtr = GetVariableNamePtr (Variable);
+ UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable);
+ if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid) &&
+ VariableNameSize == UpdatingVariableNameSize &&
+ CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) {
+ Variable = NextVariable;
+ continue;
+ }
+ }
+ VariableSize = (UINTN) NextVariable - (UINTN) Variable;
+ CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
+ CurrPtr += VariableSize;
+ if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ HwErrVariableTotalSize += VariableSize;
+ } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ CommonVariableTotalSize += VariableSize;
+ }
+ }
+ Variable = NextVariable;
+ }
+
+ //
+ // Reinstall the variable being updated if it is not NULL.
+ //
+ if (UpdatingVariable != NULL) {
+ VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
+ CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);
+ CurrPtr += VariableSize;
+ if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ HwErrVariableTotalSize += VariableSize;
+ } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ CommonVariableTotalSize += VariableSize;
+ }
+ }
+
+ //
+ // Reinstall all in delete transition variables.
+ //
+ Variable = GetStartPointer (VariableStoreHeader);
+ while (IsValidVariableHeader (Variable)) {
+ NextVariable = GetNextVariablePtr (Variable);
+ if (Variable != UpdatingVariable && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+
+ //
+ // Buffer has cached all ADDED variable.
+ // Per IN_DELETED variable, we have to guarantee that
+ // no ADDED one in previous buffer.
+ //
+
+ FoundAdded = FALSE;
+ AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
+ while (IsValidVariableHeader (AddedVariable)) {
+ NextAddedVariable = GetNextVariablePtr (AddedVariable);
+ NameSize = NameSizeOfVariable (AddedVariable);
+ if (CompareGuid (&AddedVariable->VendorGuid, &Variable->VendorGuid) &&
+ NameSize == NameSizeOfVariable (Variable)
+ ) {
+ Point0 = (VOID *) GetVariableNamePtr (AddedVariable);
+ Point1 = (VOID *) GetVariableNamePtr (Variable);
+ if (CompareMem (Point0, Point1, NameSizeOfVariable (AddedVariable)) == 0) {
+ FoundAdded = TRUE;
+ break;
+ }
+ }
+ AddedVariable = NextAddedVariable;
+ }
+ if (!FoundAdded) {
+ //
+ // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
+ //
+ VariableSize = (UINTN) NextVariable - (UINTN) Variable;
+ CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
+ ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
+ CurrPtr += VariableSize;
+ if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ HwErrVariableTotalSize += VariableSize;
+ } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ CommonVariableTotalSize += VariableSize;
+ }
+ }
+ }
+
+ Variable = NextVariable;
+ }
+
+ if (IsVolatile) {
+ //
+ // If volatile variable store, just copy valid buffer.
+ //
+ SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);
+ CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // If non-volatile variable store, perform FTW here.
+ //
+ Status = FtwVariableSpace (
+ VariableBase,
+ ValidBuffer,
+ (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)
+ );
+ CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);
+ }
+ if (!EFI_ERROR (Status)) {
+ *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);
+ if (!IsVolatile) {
+ mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;
+ mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;
+ }
+ } else {
+ NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);
+ while (IsValidVariableHeader (NextVariable)) {
+ VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
+ if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
+ } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
+ }
+
+ NextVariable = GetNextVariablePtr (NextVariable);
+ }
+ *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;
+ }
+
+ FreePool (ValidBuffer);
+
+ return Status;
+}
+
+/**
+ Find the variable in the specified variable store.
+
+ @param VariableName Name of the variable to be found
+ @param VendorGuid Vendor GUID to be found.
+ @param IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
+ check at runtime when searching variable.
+ @param PtrTrack Variable Track Pointer structure that contains Variable Information.
+
+ @retval EFI_SUCCESS Variable found successfully
+ @retval EFI_NOT_FOUND Variable not found
+**/
+EFI_STATUS
+FindVariableEx (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN BOOLEAN IgnoreRtCheck,
+ IN OUT VARIABLE_POINTER_TRACK *PtrTrack
+ )
+{
+ VARIABLE_HEADER *InDeletedVariable;
+ VOID *Point;
+
+ //
+ // Find the variable by walk through HOB, volatile and non-volatile variable store.
+ //
+ InDeletedVariable = NULL;
+
+ for ( PtrTrack->CurrPtr = PtrTrack->StartPtr
+ ; (PtrTrack->CurrPtr < PtrTrack->EndPtr) && IsValidVariableHeader (PtrTrack->CurrPtr)
+ ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr)
+ ) {
+ if (PtrTrack->CurrPtr->State == VAR_ADDED ||
+ PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
+ ) {
+ if (IgnoreRtCheck || !AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
+ if (VariableName[0] == 0) {
+ if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ InDeletedVariable = PtrTrack->CurrPtr;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ if (CompareGuid (VendorGuid, &PtrTrack->CurrPtr->VendorGuid)) {
+ Point = (VOID *) GetVariableNamePtr (PtrTrack->CurrPtr);
+
+ ASSERT (NameSizeOfVariable (PtrTrack->CurrPtr) != 0);
+ if (CompareMem (VariableName, Point, NameSizeOfVariable (PtrTrack->CurrPtr)) == 0) {
+ if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ InDeletedVariable = PtrTrack->CurrPtr;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ PtrTrack->CurrPtr = InDeletedVariable;
+ return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
+}
+
+
+/**
+ Finds variable in storage blocks of volatile and non-volatile storage areas.
+
+ This code finds variable in storage blocks of volatile and non-volatile storage areas.
+ If VariableName is an empty string, then we just return the first
+ qualified variable without comparing VariableName and VendorGuid.
+ If IgnoreRtCheck is TRUE, then we ignore the EFI_VARIABLE_RUNTIME_ACCESS attribute check
+ at runtime when searching existing variable, only VariableName and VendorGuid are compared.
+ Otherwise, variables without EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime.
+
+ @param VariableName Name of the variable to be found.
+ @param VendorGuid Vendor GUID to be found.
+ @param PtrTrack VARIABLE_POINTER_TRACK structure for output,
+ including the range searched and the target position.
+ @param Global Pointer to VARIABLE_GLOBAL structure, including
+ base of volatile variable storage area, base of
+ NV variable storage area, and a lock.
+ @param IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
+ check at runtime when searching variable.
+
+ @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
+ VendorGuid is NULL.
+ @retval EFI_SUCCESS Variable successfully found.
+ @retval EFI_NOT_FOUND Variable not found
+
+**/
+EFI_STATUS
+FindVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ OUT VARIABLE_POINTER_TRACK *PtrTrack,
+ IN VARIABLE_GLOBAL *Global,
+ IN BOOLEAN IgnoreRtCheck
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
+ VARIABLE_STORE_TYPE Type;
+
+ if (VariableName[0] != 0 && VendorGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // 0: Volatile, 1: HOB, 2: Non-Volatile.
+ // The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
+ // make use of this mapping to implement search algorithm.
+ //
+ VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) Global->VolatileVariableBase;
+ VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *) (UINTN) Global->HobVariableBase;
+ VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache;
+
+ //
+ // Find the variable by walk through HOB, volatile and non-volatile variable store.
+ //
+ for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
+ if (VariableStoreHeader[Type] == NULL) {
+ continue;
+ }
+
+ PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Type]);
+ PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Type]);
+ PtrTrack->Volatile = (BOOLEAN) (Type == VariableStoreTypeVolatile);
+
+ Status = FindVariableEx (VariableName, VendorGuid, IgnoreRtCheck, PtrTrack);
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Get index from supported language codes according to language string.
+
+ This code is used to get corresponding index in supported language codes. It can handle
+ RFC4646 and ISO639 language tags.
+ In ISO639 language tags, take 3-characters as a delimitation to find matched string and calculate the index.
+ In RFC4646 language tags, take semicolon as a delimitation to find matched string and calculate the index.
+
+ For example:
+ SupportedLang = "engfraengfra"
+ Lang = "eng"
+ Iso639Language = TRUE
+ The return value is "0".
+ Another example:
+ SupportedLang = "en;fr;en-US;fr-FR"
+ Lang = "fr-FR"
+ Iso639Language = FALSE
+ The return value is "3".
+
+ @param SupportedLang Platform supported language codes.
+ @param Lang Configured language.
+ @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.
+
+ @retval The index of language in the language codes.
+
+**/
+UINTN
+GetIndexFromSupportedLangCodes(
+ IN CHAR8 *SupportedLang,
+ IN CHAR8 *Lang,
+ IN BOOLEAN Iso639Language
+ )
+{
+ UINTN Index;
+ UINTN CompareLength;
+ UINTN LanguageLength;
+
+ if (Iso639Language) {
+ CompareLength = ISO_639_2_ENTRY_SIZE;
+ for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {
+ if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {
+ //
+ // Successfully find the index of Lang string in SupportedLang string.
+ //
+ Index = Index / CompareLength;
+ return Index;
+ }
+ }
+ ASSERT (FALSE);
+ return 0;
+ } else {
+ //
+ // Compare RFC4646 language code
+ //
+ Index = 0;
+ for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++);
+
+ for (Index = 0; *SupportedLang != '\0'; Index++, SupportedLang += CompareLength) {
+ //
+ // Skip ';' characters in SupportedLang
+ //
+ for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++);
+ //
+ // Determine the length of the next language code in SupportedLang
+ //
+ for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++);
+
+ if ((CompareLength == LanguageLength) &&
+ (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) {
+ //
+ // Successfully find the index of Lang string in SupportedLang string.
+ //
+ return Index;
+ }
+ }
+ ASSERT (FALSE);
+ return 0;
+ }
+}
+
+/**
+ Get language string from supported language codes according to index.
+
+ This code is used to get corresponding language strings in supported language codes. It can handle
+ RFC4646 and ISO639 language tags.
+ In ISO639 language tags, take 3-characters as a delimitation. Find language string according to the index.
+ In RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.
+
+ For example:
+ SupportedLang = "engfraengfra"
+ Index = "1"
+ Iso639Language = TRUE
+ The return value is "fra".
+ Another example:
+ SupportedLang = "en;fr;en-US;fr-FR"
+ Index = "1"
+ Iso639Language = FALSE
+ The return value is "fr".
+
+ @param SupportedLang Platform supported language codes.
+ @param Index The index in supported language codes.
+ @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.
+
+ @retval The language string in the language codes.
+
+**/
+CHAR8 *
+GetLangFromSupportedLangCodes (
+ IN CHAR8 *SupportedLang,
+ IN UINTN Index,
+ IN BOOLEAN Iso639Language
+)
+{
+ UINTN SubIndex;
+ UINTN CompareLength;
+ CHAR8 *Supported;
+
+ SubIndex = 0;
+ Supported = SupportedLang;
+ if (Iso639Language) {
+ //
+ // According to the index of Lang string in SupportedLang string to get the language.
+ // This code will be invoked in RUNTIME, therefore there is not a memory allocate/free operation.
+ // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
+ //
+ CompareLength = ISO_639_2_ENTRY_SIZE;
+ mVariableModuleGlobal->Lang[CompareLength] = '\0';
+ return CopyMem (mVariableModuleGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);
+
+ } else {
+ while (TRUE) {
+ //
+ // Take semicolon as delimitation, sequentially traverse supported language codes.
+ //
+ for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {
+ Supported++;
+ }
+ if ((*Supported == '\0') && (SubIndex != Index)) {
+ //
+ // Have completed the traverse, but not find corrsponding string.
+ // This case is not allowed to happen.
+ //
+ ASSERT(FALSE);
+ return NULL;
+ }
+ if (SubIndex == Index) {
+ //
+ // According to the index of Lang string in SupportedLang string to get the language.
+ // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
+ // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
+ //
+ mVariableModuleGlobal->PlatformLang[CompareLength] = '\0';
+ return CopyMem (mVariableModuleGlobal->PlatformLang, Supported - CompareLength, CompareLength);
+ }
+ SubIndex++;
+
+ //
+ // Skip ';' characters in Supported
+ //
+ for (; *Supported != '\0' && *Supported == ';'; Supported++);
+ }
+ }
+}
+
+/**
+ Returns a pointer to an allocated buffer that contains the best matching language
+ from a set of supported languages.
+
+ This function supports both ISO 639-2 and RFC 4646 language codes, but language
+ code types may not be mixed in a single call to this function. This function
+ supports a variable argument list that allows the caller to pass in a prioritized
+ list of language codes to test against all the language codes in SupportedLanguages.
+
+ If SupportedLanguages is NULL, then ASSERT().
+
+ @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that
+ contains a set of language codes in the format
+ specified by Iso639Language.
+ @param[in] Iso639Language If TRUE, then all language codes are assumed to be
+ in ISO 639-2 format. If FALSE, then all language
+ codes are assumed to be in RFC 4646 language format
+ @param[in] ... A variable argument list that contains pointers to
+ Null-terminated ASCII strings that contain one or more
+ language codes in the format specified by Iso639Language.
+ The first language code from each of these language
+ code lists is used to determine if it is an exact or
+ close match to any of the language codes in
+ SupportedLanguages. Close matches only apply to RFC 4646
+ language codes, and the matching algorithm from RFC 4647
+ is used to determine if a close match is present. If
+ an exact or close match is found, then the matching
+ language code from SupportedLanguages is returned. If
+ no matches are found, then the next variable argument
+ parameter is evaluated. The variable argument list
+ is terminated by a NULL.
+
+ @retval NULL The best matching language could not be found in SupportedLanguages.
+ @retval NULL There are not enough resources available to return the best matching
+ language.
+ @retval Other A pointer to a Null-terminated ASCII string that is the best matching
+ language in SupportedLanguages.
+
+**/
+CHAR8 *
+EFIAPI
+VariableGetBestLanguage (
+ IN CONST CHAR8 *SupportedLanguages,
+ IN BOOLEAN Iso639Language,
+ ...
+ )
+{
+ VA_LIST Args;
+ CHAR8 *Language;
+ UINTN CompareLength;
+ UINTN LanguageLength;
+ CONST CHAR8 *Supported;
+ CHAR8 *Buffer;
+
+ ASSERT (SupportedLanguages != NULL);
+
+ VA_START (Args, Iso639Language);
+ while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {
+ //
+ // Default to ISO 639-2 mode
+ //
+ CompareLength = 3;
+ LanguageLength = MIN (3, AsciiStrLen (Language));
+
+ //
+ // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language
+ //
+ if (!Iso639Language) {
+ for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);
+ }
+
+ //
+ // Trim back the length of Language used until it is empty
+ //
+ while (LanguageLength > 0) {
+ //
+ // Loop through all language codes in SupportedLanguages
+ //
+ for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
+ //
+ // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages
+ //
+ if (!Iso639Language) {
+ //
+ // Skip ';' characters in Supported
+ //
+ for (; *Supported != '\0' && *Supported == ';'; Supported++);
+ //
+ // Determine the length of the next language code in Supported
+ //
+ for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);
+ //
+ // If Language is longer than the Supported, then skip to the next language
+ //
+ if (LanguageLength > CompareLength) {
+ continue;
+ }
+ }
+ //
+ // See if the first LanguageLength characters in Supported match Language
+ //
+ if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {
+ VA_END (Args);
+
+ Buffer = Iso639Language ? mVariableModuleGlobal->Lang : mVariableModuleGlobal->PlatformLang;
+ Buffer[CompareLength] = '\0';
+ return CopyMem (Buffer, Supported, CompareLength);
+ }
+ }
+
+ if (Iso639Language) {
+ //
+ // If ISO 639 mode, then each language can only be tested once
+ //
+ LanguageLength = 0;
+ } else {
+ //
+ // If RFC 4646 mode, then trim Language from the right to the next '-' character
+ //
+ for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);
+ }
+ }
+ }
+ VA_END (Args);
+
+ //
+ // No matches were found
+ //
+ return NULL;
+}
+
+/**
+ Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.
+
+ When setting Lang/LangCodes, simultaneously update PlatformLang/PlatformLangCodes.
+
+ According to UEFI spec, PlatformLangCodes/LangCodes are only set once in firmware initialization,
+ and are read-only. Therefore, in variable driver, only store the original value for other use.
+
+ @param[in] VariableName Name of variable.
+
+ @param[in] Data Variable data.
+
+ @param[in] DataSize Size of data. 0 means delete.
+
+**/
+VOID
+AutoUpdateLangVariable (
+ IN CHAR16 *VariableName,
+ IN VOID *Data,
+ IN UINTN DataSize
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *BestPlatformLang;
+ CHAR8 *BestLang;
+ UINTN Index;
+ UINT32 Attributes;
+ VARIABLE_POINTER_TRACK Variable;
+ BOOLEAN SetLanguageCodes;
+
+ //
+ // Don't do updates for delete operation
+ //
+ if (DataSize == 0) {
+ return;
+ }
+
+ SetLanguageCodes = FALSE;
+
+ if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {
+ //
+ // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
+ //
+ if (AtRuntime ()) {
+ return;
+ }
+
+ SetLanguageCodes = TRUE;
+
+ //
+ // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only
+ // Therefore, in variable driver, only store the original value for other use.
+ //
+ if (mVariableModuleGlobal->PlatformLangCodes != NULL) {
+ FreePool (mVariableModuleGlobal->PlatformLangCodes);
+ }
+ mVariableModuleGlobal->PlatformLangCodes = AllocateRuntimeCopyPool (DataSize, Data);
+ ASSERT (mVariableModuleGlobal->PlatformLangCodes != NULL);
+
+ //
+ // PlatformLang holds a single language from PlatformLangCodes,
+ // so the size of PlatformLangCodes is enough for the PlatformLang.
+ //
+ if (mVariableModuleGlobal->PlatformLang != NULL) {
+ FreePool (mVariableModuleGlobal->PlatformLang);
+ }
+ mVariableModuleGlobal->PlatformLang = AllocateRuntimePool (DataSize);
+ ASSERT (mVariableModuleGlobal->PlatformLang != NULL);
+
+ } else if (StrCmp (VariableName, L"LangCodes") == 0) {
+ //
+ // LangCodes is a volatile variable, so it can not be updated at runtime.
+ //
+ if (AtRuntime ()) {
+ return;
+ }
+
+ SetLanguageCodes = TRUE;
+
+ //
+ // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only
+ // Therefore, in variable driver, only store the original value for other use.
+ //
+ if (mVariableModuleGlobal->LangCodes != NULL) {
+ FreePool (mVariableModuleGlobal->LangCodes);
+ }
+ mVariableModuleGlobal->LangCodes = AllocateRuntimeCopyPool (DataSize, Data);
+ ASSERT (mVariableModuleGlobal->LangCodes != NULL);
+ }
+
+ if (SetLanguageCodes
+ && (mVariableModuleGlobal->PlatformLangCodes != NULL)
+ && (mVariableModuleGlobal->LangCodes != NULL)) {
+ //
+ // Update Lang if PlatformLang is already set
+ // Update PlatformLang if Lang is already set
+ //
+ Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update Lang
+ //
+ VariableName = L"PlatformLang";
+ Data = GetVariableDataPtr (Variable.CurrPtr);
+ DataSize = Variable.CurrPtr->DataSize;
+ } else {
+ Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update PlatformLang
+ //
+ VariableName = L"Lang";
+ Data = GetVariableDataPtr (Variable.CurrPtr);
+ DataSize = Variable.CurrPtr->DataSize;
+ } else {
+ //
+ // Neither PlatformLang nor Lang is set, directly return
+ //
+ return;
+ }
+ }
+ }
+
+ //
+ // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.
+ //
+ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
+
+ if (StrCmp (VariableName, L"PlatformLang") == 0) {
+ //
+ // Update Lang when PlatformLangCodes/LangCodes were set.
+ //
+ if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {
+ //
+ // When setting PlatformLang, firstly get most matched language string from supported language codes.
+ //
+ BestPlatformLang = VariableGetBestLanguage (mVariableModuleGlobal->PlatformLangCodes, FALSE, Data, NULL);
+ if (BestPlatformLang != NULL) {
+ //
+ // Get the corresponding index in language codes.
+ //
+ Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);
+
+ //
+ // Get the corresponding ISO639 language tag according to RFC4646 language tag.
+ //
+ BestLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, Index, TRUE);
+
+ //
+ // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
+ //
+ FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal, FALSE);
+
+ Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,
+ ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
+
+ DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));
+
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+
+ } else if (StrCmp (VariableName, L"Lang") == 0) {
+ //
+ // Update PlatformLang when PlatformLangCodes/LangCodes were set.
+ //
+ if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {
+ //
+ // When setting Lang, firstly get most matched language string from supported language codes.
+ //
+ BestLang = VariableGetBestLanguage (mVariableModuleGlobal->LangCodes, TRUE, Data, NULL);
+ if (BestLang != NULL) {
+ //
+ // Get the corresponding index in language codes.
+ //
+ Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, BestLang, TRUE);
+
+ //
+ // Get the corresponding RFC4646 language tag according to ISO639 language tag.
+ //
+ BestPlatformLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);
+
+ //
+ // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
+ //
+ FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+
+ Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang,
+ AsciiStrSize (BestPlatformLang), Attributes, &Variable);
+
+ DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ }
+}
+
+/**
+ Update the variable region with Variable information. These are the same
+ arguments as the EFI Variable services.
+
+ @param[in] VariableName Name of variable.
+ @param[in] VendorGuid Guid of variable.
+ @param[in] Data Variable data.
+ @param[in] DataSize Size of data. 0 means delete.
+ @param[in] Attributes Attribues of the variable.
+ @param[in] CacheVariable The variable information which is used to keep track of variable usage.
+
+ @retval EFI_SUCCESS The update operation is success.
+ @retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.
+
+**/
+EFI_STATUS
+UpdateVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT32 Attributes OPTIONAL,
+ IN VARIABLE_POINTER_TRACK *CacheVariable
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_HEADER *NextVariable;
+ UINTN ScratchSize;
+ UINTN NonVolatileVarableStoreSize;
+ UINTN VarNameOffset;
+ UINTN VarDataOffset;
+ UINTN VarNameSize;
+ UINTN VarSize;
+ BOOLEAN Volatile;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ UINT8 State;
+ BOOLEAN Reclaimed;
+ VARIABLE_POINTER_TRACK *Variable;
+ VARIABLE_POINTER_TRACK NvVariable;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN CacheOffset;
+
+ if ((mVariableModuleGlobal->FvbInstance == NULL) && ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) {
+ //
+ // The FVB protocol is not ready. Trying to update NV variable prior to the installation
+ // of EFI_VARIABLE_WRITE_ARCH_PROTOCOL.
+ //
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ if ((CacheVariable->CurrPtr == NULL) || CacheVariable->Volatile) {
+ Variable = CacheVariable;
+ } else {
+ //
+ // Update/Delete existing NV variable.
+ // CacheVariable points to the variable in the memory copy of Flash area
+ // Now let Variable points to the same variable in Flash area.
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
+ Variable = &NvVariable;
+ Variable->StartPtr = GetStartPointer (VariableStoreHeader);
+ Variable->EndPtr = GetEndPointer (VariableStoreHeader);
+ Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));
+ Variable->Volatile = FALSE;
+ }
+
+ Fvb = mVariableModuleGlobal->FvbInstance;
+ Reclaimed = FALSE;
+
+ if (Variable->CurrPtr != NULL) {
+ //
+ // Update/Delete existing variable.
+ //
+ if (AtRuntime ()) {
+ //
+ // If AtRuntime and the variable is Volatile and Runtime Access,
+ // the volatile is ReadOnly, and SetVariable should be aborted and
+ // return EFI_WRITE_PROTECTED.
+ //
+ if (Variable->Volatile) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Done;
+ }
+ //
+ // Only variable that have NV|RT attributes can be updated/deleted in Runtime.
+ //
+ if (((Variable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ //
+ // Setting a data variable with no access, or zero DataSize attributes
+ // causes it to be deleted.
+ //
+ if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
+ State = Variable->CurrPtr->State;
+ State &= VAR_DELETED;
+
+ Status = UpdateVariableStore (
+ &mVariableModuleGlobal->VariableGlobal,
+ Variable->Volatile,
+ FALSE,
+ Fvb,
+ (UINTN) &Variable->CurrPtr->State,
+ sizeof (UINT8),
+ &State
+ );
+ if (!EFI_ERROR (Status)) {
+ UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
+ if (!Variable->Volatile) {
+ CacheVariable->CurrPtr->State = State;
+ }
+ }
+ goto Done;
+ }
+ //
+ // If the variable is marked valid, and the same data has been passed in,
+ // then return to the caller immediately.
+ //
+ if (DataSizeOfVariable (Variable->CurrPtr) == DataSize &&
+ (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0)) {
+
+ UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
+ Status = EFI_SUCCESS;
+ goto Done;
+ } else if ((Variable->CurrPtr->State == VAR_ADDED) ||
+ (Variable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {
+
+ //
+ // Mark the old variable as in delete transition.
+ //
+ State = Variable->CurrPtr->State;
+ State &= VAR_IN_DELETED_TRANSITION;
+
+ Status = UpdateVariableStore (
+ &mVariableModuleGlobal->VariableGlobal,
+ Variable->Volatile,
+ FALSE,
+ Fvb,
+ (UINTN) &Variable->CurrPtr->State,
+ sizeof (UINT8),
+ &State
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ if (!Variable->Volatile) {
+ CacheVariable->CurrPtr->State = State;
+ }
+ }
+ } else {
+ //
+ // Not found existing variable. Create a new variable.
+ //
+
+ //
+ // Make sure we are trying to create a new variable.
+ // Setting a data variable with zero DataSize or no access attributes means to delete it.
+ //
+ if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Only variable have NV|RT attribute can be created in Runtime.
+ //
+ if (AtRuntime () &&
+ (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0))) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ //
+ // Function part - create a new variable and copy the data.
+ // Both update a variable and create a variable will come here.
+
+ //
+ // Tricky part: Use scratch data area at the end of volatile variable store
+ // as a temporary storage.
+ //
+ NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));
+ ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
+
+ SetMem (NextVariable, ScratchSize, 0xff);
+
+ NextVariable->StartId = VARIABLE_DATA;
+ NextVariable->Attributes = Attributes;
+ //
+ // NextVariable->State = VAR_ADDED;
+ //
+ NextVariable->Reserved = 0;
+ VarNameOffset = sizeof (VARIABLE_HEADER);
+ VarNameSize = StrSize (VariableName);
+ CopyMem (
+ (UINT8 *) ((UINTN) NextVariable + VarNameOffset),
+ VariableName,
+ VarNameSize
+ );
+ VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
+ CopyMem (
+ (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
+ Data,
+ DataSize
+ );
+ CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));
+ //
+ // There will be pad bytes after Data, the NextVariable->NameSize and
+ // NextVariable->DataSize should not include pad size so that variable
+ // service can get actual size in GetVariable.
+ //
+ NextVariable->NameSize = (UINT32)VarNameSize;
+ NextVariable->DataSize = (UINT32)DataSize;
+
+ //
+ // The actual size of the variable that stores in storage should
+ // include pad size.
+ //
+ VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
+ //
+ // Create a nonvolatile variable.
+ //
+ Volatile = FALSE;
+ NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase))->Size;
+ if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
+ && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
+ || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0)
+ && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {
+ if (AtRuntime ()) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ //
+ // Perform garbage collection & reclaim operation.
+ //
+ Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // If still no enough space, return out of resources.
+ //
+ if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
+ && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
+ || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0)
+ && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ Reclaimed = TRUE;
+ }
+ //
+ // Four steps
+ // 1. Write variable header
+ // 2. Set variable state to header valid
+ // 3. Write variable data
+ // 4. Set variable state to valid
+ //
+ //
+ // Step 1:
+ //
+ CacheOffset = mVariableModuleGlobal->NonVolatileLastVariableOffset;
+ Status = UpdateVariableStore (
+ &mVariableModuleGlobal->VariableGlobal,
+ FALSE,
+ TRUE,
+ Fvb,
+ mVariableModuleGlobal->NonVolatileLastVariableOffset,
+ sizeof (VARIABLE_HEADER),
+ (UINT8 *) NextVariable
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Step 2:
+ //
+ NextVariable->State = VAR_HEADER_VALID_ONLY;
+ Status = UpdateVariableStore (
+ &mVariableModuleGlobal->VariableGlobal,
+ FALSE,
+ TRUE,
+ Fvb,
+ mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF (VARIABLE_HEADER, State),
+ sizeof (UINT8),
+ &NextVariable->State
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Step 3:
+ //
+ Status = UpdateVariableStore (
+ &mVariableModuleGlobal->VariableGlobal,
+ FALSE,
+ TRUE,
+ Fvb,
+ mVariableModuleGlobal->NonVolatileLastVariableOffset + sizeof (VARIABLE_HEADER),
+ (UINT32) VarSize - sizeof (VARIABLE_HEADER),
+ (UINT8 *) NextVariable + sizeof (VARIABLE_HEADER)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Step 4:
+ //
+ NextVariable->State = VAR_ADDED;
+ Status = UpdateVariableStore (
+ &mVariableModuleGlobal->VariableGlobal,
+ FALSE,
+ TRUE,
+ Fvb,
+ mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF (VARIABLE_HEADER, State),
+ sizeof (UINT8),
+ &NextVariable->State
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ mVariableModuleGlobal->NonVolatileLastVariableOffset += HEADER_ALIGN (VarSize);
+
+ if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VarSize);
+ } else {
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VarSize);
+ }
+ //
+ // update the memory copy of Flash region.
+ //
+ CopyMem ((UINT8 *)mNvVariableCache + CacheOffset, (UINT8 *)NextVariable, VarSize);
+ } else {
+ //
+ // Create a volatile variable.
+ //
+ Volatile = TRUE;
+
+ if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >
+ ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) {
+ //
+ // Perform garbage collection & reclaim operation.
+ //
+ Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
+ &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // If still no enough space, return out of resources.
+ //
+ if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >
+ ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size
+ ) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ Reclaimed = TRUE;
+ }
+
+ NextVariable->State = VAR_ADDED;
+ Status = UpdateVariableStore (
+ &mVariableModuleGlobal->VariableGlobal,
+ TRUE,
+ TRUE,
+ Fvb,
+ mVariableModuleGlobal->VolatileLastVariableOffset,
+ (UINT32) VarSize,
+ (UINT8 *) NextVariable
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ mVariableModuleGlobal->VolatileLastVariableOffset += HEADER_ALIGN (VarSize);
+ }
+
+ //
+ // Mark the old variable as deleted.
+ //
+ if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) {
+ State = Variable->CurrPtr->State;
+ State &= VAR_DELETED;
+
+ Status = UpdateVariableStore (
+ &mVariableModuleGlobal->VariableGlobal,
+ Variable->Volatile,
+ FALSE,
+ Fvb,
+ (UINTN) &Variable->CurrPtr->State,
+ sizeof (UINT8),
+ &State
+ );
+ if (!EFI_ERROR (Status) && !Variable->Volatile) {
+ CacheVariable->CurrPtr->State = State;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);
+ }
+
+Done:
+ return Status;
+}
+
+/**
+ Check if a Unicode character is a hexadecimal character.
+
+ This function checks if a Unicode character is a
+ hexadecimal character. The valid hexadecimal character is
+ L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
+
+
+ @param Char The character to check against.
+
+ @retval TRUE If the Char is a hexadecmial character.
+ @retval FALSE If the Char is not a hexadecmial character.
+
+**/
+BOOLEAN
+EFIAPI
+IsHexaDecimalDigitCharacter (
+ IN CHAR16 Char
+ )
+{
+ return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));
+}
+
+/**
+
+ This code checks if variable is hardware error record variable or not.
+
+ According to UEFI spec, hardware error record variable should use the EFI_HARDWARE_ERROR_VARIABLE VendorGuid
+ and have the L"HwErrRec####" name convention, #### is a printed hex value and no 0x or h is included in the hex value.
+
+ @param VariableName Pointer to variable name.
+ @param VendorGuid Variable Vendor Guid.
+
+ @retval TRUE Variable is hardware error record variable.
+ @retval FALSE Variable is not hardware error record variable.
+
+**/
+BOOLEAN
+EFIAPI
+IsHwErrRecVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ if (!CompareGuid (VendorGuid, &gEfiHardwareErrorVariableGuid) ||
+ (StrLen (VariableName) != StrLen (L"HwErrRec####")) ||
+ (StrnCmp(VariableName, L"HwErrRec", StrLen (L"HwErrRec")) != 0) ||
+ !IsHexaDecimalDigitCharacter (VariableName[0x8]) ||
+ !IsHexaDecimalDigitCharacter (VariableName[0x9]) ||
+ !IsHexaDecimalDigitCharacter (VariableName[0xA]) ||
+ !IsHexaDecimalDigitCharacter (VariableName[0xB])) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+
+ This code finds variable in storage blocks (Volatile or Non-Volatile).
+
+ @param VariableName Name of Variable to be found.
+ @param VendorGuid Variable vendor GUID.
+ @param Attributes Attribute value of the variable found.
+ @param DataSize Size of Data found. If size is less than the
+ data, this value contains the required size.
+ @param Data Data pointer.
+
+ @return EFI_INVALID_PARAMETER Invalid parameter.
+ @return EFI_SUCCESS Find the specified variable.
+ @return EFI_NOT_FOUND Not found.
+ @return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
+
+**/
+EFI_STATUS
+EFIAPI
+VariableServiceGetVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINT32 *Attributes OPTIONAL,
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_POINTER_TRACK Variable;
+ UINTN VarDataSize;
+
+ if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+ Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+ if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Get data size
+ //
+ VarDataSize = DataSizeOfVariable (Variable.CurrPtr);
+ ASSERT (VarDataSize != 0);
+
+ if (*DataSize >= VarDataSize) {
+ if (Data == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
+ if (Attributes != NULL) {
+ *Attributes = Variable.CurrPtr->Attributes;
+ }
+
+ *DataSize = VarDataSize;
+ UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);
+
+ Status = EFI_SUCCESS;
+ goto Done;
+ } else {
+ *DataSize = VarDataSize;
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+Done:
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+ return Status;
+}
+
+
+
+/**
+
+ This code Finds the Next available variable.
+
+ @param VariableNameSize Size of the variable name.
+ @param VariableName Pointer to variable name.
+ @param VendorGuid Variable Vendor Guid.
+
+ @return EFI_INVALID_PARAMETER Invalid parameter.
+ @return EFI_SUCCESS Find the specified variable.
+ @return EFI_NOT_FOUND Not found.
+ @return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
+
+**/
+EFI_STATUS
+EFIAPI
+VariableServiceGetNextVariableName (
+ IN OUT UINTN *VariableNameSize,
+ IN OUT CHAR16 *VariableName,
+ IN OUT EFI_GUID *VendorGuid
+ )
+{
+ VARIABLE_STORE_TYPE Type;
+ VARIABLE_POINTER_TRACK Variable;
+ VARIABLE_POINTER_TRACK VariableInHob;
+ UINTN VarNameSize;
+ EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
+
+ if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+ Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+ if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (VariableName[0] != 0) {
+ //
+ // If variable name is not NULL, get next variable.
+ //
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ }
+
+ //
+ // 0: Volatile, 1: HOB, 2: Non-Volatile.
+ // The index and attributes mapping must be kept in this order as FindVariable
+ // makes use of this mapping to implement search algorithm.
+ //
+ VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;
+ VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
+ VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache;
+
+ while (TRUE) {
+ //
+ // Switch from Volatile to HOB, to Non-Volatile.
+ //
+ while ((Variable.CurrPtr >= Variable.EndPtr) ||
+ (Variable.CurrPtr == NULL) ||
+ !IsValidVariableHeader (Variable.CurrPtr)
+ ) {
+ //
+ // Find current storage index
+ //
+ for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
+ if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
+ break;
+ }
+ }
+ ASSERT (Type < VariableStoreTypeMax);
+ //
+ // Switch to next storage
+ //
+ for (Type++; Type < VariableStoreTypeMax; Type++) {
+ if (VariableStoreHeader[Type] != NULL) {
+ break;
+ }
+ }
+ //
+ // Capture the case that
+ // 1. current storage is the last one, or
+ // 2. no further storage
+ //
+ if (Type == VariableStoreTypeMax) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
+ Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]);
+ Variable.CurrPtr = Variable.StartPtr;
+ }
+
+ //
+ // Variable is found
+ //
+ if (Variable.CurrPtr->State == VAR_ADDED) {
+ if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {
+
+ //
+ // Don't return NV variable when HOB overrides it
+ //
+ if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&
+ (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
+ ) {
+ VariableInHob.StartPtr = GetStartPointer (VariableStoreHeader[VariableStoreTypeHob]);
+ VariableInHob.EndPtr = GetEndPointer (VariableStoreHeader[VariableStoreTypeHob]);
+ Status = FindVariableEx (
+ GetVariableNamePtr (Variable.CurrPtr),
+ &Variable.CurrPtr->VendorGuid,
+ FALSE,
+ &VariableInHob
+ );
+ if (!EFI_ERROR (Status)) {
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ continue;
+ }
+ }
+
+ VarNameSize = NameSizeOfVariable (Variable.CurrPtr);
+ ASSERT (VarNameSize != 0);
+
+ if (VarNameSize <= *VariableNameSize) {
+ CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);
+ CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *VariableNameSize = VarNameSize;
+ goto Done;
+ }
+ }
+
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ }
+
+Done:
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+ return Status;
+}
+
+/**
+
+ This code sets variable in storage blocks (Volatile or Non-Volatile).
+
+ @param VariableName Name of Variable to be found.
+ @param VendorGuid Variable vendor GUID.
+ @param Attributes Attribute value of the variable found
+ @param DataSize Size of Data found. If size is less than the
+ data, this value contains the required size.
+ @param Data Data pointer.
+
+ @return EFI_INVALID_PARAMETER Invalid parameter.
+ @return EFI_SUCCESS Set successfully.
+ @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @return EFI_NOT_FOUND Not found.
+ @return EFI_WRITE_PROTECTED Variable is read-only.
+
+**/
+EFI_STATUS
+EFIAPI
+VariableServiceSetVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ VARIABLE_POINTER_TRACK Variable;
+ EFI_STATUS Status;
+ VARIABLE_HEADER *NextVariable;
+ EFI_PHYSICAL_ADDRESS Point;
+
+ //
+ // Check input parameters.
+ //
+ if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If variable handled by QuarkVariableLockHandler then don't set the
+ // variable and return success.
+ //
+ if (QuarkVariableLockHandler (VariableName, VendorGuid)) {
+ return EFI_SUCCESS;
+ }
+
+ if (DataSize != 0 && Data == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Not support authenticated variable write yet.
+ //
+ if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Make sure if runtime bit is set, boot service bit is set also.
+ //
+ if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The size of the VariableName, including the Unicode Null in bytes plus
+ // the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)
+ // bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.
+ //
+ if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
+ if ((DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) ||
+ (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!IsHwErrRecVariable(VariableName, VendorGuid)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // The size of the VariableName, including the Unicode Null in bytes plus
+ // the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.
+ //
+ if ((DataSize > PcdGet32 (PcdMaxVariableSize)) ||
+ (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize))) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (AtRuntime ()) {
+ //
+ // HwErrRecSupport Global Variable identifies the level of hardware error record persistence
+ // support implemented by the platform. This variable is only modified by firmware and is read-only to the OS.
+ //
+ if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, L"HwErrRecSupport") == 0)) {
+ return EFI_WRITE_PROTECTED;
+ }
+ }
+
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+ //
+ // Consider reentrant in MCA/INIT/NMI. It needs be reupdated.
+ //
+ if (1 < InterlockedIncrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState)) {
+ Point = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
+ //
+ // Parse non-volatile variable data and get last variable offset.
+ //
+ NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point);
+ while ((NextVariable < GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point))
+ && IsValidVariableHeader (NextVariable)) {
+ NextVariable = GetNextVariablePtr (NextVariable);
+ }
+ mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point;
+ }
+
+ //
+ // Check whether the input variable is already existed.
+ //
+ Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, TRUE);
+ if (!EFI_ERROR (Status)) {
+ if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) {
+ return EFI_WRITE_PROTECTED;
+ }
+ }
+
+ //
+ // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
+ //
+ AutoUpdateLangVariable (VariableName, Data, DataSize);
+
+ Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);
+
+ InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+ return Status;
+}
+
+/**
+
+ This code returns information about the EFI variables.
+
+ @param Attributes Attributes bitmask to specify the type of variables
+ on which to return information.
+ @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
+ for the EFI variables associated with the attributes specified.
+ @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
+ for EFI variables associated with the attributes specified.
+ @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
+ associated with the attributes specified.
+
+ @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
+ @return EFI_SUCCESS Query successfully.
+ @return EFI_UNSUPPORTED The attribute is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+VariableServiceQueryVariableInfo (
+ IN UINT32 Attributes,
+ OUT UINT64 *MaximumVariableStorageSize,
+ OUT UINT64 *RemainingVariableStorageSize,
+ OUT UINT64 *MaximumVariableSize
+ )
+{
+ VARIABLE_HEADER *Variable;
+ VARIABLE_HEADER *NextVariable;
+ UINT64 VariableSize;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINT64 CommonVariableTotalSize;
+ UINT64 HwErrVariableTotalSize;
+
+ CommonVariableTotalSize = 0;
+ HwErrVariableTotalSize = 0;
+
+ if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {
+ //
+ // Make sure the Attributes combination is supported by the platform.
+ //
+ return EFI_UNSUPPORTED;
+ } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
+ //
+ // Make sure if runtime bit is set, boot service bit is set also.
+ //
+ return EFI_INVALID_PARAMETER;
+ } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
+ //
+ // Make sure RT Attribute is set if we are in Runtime phase.
+ //
+ return EFI_INVALID_PARAMETER;
+ } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
+ //
+ // Make sure Hw Attribute is set with NV.
+ //
+ return EFI_INVALID_PARAMETER;
+ } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
+ //
+ // Not support authentiated variable write yet.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+ if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
+ //
+ // Query is Volatile related.
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
+ } else {
+ //
+ // Query is Non-Volatile related.
+ //
+ VariableStoreHeader = mNvVariableCache;
+ }
+
+ //
+ // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
+ // with the storage size (excluding the storage header size).
+ //
+ *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
+
+ //
+ // Harware error record variable needs larger size.
+ //
+ if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ *MaximumVariableStorageSize = PcdGet32 (PcdHwErrStorageSize);
+ *MaximumVariableSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER);
+ } else {
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
+ ASSERT (PcdGet32 (PcdHwErrStorageSize) < VariableStoreHeader->Size);
+ *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize);
+ }
+
+ //
+ // Let *MaximumVariableSize be PcdGet32 (PcdMaxVariableSize) with the exception of the variable header size.
+ //
+ *MaximumVariableSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);
+ }
+
+ //
+ // Point to the starting address of the variables.
+ //
+ Variable = GetStartPointer (VariableStoreHeader);
+
+ //
+ // Now walk through the related variable store.
+ //
+ while ((Variable < GetEndPointer (VariableStoreHeader)) && IsValidVariableHeader (Variable)) {
+ NextVariable = GetNextVariablePtr (Variable);
+ VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;
+
+ if (AtRuntime ()) {
+ //
+ // We don't take the state of the variables in mind
+ // when calculating RemainingVariableStorageSize,
+ // since the space occupied by variables not marked with
+ // VAR_ADDED is not allowed to be reclaimed in Runtime.
+ //
+ if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
+ HwErrVariableTotalSize += VariableSize;
+ } else {
+ CommonVariableTotalSize += VariableSize;
+ }
+ } else {
+ //
+ // Only care about Variables with State VAR_ADDED, because
+ // the space not marked as VAR_ADDED is reclaimable now.
+ //
+ if (Variable->State == VAR_ADDED) {
+ if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
+ HwErrVariableTotalSize += VariableSize;
+ } else {
+ CommonVariableTotalSize += VariableSize;
+ }
+ }
+ }
+
+ //
+ // Go to the next one.
+ //
+ Variable = NextVariable;
+ }
+
+ if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD){
+ *RemainingVariableStorageSize = *MaximumVariableStorageSize - HwErrVariableTotalSize;
+ }else {
+ *RemainingVariableStorageSize = *MaximumVariableStorageSize - CommonVariableTotalSize;
+ }
+
+ if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {
+ *MaximumVariableSize = 0;
+ } else if ((*RemainingVariableStorageSize - sizeof (VARIABLE_HEADER)) < *MaximumVariableSize) {
+ *MaximumVariableSize = *RemainingVariableStorageSize - sizeof (VARIABLE_HEADER);
+ }
+
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function reclaims variable storage if free size is below the threshold.
+
+**/
+VOID
+ReclaimForOS(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN CommonVariableSpace;
+ UINTN RemainingCommonVariableSpace;
+ UINTN RemainingHwErrVariableSpace;
+
+ Status = EFI_SUCCESS;
+
+ CommonVariableSpace = ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)))->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32(PcdHwErrStorageSize); //Allowable max size of common variable storage space
+
+ RemainingCommonVariableSpace = CommonVariableSpace - mVariableModuleGlobal->CommonVariableTotalSize;
+
+ RemainingHwErrVariableSpace = PcdGet32 (PcdHwErrStorageSize) - mVariableModuleGlobal->HwErrVariableTotalSize;
+ //
+ // Check if the free area is blow a threshold.
+ //
+ if ((RemainingCommonVariableSpace < PcdGet32 (PcdMaxVariableSize))
+ || ((PcdGet32 (PcdHwErrStorageSize) != 0) &&
+ (RemainingHwErrVariableSpace < PcdGet32 (PcdMaxHardwareErrorVariableSize)))){
+ Status = Reclaim (
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset,
+ FALSE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+
+/**
+ Initializes variable write service after FVB was ready.
+
+ @retval EFI_SUCCESS Function successfully executed.
+ @retval Others Fail to initialize the variable service.
+
+**/
+EFI_STATUS
+VariableWriteServiceInitialize (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN Index;
+ UINT8 Data;
+ EFI_PHYSICAL_ADDRESS VariableStoreBase;
+ VARIABLE_HEADER *Variable;
+ VOID *VariableData;
+
+ VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
+
+ //
+ // Check if the free area is really free.
+ //
+ for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) {
+ Data = ((UINT8 *) mNvVariableCache)[Index];
+ if (Data != 0xff) {
+ //
+ // There must be something wrong in variable store, do reclaim operation.
+ //
+ Status = Reclaim (
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset,
+ FALSE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ break;
+ }
+ }
+
+ //
+ // Flush the HOB variable to flash and invalidate HOB variable.
+ //
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
+ //
+ // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
+
+ for ( Variable = GetStartPointer (VariableStoreHeader)
+ ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))
+ ; Variable = GetNextVariablePtr (Variable)
+ ) {
+ ASSERT (Variable->State == VAR_ADDED);
+ ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
+ VariableData = GetVariableDataPtr (Variable);
+ Status = VariableServiceSetVariable (
+ GetVariableNamePtr (Variable),
+ &Variable->VendorGuid,
+ Variable->Attributes,
+ Variable->DataSize,
+ VariableData
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initializes variable store area for non-volatile and volatile variable.
+
+ @retval EFI_SUCCESS Function successfully executed.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
+
+**/
+EFI_STATUS
+VariableCommonInitialize (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VolatileVariableStore;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ VARIABLE_HEADER *NextVariable;
+ EFI_PHYSICAL_ADDRESS TempVariableStoreHeader;
+ EFI_PHYSICAL_ADDRESS VariableStoreBase;
+ UINT64 VariableStoreLength;
+ UINTN ScratchSize;
+ UINTN VariableSize;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ //
+ // Allocate runtime memory for variable driver global structure.
+ //
+ mVariableModuleGlobal = AllocateRuntimeZeroPool (sizeof (VARIABLE_MODULE_GLOBAL));
+ if (mVariableModuleGlobal == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeLock (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);
+
+ //
+ // Note that in EdkII variable driver implementation, Hardware Error Record type variable
+ // is stored with common variable in the same NV region. So the platform integrator should
+ // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
+ // PcdFlashNvStorageVariableSize.
+ //
+ ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
+
+ //
+ // Get HOB variable store.
+ //
+ GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
+ if (GuidHob != NULL) {
+ VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);
+ if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
+ } else {
+ DEBUG ((EFI_D_ERROR, "HOB Variable Store header is corrupted!\n"));
+ }
+ }
+
+ //
+ // Allocate memory for volatile variable store, note that there is a scratch space to store scratch data.
+ //
+ ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
+ VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize);
+ if (VolatileVariableStore == NULL) {
+ FreePool (mVariableModuleGlobal);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetMem (VolatileVariableStore, PcdGet32 (PcdVariableStoreSize) + ScratchSize, 0xff);
+
+ //
+ // Initialize Variable Specific Data.
+ //
+ mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;
+ mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;
+ mVariableModuleGlobal->FvbInstance = NULL;
+
+ CopyGuid (&VolatileVariableStore->Signature, &gEfiVariableGuid);
+ VolatileVariableStore->Size = PcdGet32 (PcdVariableStoreSize);
+ VolatileVariableStore->Format = VARIABLE_STORE_FORMATTED;
+ VolatileVariableStore->State = VARIABLE_STORE_HEALTHY;
+ VolatileVariableStore->Reserved = 0;
+ VolatileVariableStore->Reserved1 = 0;
+
+ //
+ // Get non-volatile variable store.
+ //
+
+ TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
+ if (TempVariableStoreHeader == 0) {
+ TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
+ }
+
+ //
+ // Check if the Firmware Volume is not corrupted
+ //
+ if ((((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->Signature != EFI_FVH_SIGNATURE) ||
+ (!CompareGuid (&gEfiSystemNvDataFvGuid, &((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->FileSystemGuid))) {
+ Status = EFI_VOLUME_CORRUPTED;
+ DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
+ goto Done;
+ }
+
+ VariableStoreBase = TempVariableStoreHeader + \
+ (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
+ VariableStoreLength = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \
+ (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
+
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
+ if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
+ Status = EFI_VOLUME_CORRUPTED;
+ DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));
+ goto Done;
+ }
+ ASSERT(VariableStoreHeader->Size == VariableStoreLength);
+
+ //
+ // Parse non-volatile variable data and get last variable offset.
+ //
+ NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
+ while (IsValidVariableHeader (NextVariable)) {
+ VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
+ if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
+ } else {
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
+ }
+
+ NextVariable = GetNextVariablePtr (NextVariable);
+ }
+
+ mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
+
+ //
+ // Allocate runtime memory used for a memory copy of the FLASH region.
+ // Keep the memory and the FLASH in sync as updates occur
+ //
+ mNvVariableCache = AllocateRuntimeZeroPool ((UINTN)VariableStoreLength);
+ if (mNvVariableCache == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableStoreBase, (UINTN)VariableStoreLength);
+ Status = EFI_SUCCESS;
+
+Done:
+ if (EFI_ERROR (Status)) {
+ FreePool (mVariableModuleGlobal);
+ FreePool (VolatileVariableStore);
+ }
+
+ return Status;
+}
+
+
+/**
+ Get the proper fvb handle and/or fvb protocol by the given Flash address.
+
+ @param[in] Address The Flash address.
+ @param[out] FvbHandle In output, if it is not NULL, it points to the proper FVB handle.
+ @param[out] FvbProtocol In output, if it is not NULL, it points to the proper FVB protocol.
+
+**/
+EFI_STATUS
+GetFvbInfoByAddress (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ OUT EFI_HANDLE *FvbHandle OPTIONAL,
+ OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvbProtocol OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS FvbBaseAddress;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+
+ //
+ // Get all FVB handles.
+ //
+ Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the FVB to access variable store.
+ //
+ Fvb = NULL;
+ for (Index = 0; Index < HandleCount; Index += 1, Status = EFI_NOT_FOUND, Fvb = NULL) {
+ Status = GetFvbByHandle (HandleBuffer[Index], &Fvb);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ //
+ // Ensure this FVB protocol supported Write operation.
+ //
+ Status = Fvb->GetAttributes (Fvb, &Attributes);
+ if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
+ continue;
+ }
+
+ //
+ // Compare the address and select the right one.
+ //
+ Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
+ if ((Address >= FvbBaseAddress) && (Address < (FvbBaseAddress + FwVolHeader->FvLength))) {
+ if (FvbHandle != NULL) {
+ *FvbHandle = HandleBuffer[Index];
+ }
+ if (FvbProtocol != NULL) {
+ *FvbProtocol = Fvb;
+ }
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ FreePool (HandleBuffer);
+
+ if (Fvb == NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+
+ return Status;
+}
+
diff --git a/QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
new file mode 100644
index 0000000..fa49bbb
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -0,0 +1,110 @@
+## @file
+# Component description file for SMM Variable module.
+#
+# This module installs SMM variable protocol into SMM protocol database,
+# which can be used by SMM driver, and installs SMM variable protocol
+# into BS protocol database, which can be used to notify the SMM Runtime
+# Dxe driver that the SMM variable service is ready.
+# This module should be used with SMM Runtime DXE module together. The
+# SMM Runtime DXE module would install variable arch protocol and variable
+# write arch protocol based on SMM variable module.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VariableSmm
+ FILE_GUID = 23A089B3-EED5-4ac5-B2AB-43E3298C2343
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = VariableServiceInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+[Sources]
+ ../../../../../../MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c
+ Variable.c
+ ../../../../../../MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
+ ../../../../../../MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ MemoryAllocationLib
+ BaseLib
+ SynchronizationLib
+ UefiLib
+ SmmServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ DxeServicesTableLib
+ HobLib
+
+[Protocols]
+ gEfiSmmFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES
+ gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiVariableGuid ## PRODUCES ## Configuration Table Guid
+ gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid
+ gSmmVariableWriteGuid ## PRODUCES ## SMM Variable Write Guid
+ gEfiSystemNvDataFvGuid ## CONSUMES
+ gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES
+ gEfiMemoryConfigDataGuid ## SOMETIMES_CONSUMES
+ gQuarkVariableLockGuid ## SOMETIMES_CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)
+
+[Depex]
+ TRUE
+
+
diff --git a/QuarkPlatformPkg/Override/MdePkg/Include/Library/DebugLib.h b/QuarkPlatformPkg/Override/MdePkg/Include/Library/DebugLib.h
new file mode 100755
index 0000000..4d10b9a
--- /dev/null
+++ b/QuarkPlatformPkg/Override/MdePkg/Include/Library/DebugLib.h
@@ -0,0 +1,505 @@
+/** @file
+ Provides services to print debug and assert messages to a debug output device.
+
+ The Debug library supports debug print and asserts based on a combination of macros and code.
+ The debug library can be turned on and off so that the debug code does not increase the size of an image.
+
+ Note that a reserved macro named MDEPKG_NDEBUG is introduced for the intention
+ of size reduction when compiler optimization is disabled. If MDEPKG_NDEBUG is
+ defined, then debug and assert related macros wrapped by it are the NULL implementations.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __DEBUG_LIB_H__
+#define __DEBUG_LIB_H__
+
+//
+// Declare bits for PcdDebugPropertyMask
+//
+#define DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED 0x01
+#define DEBUG_PROPERTY_DEBUG_PRINT_ENABLED 0x02
+#define DEBUG_PROPERTY_DEBUG_CODE_ENABLED 0x04
+#define DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED 0x08
+#define DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED 0x10
+#define DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED 0x20
+
+//
+// Declare bits for PcdDebugPrintErrorLevel and the ErrorLevel parameter of DebugPrint()
+//
+#define DEBUG_INIT 0x00000001 // Initialization
+#define DEBUG_WARN 0x00000002 // Warnings
+#define DEBUG_LOAD 0x00000004 // Load events
+#define DEBUG_FS 0x00000008 // EFI File system
+#define DEBUG_POOL 0x00000010 // Alloc & Free's
+#define DEBUG_PAGE 0x00000020 // Alloc & Free's
+#define DEBUG_INFO 0x00000040 // Informational debug messages
+#define DEBUG_DISPATCH 0x00000080 // PEI/DXE/SMM Dispatchers
+#define DEBUG_VARIABLE 0x00000100 // Variable
+#define DEBUG_BM 0x00000400 // Boot Manager
+#define DEBUG_BLKIO 0x00001000 // BlkIo Driver
+#define DEBUG_NET 0x00004000 // SNI Driver
+#define DEBUG_UNDI 0x00010000 // UNDI Driver
+#define DEBUG_LOADFILE 0x00020000 // UNDI Driver
+#define DEBUG_EVENT 0x00080000 // Event messages
+#define DEBUG_GCD 0x00100000 // Global Coherency Database changes
+#define DEBUG_CACHE 0x00200000 // Memory range cachability changes
+#define DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may significantly impact boot performance
+#define DEBUG_ERROR 0x80000000 // Error
+
+//
+// Aliases of debug message mask bits
+//
+#define EFI_D_INIT DEBUG_INIT
+#define EFI_D_WARN DEBUG_WARN
+#define EFI_D_LOAD DEBUG_LOAD
+#define EFI_D_FS DEBUG_FS
+#define EFI_D_POOL DEBUG_POOL
+#define EFI_D_PAGE DEBUG_PAGE
+#define EFI_D_INFO DEBUG_INFO
+#define EFI_D_DISPATCH DEBUG_DISPATCH
+#define EFI_D_VARIABLE DEBUG_VARIABLE
+#define EFI_D_BM DEBUG_BM
+#define EFI_D_BLKIO DEBUG_BLKIO
+#define EFI_D_NET DEBUG_NET
+#define EFI_D_UNDI DEBUG_UNDI
+#define EFI_D_LOADFILE DEBUG_LOADFILE
+#define EFI_D_EVENT DEBUG_EVENT
+#define EFI_D_VERBOSE DEBUG_VERBOSE
+#define EFI_D_ERROR DEBUG_ERROR
+
+/**
+ Prints a debug message to the debug output device if the specified error level is enabled.
+
+ If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
+ GetDebugPrintErrorLevel (), then print the message specified by Format and the
+ associated variable argument list to the debug output device.
+
+ If Format is NULL, then ASSERT().
+
+ @param ErrorLevel The error level of the debug message.
+ @param Format The format string for the debug message to print.
+ @param ... The variable argument list whose contents are accessed
+ based on the format string specified by Format.
+
+**/
+VOID
+EFIAPI
+DebugPrint (
+ IN UINTN ErrorLevel,
+ IN CONST CHAR8 *Format,
+ ...
+ );
+
+
+/**
+ Prints an assert message containing a filename, line number, and description.
+ This may be followed by a breakpoint or a dead loop.
+
+ Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
+ to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
+ PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
+ DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
+ CpuDeadLoop() is called. If neither of these bits are set, then this function
+ returns immediately after the message is printed to the debug output device.
+ DebugAssert() must actively prevent recursion. If DebugAssert() is called while
+ processing another DebugAssert(), then DebugAssert() must return immediately.
+
+ If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
+ If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
+
+ @param FileName The pointer to the name of the source file that generated the assert condition.
+ @param LineNumber The line number in the source file that generated the assert condition
+ @param Description The pointer to the description of the assert condition.
+
+**/
+VOID
+EFIAPI
+DebugAssert (
+ IN CONST CHAR8 *FileName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *Description
+ );
+
+
+/**
+ Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
+
+ This function fills Length bytes of Buffer with the value specified by
+ PcdDebugClearMemoryValue, and returns Buffer.
+
+ If Buffer is NULL, then ASSERT().
+ If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+ @param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
+ @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
+
+ @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue.
+
+**/
+VOID *
+EFIAPI
+DebugClearMemory (
+ OUT VOID *Buffer,
+ IN UINTN Length
+ );
+
+
+/**
+ Returns TRUE if ASSERT() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise, FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugAssertEnabled (
+ VOID
+ );
+
+
+/**
+ Returns TRUE if DEBUG() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise, FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugPrintEnabled (
+ VOID
+ );
+
+
+/**
+ Returns TRUE if DEBUG_CODE() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise, FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugCodeEnabled (
+ VOID
+ );
+
+
+/**
+ Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise, FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugClearMemoryEnabled (
+ VOID
+ );
+
+
+/**
+ Internal worker macro that calls DebugAssert().
+
+ This macro calls DebugAssert(), passing in the filename, line number, and an
+ expression that evaluated to FALSE.
+
+ @param Expression Boolean expression that evaluated to FALSE
+
+**/
+//BugID31643 - Start
+// #define _ASSERT(Expression) DebugAssert (__FILE__, __LINE__, #Expression)
+#if !defined(__GNUC__)
+#define _ASSERT(Expression) DebugAssert (__FILE__, __LINE__, #Expression)
+#else
+VOID
+EFIAPI
+CpuDeadLoop (
+ VOID
+ );
+
+#define _ASSERT(Expression) CpuDeadLoop()
+#endif
+//BugID31643 - End
+
+/**
+ Internal worker macro that calls DebugPrint().
+
+ This macro calls DebugPrint() passing in the debug error level, a format
+ string, and a variable argument list.
+
+ @param Expression Expression containing an error level, a format string,
+ and a variable argument list based on the format string.
+
+**/
+#define _DEBUG(Expression) DebugPrint Expression
+
+
+/**
+ Macro that calls DebugAssert() if an expression evaluates to FALSE.
+
+ If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED
+ bit of PcdDebugProperyMask is set, then this macro evaluates the Boolean
+ expression specified by Expression. If Expression evaluates to FALSE, then
+ DebugAssert() is called passing in the source filename, source line number,
+ and Expression.
+
+ @param Expression Boolean expression.
+
+**/
+#if !defined(MDEPKG_NDEBUG)
+ #define ASSERT(Expression) \
+ do { \
+ if (DebugAssertEnabled ()) { \
+ if (!(Expression)) { \
+ _ASSERT (Expression); \
+ } \
+ } \
+ } while (FALSE)
+#else
+ #define ASSERT(Expression)
+#endif
+
+/**
+ Macro that calls DebugPrint().
+
+ If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED
+ bit of PcdDebugProperyMask is set, then this macro passes Expression to
+ DebugPrint().
+
+ @param Expression Expression containing an error level, a format string,
+ and a variable argument list based on the format string.
+
+
+**/
+#if !defined(MDEPKG_NDEBUG)
+ #define DEBUG(Expression) \
+ do { \
+ if (DebugPrintEnabled ()) { \
+ _DEBUG (Expression); \
+ } \
+ } while (FALSE)
+#else
+ #define DEBUG(Expression)
+#endif
+
+/**
+ Macro that calls DebugAssert() if an EFI_STATUS evaluates to an error code.
+
+ If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED
+ bit of PcdDebugProperyMask is set, then this macro evaluates the EFI_STATUS
+ value specified by StatusParameter. If StatusParameter is an error code,
+ then DebugAssert() is called passing in the source filename, source line
+ number, and StatusParameter.
+
+ @param StatusParameter EFI_STATUS value to evaluate.
+
+**/
+#if !defined(MDEPKG_NDEBUG)
+ #define ASSERT_EFI_ERROR(StatusParameter) \
+ do { \
+ if (DebugAssertEnabled ()) { \
+ if (EFI_ERROR (StatusParameter)) { \
+ DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", StatusParameter)); \
+ _ASSERT (!EFI_ERROR (StatusParameter)); \
+ } \
+ } \
+ } while (FALSE)
+#else
+ #define ASSERT_EFI_ERROR(StatusParameter)
+#endif
+
+/**
+ Macro that calls DebugAssert() if a protocol is already installed in the
+ handle database.
+
+ If MDEPKG_NDEBUG is defined or the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit
+ of PcdDebugProperyMask is clear, then return.
+
+ If Handle is NULL, then a check is made to see if the protocol specified by Guid
+ is present on any handle in the handle database. If Handle is not NULL, then
+ a check is made to see if the protocol specified by Guid is present on the
+ handle specified by Handle. If the check finds the protocol, then DebugAssert()
+ is called passing in the source filename, source line number, and Guid.
+
+ If Guid is NULL, then ASSERT().
+
+ @param Handle The handle to check for the protocol. This is an optional
+ parameter that may be NULL. If it is NULL, then the entire
+ handle database is searched.
+
+ @param Guid The pointer to a protocol GUID.
+
+**/
+#if !defined(MDEPKG_NDEBUG)
+ #define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid) \
+ do { \
+ if (DebugAssertEnabled ()) { \
+ VOID *Instance; \
+ ASSERT (Guid != NULL); \
+ if (Handle == NULL) { \
+ if (!EFI_ERROR (gBS->LocateProtocol ((EFI_GUID *)Guid, NULL, &Instance))) { \
+ _ASSERT (Guid already installed in database); \
+ } \
+ } else { \
+ if (!EFI_ERROR (gBS->HandleProtocol (Handle, (EFI_GUID *)Guid, &Instance))) { \
+ _ASSERT (Guid already installed on Handle); \
+ } \
+ } \
+ } \
+ } while (FALSE)
+#else
+ #define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid)
+#endif
+
+/**
+ Macro that marks the beginning of debug source code.
+
+ If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set,
+ then this macro marks the beginning of source code that is included in a module.
+ Otherwise, the source lines between DEBUG_CODE_BEGIN() and DEBUG_CODE_END()
+ are not included in a module.
+
+**/
+#define DEBUG_CODE_BEGIN() do { if (DebugCodeEnabled ()) { UINT8 __DebugCodeLocal
+
+
+/**
+ The macro that marks the end of debug source code.
+
+ If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set,
+ then this macro marks the end of source code that is included in a module.
+ Otherwise, the source lines between DEBUG_CODE_BEGIN() and DEBUG_CODE_END()
+ are not included in a module.
+
+**/
+#define DEBUG_CODE_END() __DebugCodeLocal = 0; __DebugCodeLocal++; } } while (FALSE)
+
+
+/**
+ The macro that declares a section of debug source code.
+
+ If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set,
+ then the source code specified by Expression is included in a module.
+ Otherwise, the source specified by Expression is not included in a module.
+
+**/
+#define DEBUG_CODE(Expression) \
+ DEBUG_CODE_BEGIN (); \
+ Expression \
+ DEBUG_CODE_END ()
+
+
+/**
+ The macro that calls DebugClearMemory() to clear a buffer to a default value.
+
+ If the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set,
+ then this macro calls DebugClearMemory() passing in Address and Length.
+
+ @param Address The pointer to a buffer.
+ @param Length The number of bytes in the buffer to set.
+
+**/
+#define DEBUG_CLEAR_MEMORY(Address, Length) \
+ do { \
+ if (DebugClearMemoryEnabled ()) { \
+ DebugClearMemory (Address, Length); \
+ } \
+ } while (FALSE)
+
+
+/**
+ Macro that calls DebugAssert() if the containing record does not have a
+ matching signature. If the signatures matches, then a pointer to the data
+ structure that contains a specified field of that data structure is returned.
+ This is a lightweight method hide information by placing a public data
+ structure inside a larger private data structure and using a pointer to the
+ public data structure to retrieve a pointer to the private data structure.
+
+ If MDEPKG_NDEBUG is defined or the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit
+ of PcdDebugProperyMask is clear, then this macro computes the offset, in bytes,
+ of the field specified by Field from the beginning of the data structure specified
+ by TYPE. This offset is subtracted from Record, and is used to return a pointer
+ to a data structure of the type specified by TYPE.
+
+ If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit
+ of PcdDebugProperyMask is set, then this macro computes the offset, in bytes,
+ of field specified by Field from the beginning of the data structure specified
+ by TYPE. This offset is subtracted from Record, and is used to compute a pointer
+ to a data structure of the type specified by TYPE. The Signature field of the
+ data structure specified by TYPE is compared to TestSignature. If the signatures
+ match, then a pointer to the pointer to a data structure of the type specified by
+ TYPE is returned. If the signatures do not match, then DebugAssert() is called
+ with a description of "CR has a bad signature" and Record is returned.
+
+ If the data type specified by TYPE does not contain the field specified by Field,
+ then the module will not compile.
+
+ If TYPE does not contain a field called Signature, then the module will not
+ compile.
+
+ @param Record The pointer to the field specified by Field within a data
+ structure of type TYPE.
+
+ @param TYPE The name of the data structure type to return This
+ data structure must contain the field specified by Field.
+
+ @param Field The name of the field in the data structure specified
+ by TYPE to which Record points.
+
+ @param TestSignature The 32-bit signature value to match.
+
+**/
+#if !defined(MDEPKG_NDEBUG)
+ #define CR(Record, TYPE, Field, TestSignature) \
+ (DebugAssertEnabled () && (BASE_CR (Record, TYPE, Field)->Signature != TestSignature)) ? \
+ (TYPE *) (_ASSERT (CR has Bad Signature), Record) : \
+ BASE_CR (Record, TYPE, Field)
+#else
+ #define CR(Record, TYPE, Field, TestSignature) \
+ BASE_CR (Record, TYPE, Field)
+#endif
+
+#endif
diff --git a/QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c b/QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
new file mode 100644
index 0000000..83278b3
--- /dev/null
+++ b/QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
@@ -0,0 +1,1132 @@
+/** @file
+ RTC Architectural Protocol GUID as defined in DxeCis 0.96.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PcRtc.h"
+
+/**
+ Compare the Hour, Minute and Second of the From time and the To time.
+
+ Only compare H/M/S in EFI_TIME and ignore other fields here.
+
+ @param From the first time
+ @param To the second time
+
+ @return >0 The H/M/S of the From time is later than those of To time
+ @return ==0 The H/M/S of the From time is same as those of To time
+ @return <0 The H/M/S of the From time is earlier than those of To time
+**/
+INTN
+CompareHMS (
+ IN EFI_TIME *From,
+ IN EFI_TIME *To
+ );
+
+/**
+ To check if second date is later than first date within 24 hours.
+
+ @param From the first date
+ @param To the second date
+
+ @retval TRUE From is previous to To within 24 hours.
+ @retval FALSE From is later, or it is previous to To more than 24 hours.
+**/
+BOOLEAN
+IsWithinOneDay (
+ IN EFI_TIME *From,
+ IN EFI_TIME *To
+ );
+
+/**
+ Read RTC content through its registers.
+
+ @param Address Address offset of RTC. It is recommended to use macros such as
+ RTC_ADDRESS_SECONDS.
+
+ @return The data of UINT8 type read from RTC.
+**/
+UINT8
+RtcRead (
+ IN UINT8 Address
+ )
+{
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
+ return IoRead8 (PCAT_RTC_DATA_REGISTER);
+}
+
+/**
+ Write RTC through its registers.
+
+ @param Address Address offset of RTC. It is recommended to use macros such as
+ RTC_ADDRESS_SECONDS.
+ @param Data The content you want to write into RTC.
+
+**/
+VOID
+RtcWrite (
+ IN UINT8 Address,
+ IN UINT8 Data
+ )
+{
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);
+}
+
+/**
+ Initialize RTC.
+
+ @param Global For global use inside this module.
+
+ @retval EFI_DEVICE_ERROR Initialization failed due to device error.
+ @retval EFI_SUCCESS Initialization successful.
+
+**/
+EFI_STATUS
+PcRtcInit (
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+{
+ EFI_STATUS Status;
+ RTC_REGISTER_A RegisterA;
+ RTC_REGISTER_B RegisterB;
+ RTC_REGISTER_D RegisterD;
+ UINT8 Century;
+ EFI_TIME Time;
+ UINTN DataSize;
+ UINT32 TimerVar;
+
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ if (!EfiAtRuntime ()) {
+ EfiAcquireLock (&Global->RtcLock);
+ }
+ //
+ // Initialize RTC Register
+ //
+ // Make sure Division Chain is properly configured,
+ // or RTC clock won't "tick" -- time won't increment
+ //
+ RegisterA.Data = RTC_INIT_REGISTER_A;
+ RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data);
+
+ //
+ // Read Register B
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+ //
+ // Clear RTC flag register
+ //
+ RtcRead (RTC_ADDRESS_REGISTER_C);
+
+ //
+ // Clear RTC register D
+ //
+ RegisterD.Data = RTC_INIT_REGISTER_D;
+ RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data);
+
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+ if (EFI_ERROR (Status)) {
+ //
+ // Set the variable with default value if the RTC is functioning incorrectly.
+ //
+ Global->SavedTimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ Global->Daylight = 0;
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Get the Time/Date/Daylight Savings values.
+ //
+ Time.Second = RtcRead (RTC_ADDRESS_SECONDS);
+ Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);
+ Time.Hour = RtcRead (RTC_ADDRESS_HOURS);
+ Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ Time.Month = RtcRead (RTC_ADDRESS_MONTH);
+ Time.Year = RtcRead (RTC_ADDRESS_YEAR);
+
+ Century = RtcRead (RTC_ADDRESS_CENTURY);
+
+ //
+ // Set RTC configuration after get original time
+ // The value of bit AIE should be reserved.
+ //
+ RtcWrite (RTC_ADDRESS_REGISTER_B, (UINT8)(RTC_INIT_REGISTER_B | (RegisterB.Data & BIT5)));
+
+ //
+ // Release RTC Lock.
+ //
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+
+ //
+ // Get the data of Daylight saving and time zone, if they have been
+ // stored in NV variable during previous boot.
+ //
+ DataSize = sizeof (UINT32);
+ Status = EfiGetVariable (
+ L"RTC",
+ &gEfiCallerIdGuid,
+ NULL,
+ &DataSize,
+ (VOID *) &TimerVar
+ );
+ if (!EFI_ERROR (Status)) {
+ Time.TimeZone = (INT16) TimerVar;
+ Time.Daylight = (UINT8) (TimerVar >> 16);
+ } else {
+ Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ Time.Daylight = 0;
+ }
+
+ //
+ // Validate time fields
+ //
+ Status = ConvertRtcTimeToEfiTime (&Time, Century, RegisterB);
+ if (!EFI_ERROR (Status)) {
+ Status = RtcTimeFieldsValid (&Time);
+ }
+ if (EFI_ERROR (Status)) {
+ //
+ // Report Status Code to indicate that the RTC has bad date and time
+ //
+ //
+ // Replace call to report status code with debug warning message on override
+ // for this hardware since we only wish to see error traces on serial port
+ // during release builds for unexpected errors.
+ // i.e we expect an invalid time if no battery (or 1st boot after
+ // installing battery) on this HW.
+ //
+ DEBUG ((EFI_D_WARN, "PcRtcInit: Read BadTime from RTC, Program RTC with default time.\n"));
+ //REPORT_STATUS_CODE (
+ // EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ // (EFI_SOFTWARE_DXE_RT_DRIVER | EFI_SW_EC_BAD_DATE_TIME)
+ // );
+ Time.Second = RTC_INIT_SECOND;
+ Time.Minute = RTC_INIT_MINUTE;
+ Time.Hour = RTC_INIT_HOUR;
+ Time.Day = RTC_INIT_DAY;
+ Time.Month = RTC_INIT_MONTH;
+ Time.Year = RTC_INIT_YEAR;
+ Time.Nanosecond = 0;
+ Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ Time.Daylight = 0;
+ }
+
+ //
+ // Reset time value according to new RTC configuration
+ //
+ Status = PcRtcSetTime (&Time, Global);
+ if(!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+ @param Global For global use inside this module.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+{
+ EFI_STATUS Status;
+ RTC_REGISTER_B RegisterB;
+ UINT8 Century;
+
+ //
+ // Check parameters for null pointer
+ //
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+
+ }
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ if (!EfiAtRuntime ()) {
+ EfiAcquireLock (&Global->RtcLock);
+ }
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+ if (EFI_ERROR (Status)) {
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+ return Status;
+ }
+ //
+ // Read Register B
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+ //
+ // Get the Time/Date/Daylight Savings values.
+ //
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS);
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS);
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);
+
+ Century = RtcRead (RTC_ADDRESS_CENTURY);
+
+ //
+ // Release RTC Lock.
+ //
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+
+ //
+ // Get the variable that contains the TimeZone and Daylight fields
+ //
+ Time->TimeZone = Global->SavedTimeZone;
+ Time->Daylight = Global->Daylight;
+
+ //
+ // Make sure all field values are in correct range
+ //
+ Status = ConvertRtcTimeToEfiTime (Time, Century, RegisterB);
+ if (!EFI_ERROR (Status)) {
+ Status = RtcTimeFieldsValid (Time);
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Fill in Capabilities if it was passed in
+ //
+ if (Capabilities != NULL) {
+ Capabilities->Resolution = 1;
+ //
+ // 1 hertz
+ //
+ Capabilities->Accuracy = 50000000;
+ //
+ // 50 ppm
+ //
+ Capabilities->SetsToZero = FALSE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets the current local time and date information.
+
+ @param Time A pointer to the current time.
+ @param Global For global use inside this module.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcSetTime (
+ IN EFI_TIME *Time,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+{
+ EFI_STATUS Status;
+ EFI_TIME RtcTime;
+ RTC_REGISTER_B RegisterB;
+ UINT8 Century;
+ UINT32 TimerVar;
+
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure that the time fields are valid
+ //
+ Status = RtcTimeFieldsValid (Time);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (&RtcTime, Time, sizeof (EFI_TIME));
+
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ if (!EfiAtRuntime ()) {
+ EfiAcquireLock (&Global->RtcLock);
+ }
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+ if (EFI_ERROR (Status)) {
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+ return Status;
+ }
+ //
+ // Read Register B, and inhibit updates of the RTC
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+ RegisterB.Bits.Set = 1;
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+ ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);
+
+ RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);
+ RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);
+ RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);
+ RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);
+ RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);
+ RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year);
+ RtcWrite (RTC_ADDRESS_CENTURY, Century);
+
+ //
+ // Allow updates of the RTC registers
+ //
+ RegisterB.Bits.Set = 0;
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+ //
+ // Release RTC Lock.
+ //
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+ //
+ // Set the variable that contains the TimeZone and Daylight fields
+ //
+ Global->SavedTimeZone = Time->TimeZone;
+ Global->Daylight = Time->Daylight;
+
+ TimerVar = Time->Daylight;
+ TimerVar = (UINT32) ((TimerVar << 16) | (UINT16)(Time->TimeZone));
+ Status = EfiSetVariable (
+ L"RTC",
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (TimerVar),
+ &TimerVar
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgment.
+ @param Time The current alarm setting.
+ @param Global For global use inside this module.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Enabled is NULL.
+ @retval EFI_INVALID_PARAMETER Pending is NULL.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+PcRtcGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+{
+ EFI_STATUS Status;
+ RTC_REGISTER_B RegisterB;
+ RTC_REGISTER_C RegisterC;
+ UINT8 Century;
+ EFI_TIME RtcTime;
+ UINTN DataSize;
+
+ //
+ // Check parameters for null pointers
+ //
+ if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {
+ return EFI_INVALID_PARAMETER;
+
+ }
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ if (!EfiAtRuntime ()) {
+ EfiAcquireLock (&Global->RtcLock);
+ }
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+ if (EFI_ERROR (Status)) {
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Read Register B and Register C
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+ RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);
+
+ //
+ // Get the Time/Date/Daylight Savings values.
+ //
+ *Enabled = RegisterB.Bits.Aie;
+ *Pending = RegisterC.Bits.Af;
+
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM);
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM);
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM);
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);
+ Time->TimeZone = Global->SavedTimeZone;
+ Time->Daylight = Global->Daylight;
+
+ Century = RtcRead (RTC_ADDRESS_CENTURY);
+
+ //
+ // Get the alarm info from variable
+ //
+ DataSize = sizeof (EFI_TIME);
+ Status = EfiGetVariable (
+ L"RTCALARM",
+ &gEfiCallerIdGuid,
+ NULL,
+ &DataSize,
+ &RtcTime
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // The alarm variable exists. In this case, we read variable to get info.
+ //
+ Time->Day = RtcTime.Day;
+ Time->Month = RtcTime.Month;
+ Time->Year = RtcTime.Year;
+ }
+
+ //
+ // Release RTC Lock.
+ //
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+
+ //
+ // Make sure all field values are in correct range
+ //
+ Status = ConvertRtcTimeToEfiTime (Time, Century, RegisterB);
+ if (!EFI_ERROR (Status)) {
+ Status = RtcTimeFieldsValid (Time);
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param Enabled Enable or disable the wakeup alarm.
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
+ If Enable is FALSE, then this parameter is optional, and may be NULL.
+ @param Global For global use inside this module.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled.
+ If Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+PcRtcSetWakeupTime (
+ IN BOOLEAN Enable,
+ IN EFI_TIME *Time, OPTIONAL
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+{
+ EFI_STATUS Status;
+ EFI_TIME RtcTime;
+ RTC_REGISTER_B RegisterB;
+ UINT8 Century;
+ EFI_TIME_CAPABILITIES Capabilities;
+
+ ZeroMem (&RtcTime, sizeof (RtcTime));
+
+ if (Enable) {
+
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure that the time fields are valid
+ //
+ Status = RtcTimeFieldsValid (Time);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Just support set alarm time within 24 hours
+ //
+ PcRtcGetTime (&RtcTime, &Capabilities, Global);
+ Status = RtcTimeFieldsValid (&RtcTime);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ if (!IsWithinOneDay (&RtcTime, Time)) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Make a local copy of the time and date
+ //
+ CopyMem (&RtcTime, Time, sizeof (EFI_TIME));
+
+ }
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ if (!EfiAtRuntime ()) {
+ EfiAcquireLock (&Global->RtcLock);
+ }
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+ if (EFI_ERROR (Status)) {
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Read Register B, and inhibit updates of the RTC
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+ RegisterB.Bits.Set = 1;
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+ if (Enable) {
+ ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);
+
+ //
+ // Set RTC alarm time
+ //
+ RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);
+ RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);
+ RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);
+
+ RegisterB.Bits.Aie = 1;
+
+ } else {
+ RegisterB.Bits.Aie = 0;
+ //
+ // if the alarm is disable, record the current setting.
+ //
+ RtcTime.Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM);
+ RtcTime.Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM);
+ RtcTime.Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM);
+ RtcTime.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ RtcTime.Month = RtcRead (RTC_ADDRESS_MONTH);
+ RtcTime.Year = RtcRead (RTC_ADDRESS_YEAR);
+ RtcTime.TimeZone = Global->SavedTimeZone;
+ RtcTime.Daylight = Global->Daylight;
+ }
+ //
+ // Allow updates of the RTC registers
+ //
+ RegisterB.Bits.Set = 0;
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+ //
+ // Set the Y/M/D info to variable as it has no corresponding hw registers.
+ //
+ Status = EfiSetVariable (
+ L"RTCALARM",
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (RtcTime),
+ &RtcTime
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Release RTC Lock.
+ //
+ if (!EfiAtRuntime ()) {
+ EfiReleaseLock (&Global->RtcLock);
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Checks an 8-bit BCD value, and converts to an 8-bit value if valid.
+
+ This function checks the 8-bit BCD value specified by Value.
+ If valid, the function converts it to an 8-bit value and returns it.
+ Otherwise, return 0xff.
+
+ @param Value The 8-bit BCD value to check and convert
+
+ @return The 8-bit value converted. Or 0xff if Value is invalid.
+
+**/
+UINT8
+CheckAndConvertBcd8ToDecimal8 (
+ IN UINT8 Value
+ )
+{
+ if ((Value < 0xa0) && ((Value & 0xf) < 0xa)) {
+ return BcdToDecimal8 (Value);
+ }
+
+ return 0xff;
+}
+
+/**
+ Converts time read from RTC to EFI_TIME format defined by UEFI spec.
+
+ This function converts raw time data read from RTC to the EFI_TIME format
+ defined by UEFI spec.
+ If data mode of RTC is BCD, then converts it to decimal,
+ If RTC is in 12-hour format, then converts it to 24-hour format.
+
+ @param Time On input, the time data read from RTC to convert
+ On output, the time converted to UEFI format
+ @param Century Value of century read from RTC.
+ @param RegisterB Value of Register B of RTC, indicating data mode
+ and hour format.
+
+ @retval EFI_INVALID_PARAMETER Parameters passed in are invalid.
+ @retval EFI_SUCCESS Convert RTC time to EFI time successfully.
+
+**/
+EFI_STATUS
+ConvertRtcTimeToEfiTime (
+ IN OUT EFI_TIME *Time,
+ IN UINT8 Century,
+ IN RTC_REGISTER_B RegisterB
+ )
+{
+ BOOLEAN IsPM;
+
+ if ((Time->Hour & 0x80) != 0) {
+ IsPM = TRUE;
+ } else {
+ IsPM = FALSE;
+ }
+
+ Time->Hour = (UINT8) (Time->Hour & 0x7f);
+
+ if (RegisterB.Bits.Dm == 0) {
+ Time->Year = CheckAndConvertBcd8ToDecimal8 ((UINT8) Time->Year);
+ Time->Month = CheckAndConvertBcd8ToDecimal8 (Time->Month);
+ Time->Day = CheckAndConvertBcd8ToDecimal8 (Time->Day);
+ Time->Hour = CheckAndConvertBcd8ToDecimal8 (Time->Hour);
+ Time->Minute = CheckAndConvertBcd8ToDecimal8 (Time->Minute);
+ Time->Second = CheckAndConvertBcd8ToDecimal8 (Time->Second);
+ }
+ Century = CheckAndConvertBcd8ToDecimal8 (Century);
+
+ if (Time->Year == 0xff || Time->Month == 0xff || Time->Day == 0xff ||
+ Time->Hour == 0xff || Time->Minute == 0xff || Time->Second == 0xff ||
+ Century == 0xff) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Time->Year = (UINT16) (Century * 100 + Time->Year);
+
+ //
+ // If time is in 12 hour format, convert it to 24 hour format
+ //
+ if (RegisterB.Bits.Mil == 0) {
+ if (IsPM && Time->Hour < 12) {
+ Time->Hour = (UINT8) (Time->Hour + 12);
+ }
+
+ if (!IsPM && Time->Hour == 12) {
+ Time->Hour = 0;
+ }
+ }
+
+ Time->Nanosecond = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wait for a period for the RTC to be ready.
+
+ @param Timeout Tell how long it should take to wait.
+
+ @retval EFI_DEVICE_ERROR RTC device error.
+ @retval EFI_SUCCESS RTC is updated and ready.
+**/
+EFI_STATUS
+RtcWaitToUpdate (
+ UINTN Timeout
+ )
+{
+ RTC_REGISTER_A RegisterA;
+ RTC_REGISTER_D RegisterD;
+
+ //
+ // See if the RTC is functioning correctly
+ //
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
+
+ if (RegisterD.Bits.Vrt == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Wait for up to 0.1 seconds for the RTC to be ready.
+ //
+ Timeout = (Timeout / 10) + 1;
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
+ while (RegisterA.Bits.Uip == 1 && Timeout > 0) {
+ MicroSecondDelay (10);
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
+ Timeout--;
+ }
+
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
+ if (Timeout == 0 || RegisterD.Bits.Vrt == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ See if all fields of a variable of EFI_TIME type is correct.
+
+ @param Time The time to be checked.
+
+ @retval EFI_INVALID_PARAMETER Some fields of Time are not correct.
+ @retval EFI_SUCCESS Time is a valid EFI_TIME variable.
+
+**/
+EFI_STATUS
+RtcTimeFieldsValid (
+ IN EFI_TIME *Time
+ )
+{
+ if (Time->Year < 1998 ||
+ Time->Year > 2099 ||
+ Time->Month < 1 ||
+ Time->Month > 12 ||
+ (!DayValid (Time)) ||
+ Time->Hour > 23 ||
+ Time->Minute > 59 ||
+ Time->Second > 59 ||
+ Time->Nanosecond > 999999999 ||
+ (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||
+ ((Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ See if field Day of an EFI_TIME is correct.
+
+ @param Time Its Day field is to be checked.
+
+ @retval TRUE Day field of Time is correct.
+ @retval FALSE Day field of Time is NOT correct.
+**/
+BOOLEAN
+DayValid (
+ IN EFI_TIME *Time
+ )
+{
+ INTN DayOfMonth[12];
+
+ DayOfMonth[0] = 31;
+ DayOfMonth[1] = 29;
+ DayOfMonth[2] = 31;
+ DayOfMonth[3] = 30;
+ DayOfMonth[4] = 31;
+ DayOfMonth[5] = 30;
+ DayOfMonth[6] = 31;
+ DayOfMonth[7] = 31;
+ DayOfMonth[8] = 30;
+ DayOfMonth[9] = 31;
+ DayOfMonth[10] = 30;
+ DayOfMonth[11] = 31;
+
+ //
+ // The validity of Time->Month field should be checked before
+ //
+ ASSERT (Time->Month >=1);
+ ASSERT (Time->Month <=12);
+ if (Time->Day < 1 ||
+ Time->Day > DayOfMonth[Time->Month - 1] ||
+ (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
+ ) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Check if it is a leap year.
+
+ @param Time The time to be checked.
+
+ @retval TRUE It is a leap year.
+ @retval FALSE It is NOT a leap year.
+**/
+BOOLEAN
+IsLeapYear (
+ IN EFI_TIME *Time
+ )
+{
+ if (Time->Year % 4 == 0) {
+ if (Time->Year % 100 == 0) {
+ if (Time->Year % 400 == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Converts time from EFI_TIME format defined by UEFI spec to RTC's.
+
+ This function converts time from EFI_TIME format defined by UEFI spec to RTC's.
+ If data mode of RTC is BCD, then converts EFI_TIME to it.
+ If RTC is in 12-hour format, then converts EFI_TIME to it.
+
+ @param Time On input, the time data read from UEFI to convert
+ On output, the time converted to RTC format
+ @param RegisterB Value of Register B of RTC, indicating data mode
+ @param Century It is set according to EFI_TIME Time.
+
+**/
+VOID
+ConvertEfiTimeToRtcTime (
+ IN OUT EFI_TIME *Time,
+ IN RTC_REGISTER_B RegisterB,
+ OUT UINT8 *Century
+ )
+{
+ BOOLEAN IsPM;
+
+ IsPM = TRUE;
+ //
+ // Adjust hour field if RTC is in 12 hour mode
+ //
+ if (RegisterB.Bits.Mil == 0) {
+ if (Time->Hour < 12) {
+ IsPM = FALSE;
+ }
+
+ if (Time->Hour >= 13) {
+ Time->Hour = (UINT8) (Time->Hour - 12);
+ } else if (Time->Hour == 0) {
+ Time->Hour = 12;
+ }
+ }
+ //
+ // Set the Time/Date/Daylight Savings values.
+ //
+ *Century = DecimalToBcd8 ((UINT8) (Time->Year / 100));
+
+ Time->Year = (UINT16) (Time->Year % 100);
+
+ if (RegisterB.Bits.Dm == 0) {
+ Time->Year = DecimalToBcd8 ((UINT8) Time->Year);
+ Time->Month = DecimalToBcd8 (Time->Month);
+ Time->Day = DecimalToBcd8 (Time->Day);
+ Time->Hour = DecimalToBcd8 (Time->Hour);
+ Time->Minute = DecimalToBcd8 (Time->Minute);
+ Time->Second = DecimalToBcd8 (Time->Second);
+ }
+ //
+ // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.
+ //
+ if (RegisterB.Bits.Mil == 0 && IsPM) {
+ Time->Hour = (UINT8) (Time->Hour | 0x80);
+ }
+}
+
+/**
+ Compare the Hour, Minute and Second of the From time and the To time.
+
+ Only compare H/M/S in EFI_TIME and ignore other fields here.
+
+ @param From the first time
+ @param To the second time
+
+ @return >0 The H/M/S of the From time is later than those of To time
+ @return ==0 The H/M/S of the From time is same as those of To time
+ @return <0 The H/M/S of the From time is earlier than those of To time
+**/
+INTN
+CompareHMS (
+ IN EFI_TIME *From,
+ IN EFI_TIME *To
+ )
+{
+ if ((From->Hour > To->Hour) ||
+ ((From->Hour == To->Hour) && (From->Minute > To->Minute)) ||
+ ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second > To->Second))) {
+ return 1;
+ } else if ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second == To->Second)) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+/**
+ To check if second date is later than first date within 24 hours.
+
+ @param From the first date
+ @param To the second date
+
+ @retval TRUE From is previous to To within 24 hours.
+ @retval FALSE From is later, or it is previous to To more than 24 hours.
+**/
+BOOLEAN
+IsWithinOneDay (
+ IN EFI_TIME *From,
+ IN EFI_TIME *To
+ )
+{
+ UINT8 DayOfMonth[12];
+ BOOLEAN Adjacent;
+
+ DayOfMonth[0] = 31;
+ DayOfMonth[1] = 29;
+ DayOfMonth[2] = 31;
+ DayOfMonth[3] = 30;
+ DayOfMonth[4] = 31;
+ DayOfMonth[5] = 30;
+ DayOfMonth[6] = 31;
+ DayOfMonth[7] = 31;
+ DayOfMonth[8] = 30;
+ DayOfMonth[9] = 31;
+ DayOfMonth[10] = 30;
+ DayOfMonth[11] = 31;
+
+ Adjacent = FALSE;
+
+ //
+ // The validity of From->Month field should be checked before
+ //
+ ASSERT (From->Month >=1);
+ ASSERT (From->Month <=12);
+
+ if (From->Year == To->Year) {
+ if (From->Month == To->Month) {
+ if ((From->Day + 1) == To->Day) {
+ if ((CompareHMS(From, To) >= 0)) {
+ Adjacent = TRUE;
+ }
+ } else if (From->Day == To->Day) {
+ if ((CompareHMS(From, To) <= 0)) {
+ Adjacent = TRUE;
+ }
+ }
+ } else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {
+ if ((From->Month == 2) && !IsLeapYear(From)) {
+ if (From->Day == 28) {
+ if ((CompareHMS(From, To) >= 0)) {
+ Adjacent = TRUE;
+ }
+ }
+ } else if (From->Day == DayOfMonth[From->Month - 1]) {
+ if ((CompareHMS(From, To) >= 0)) {
+ Adjacent = TRUE;
+ }
+ }
+ }
+ } else if (((From->Year + 1) == To->Year) &&
+ (From->Month == 12) &&
+ (From->Day == 31) &&
+ (To->Month == 1) &&
+ (To->Day == 1)) {
+ if ((CompareHMS(From, To) >= 0)) {
+ Adjacent = TRUE;
+ }
+ }
+
+ return Adjacent;
+}
+
diff --git a/QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf b/QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
new file mode 100644
index 0000000..1e97818
--- /dev/null
+++ b/QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
@@ -0,0 +1,82 @@
+## @file
+#
+# PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL.
+#
+# This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.
+# It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PcRtc
+ FILE_GUID = 378D7B65-8DA9-4773-B6E4-A47826A833E1
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializePcRtc
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ ../../../../PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
+ PcRtc.c
+ ../../../../PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ UefiRuntimeLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ TimerLib
+ IoLib
+ BaseMemoryLib
+ UefiLib
+ DebugLib
+ BaseLib
+ PcdLib
+ ReportStatusCodeLib
+
+[Protocols]
+ gEfiRealTimeClockArchProtocolGuid ## PRODUCES
+
+[Depex]
+ gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdRealTimeClockUpdateTimeout ## CONSUMES \ No newline at end of file
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TisPc.c b/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TisPc.c
new file mode 100644
index 0000000..2992b20
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TisPc.c
@@ -0,0 +1,222 @@
+/** @file
+ Basic TIS (TPM Interface Specification) functions.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/GlobalNvsArea.h>
+#include "TpmAccess.h"
+
+/**
+ Check whether TPM chip exist and update ACPI memory region.
+
+ @param[in] TisReg Pointer to TIS register.
+
+ @retval TRUE TPM chip exists.
+ @retval FALSE TPM chip is not found.
+**/
+BOOLEAN
+TisPcPresenceCheck (
+ IN TIS_PC_REGISTERS_PTR TisReg
+ )
+{
+ UINT8 RegRead;
+ EFI_STATUS Status;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsAreaProtocol;
+ EFI_GLOBAL_NVS_AREA *GlobalNvsAreaPtr = NULL;
+
+ //
+ // Get Global NVS Area Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiGlobalNvsAreaProtocolGuid, NULL, (VOID **)&GlobalNvsAreaProtocol);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TisPcPresenceCheck(): Could not locate GlobalNvsAreaProtocol\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+ GlobalNvsAreaPtr = GlobalNvsAreaProtocol->Area;
+
+ RegRead = TpmReadByte ((UINTN)&TisReg->Access);
+
+ if ((RegRead != (UINT8)-1)) {
+ GlobalNvsAreaPtr->TpmPresent = TRUE;
+ } else {
+ GlobalNvsAreaPtr->TpmPresent = FALSE;
+ }
+
+ return (BOOLEAN)(RegRead != (UINT8)-1);
+}
+
+/**
+ Check whether the value of a TPM chip register satisfies the input BIT setting.
+
+ @param[in] Register Address port of register to be checked.
+ @param[in] BitSet Check these data bits are set.
+ @param[in] BitClear Check these data bits are clear.
+ @param[in] TimeOut The max wait time (unit MicroSecond) when checking register.
+
+ @retval EFI_SUCCESS The register satisfies the check bit.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+**/
+EFI_STATUS
+EFIAPI
+TisPcWaitRegisterBits (
+ IN UINT8 *Register,
+ IN UINT8 BitSet,
+ IN UINT8 BitClear,
+ IN UINT32 TimeOut
+ )
+{
+ UINT8 RegRead;
+ UINT32 WaitTime;
+
+ for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30){
+ RegRead = TpmReadByte ((UINTN)Register);
+ if ((RegRead & BitSet) == BitSet && (RegRead & BitClear) == 0)
+ return EFI_SUCCESS;
+ MicroSecondDelay (30);
+ }
+ return EFI_TIMEOUT;
+}
+
+/**
+ Get BurstCount by reading the burstCount field of a TIS regiger
+ in the time of default TIS_TIMEOUT_D.
+
+ @param[in] TisReg Pointer to TIS register.
+ @param[out] BurstCount Pointer to a buffer to store the got BurstConut.
+
+ @retval EFI_SUCCESS Get BurstCount.
+ @retval EFI_INVALID_PARAMETER TisReg is NULL or BurstCount is NULL.
+ @retval EFI_TIMEOUT BurstCount can't be got in time.
+**/
+EFI_STATUS
+EFIAPI
+TisPcReadBurstCount (
+ IN TIS_PC_REGISTERS_PTR TisReg,
+ OUT UINT16 *BurstCount
+ )
+{
+ UINT32 WaitTime;
+ UINT8 DataByte0;
+ UINT8 DataByte1;
+
+ if (BurstCount == NULL || TisReg == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ WaitTime = 0;
+ do {
+ //
+ // TIS_PC_REGISTERS_PTR->burstCount is UINT16, but it is not 2bytes aligned,
+ // so it needs to use TpmReadByte to read two times
+ //
+ DataByte0 = TpmReadByte ((UINTN)&TisReg->BurstCount);
+ DataByte1 = TpmReadByte ((UINTN)&TisReg->BurstCount + 1);
+ *BurstCount = (UINT16)((DataByte1 << 8) + DataByte0);
+ if (*BurstCount != 0) {
+ return EFI_SUCCESS;
+ }
+ MicroSecondDelay (30);
+ WaitTime += 30;
+ } while (WaitTime < TIS_TIMEOUT_D);
+
+ return EFI_TIMEOUT;
+}
+
+/**
+ Set TPM chip to ready state by sending ready command TIS_PC_STS_READY
+ to Status Register in time.
+
+ @param[in] TisReg Pointer to TIS register.
+
+ @retval EFI_SUCCESS TPM chip enters into ready state.
+ @retval EFI_INVALID_PARAMETER TisReg is NULL.
+ @retval EFI_TIMEOUT TPM chip can't be set to ready state in time.
+**/
+EFI_STATUS
+EFIAPI
+TisPcPrepareCommand (
+ IN TIS_PC_REGISTERS_PTR TisReg
+ )
+{
+ EFI_STATUS Status;
+
+ if (TisReg == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TpmWriteByte ((UINTN)&TisReg->Status, TIS_PC_STS_READY);
+ Status = TisPcWaitRegisterBits (
+ &TisReg->Status,
+ TIS_PC_STS_READY,
+ 0,
+ TIS_TIMEOUT_B
+ );
+ return Status;
+}
+
+/**
+ Get the control of TPM chip by sending requestUse command TIS_PC_ACC_RQUUSE
+ to ACCESS Register in the time of default TIS_TIMEOUT_D.
+
+ @param[in] TisReg Pointer to TIS register.
+
+ @retval EFI_SUCCESS Get the control of TPM chip.
+ @retval EFI_INVALID_PARAMETER TisReg is NULL.
+ @retval EFI_NOT_FOUND TPM chip doesn't exit.
+ @retval EFI_TIMEOUT Can't get the TPM control in time.
+**/
+EFI_STATUS
+EFIAPI
+TisPcRequestUseTpm (
+ IN TIS_PC_REGISTERS_PTR TisReg
+ )
+{
+ EFI_STATUS Status;
+
+ if (TisReg == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!TisPcPresenceCheck (TisReg)) {
+ return EFI_NOT_FOUND;
+ }
+
+ TpmWriteByte ((UINTN)&TisReg->Access, TIS_PC_ACC_RQUUSE);
+ Status = TisPcWaitRegisterBits (
+ &TisReg->Access,
+ (UINT8)(TIS_PC_ACC_ACTIVE |TIS_PC_VALID),
+ 0,
+ TIS_TIMEOUT_D
+ );
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmAccess.c b/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmAccess.c
new file mode 100644
index 0000000..e1d3ae6
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmAccess.c
@@ -0,0 +1,324 @@
+/** @file
+ TPM Generic Write/Read Access routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+#include "TpmAccess.h"
+
+//
+// Global variable to cache pointer to I2C protocol.
+//
+EFI_I2C_HC_PROTOCOL *mI2Cbus = NULL;
+
+//
+// Global variable to indicate if TPM I2C Read Transfer has previously occurred.
+//
+BOOLEAN mI2CPrevReadTransfer = FALSE;
+
+
+/**
+ Maps a standard TCG MMIO address (offset to Locality 0)
+ to Infineon SLB9645 TPM I2C Address.
+
+ @param MMIO Address to map.
+
+ @return Mapped Infineon SLB9645 TPM I2C Address.
+
+**/
+UINTN
+MapMmioAddr2InfI2CAddr (
+ IN UINTN Address
+ )
+{
+ UINTN TpmAddress;
+
+ switch (Address) {
+ case (TPM_MMIO_BASE_ADDRESS+TPM_ACCESS_0_ADDRESS_DEFAULT):
+ TpmAddress = INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT;
+ break;
+ case (TPM_MMIO_BASE_ADDRESS+TPM_STS_0_ADDRESS_DEFAULT):
+ TpmAddress = INFINEON_TPM_STS_0_ADDRESS_DEFAULT;
+ break;
+ case (TPM_MMIO_BASE_ADDRESS+TPM_BURST0_COUNT_0_DEFAULT):
+ TpmAddress = INFINEON_TPM_BURST0_COUNT_0_DEFAULT;
+ break;
+ case (TPM_MMIO_BASE_ADDRESS+TPM_BURST1_COUNT_0_DEFAULT):
+ TpmAddress = INFINEON_TPM_BURST1_COUNT_0_DEFAULT;
+ break;
+ case (TPM_MMIO_BASE_ADDRESS+TPM_DATA_FIFO_0_DEFAULT):
+ TpmAddress = INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT;
+ break;
+ default:
+ TpmAddress = Address;
+ }
+
+ // Assert if TPM Address is not within Infineon SLB9645 Locality 0 address range.
+ ASSERT (TpmAddress >= INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT);
+ ASSERT (TpmAddress <= INFINEON_TPM_DID_VID_0_DEFAULT);
+
+ return TpmAddress;
+}
+
+
+/**
+ Writes single byte data to TPM specified by MMIO address.
+
+ Write access to TPM is MMIO or I2C (based on platform type).
+
+ @param Address The register to write.
+ @param Data The data to write to the register.
+
+**/
+VOID
+TpmWriteByte (
+ IN UINTN Address,
+ IN UINT8 Data
+ )
+{
+ UINTN TpmAddress;
+ UINTN WriteLength;
+ UINT8 WriteData[2];
+
+ EFI_PLATFORM_INFO *PlatformInfo;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr;
+ EFI_I2C_ADDR_MODE I2CAddrMode;
+
+ EFI_STATUS Status;
+
+ //
+ // Get platform type from platform info hob.
+ //
+ GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
+ PlatformInfo = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (PlatformInfo != NULL);
+
+ //
+ // Only Crosshill platform supports TPM via I2C bus.
+ // otherwise do nothing.
+ //
+ if (PlatformInfo->Type == (EFI_PLATFORM_TYPE) CrossHill) {
+ //
+ // Locate I2C protocol for TPM I2C access.
+ //
+ Status = gBS->LocateProtocol (&gEfiI2CHcProtocolGuid, NULL, (VOID**) &mI2Cbus);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TpmWriteByte(): could not locate I2CHcProtocol\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Setup I2C Slave device address and address mode (7-bit).
+ //
+ I2CDeviceAddr.I2CDeviceAddress = TPM_I2C_SLAVE_DEVICE_ADDRESS;
+ I2CAddrMode = EfiI2CSevenBitAddrMode;
+
+ //
+ // As recommended by Infineon (SLB9645 I2C Communication protocol application
+ // note revision 1.0) wait 250 microseconds between a read and a write transfer.
+ //
+ if (mI2CPrevReadTransfer) {
+ MicroSecondDelay (GUARD_TIME);
+ }
+
+ //
+ // Map MMIO address to Infineon I2C address.
+ //
+ TpmAddress = MapMmioAddr2InfI2CAddr (Address);
+
+ //
+ // Write to TPM register.
+ //
+ WriteLength = 2;
+ WriteData[0] = (UINT8)TpmAddress;
+ WriteData[1] = Data;
+
+ Status = mI2Cbus->WriteMultipleByte (
+ mI2Cbus,
+ I2CDeviceAddr,
+ I2CAddrMode,
+ &WriteLength,
+ &WriteData
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TpmWriteByte(): I2C Write to TPM address %0x failed\n", TpmAddress));
+ }
+
+ mI2CPrevReadTransfer = FALSE;
+ }
+}
+
+
+/**
+ Reads single byte data from TPM specified by MMIO address.
+
+ Read access to TPM is via MMIO or I2C (based on platform type).
+
+ Due to stability issues when using I2C combined write/read transfers (with
+ RESTART) to TPM (specifically read from status register), a single write is
+ performed followed by single read (with STOP condition in between).
+
+ @param Address of the MMIO mapped register to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+TpmReadByte (
+ IN UINTN Address
+ )
+{
+ UINTN TpmAddress;
+ UINT8 Data[1];
+ UINT8 ReadData;
+ UINT8 ReadCount;
+
+ EFI_PLATFORM_INFO *PlatformInfo;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr;
+ EFI_I2C_ADDR_MODE I2CAddrMode;
+
+ EFI_STATUS Status;
+
+ ReadData = 0xFF;
+ ReadCount = 0;
+
+ //
+ // Get platform type from platform info hob.
+ //
+ GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
+ PlatformInfo = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (PlatformInfo != NULL);
+
+ //
+ // Only Crosshill platform supports TPM via I2C bus.
+ // Otherwise return 0xff.
+ //
+ if (PlatformInfo->Type == (EFI_PLATFORM_TYPE) CrossHill) {
+ //
+ // Locate I2C protocol for TPM I2C access.
+ //
+ Status = gBS->LocateProtocol (&gEfiI2CHcProtocolGuid, NULL, (VOID**) &mI2Cbus);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TpmReadByte(): could not locate I2CHcProtocol\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Setup I2C Slave device address and address mode (7-bit).
+ //
+ I2CDeviceAddr.I2CDeviceAddress = TPM_I2C_SLAVE_DEVICE_ADDRESS;
+ I2CAddrMode = EfiI2CSevenBitAddrMode;
+
+ //
+ // Map MMIO address to Infineon I2C address.
+ //
+ TpmAddress = MapMmioAddr2InfI2CAddr (Address);
+
+ //
+ // As recommended by Infineon (SLB9645 I2C Communication protocol application
+ // note revision 1.0) retry upto 3 times if TPM status, access or burst count
+ // registers return 0xFF.
+ //
+ while ((ReadData == 0xFF) && (ReadCount < READ_RETRY)) {
+ //
+ // As recommended by Infineon (SLB9645 I2C Communication protocol application
+ // note revision 1.0) wait 250 microseconds between a read and a write transfer.
+ //
+ if (mI2CPrevReadTransfer) {
+ MicroSecondDelay (GUARD_TIME);
+ }
+
+ //
+ // Write addresss to TPM.
+ //
+ Data[0] = (UINT8)TpmAddress;
+ Status = mI2Cbus->WriteByte (
+ mI2Cbus,
+ I2CDeviceAddr,
+ I2CAddrMode,
+ NULL,
+ &Data
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "TpmReadByte(): write to TPM address %0x failed\n", TpmAddress));
+ }
+
+ mI2CPrevReadTransfer = FALSE;
+
+ //
+ // Read data from TPM.
+ //
+ Data[0] = (UINT8)TpmAddress;
+ Status = mI2Cbus->ReadByte (
+ mI2Cbus,
+ I2CDeviceAddr,
+ I2CAddrMode,
+ NULL,
+ &Data
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TpmReadByte(): read from TPM address %0x failed\n", TpmAddress));
+ ReadData = 0xFF;
+ } else {
+ ReadData = Data[0];
+ }
+
+ //
+ // Only need to retry 3 times for TPM status, access, and burst count registers.
+ // If read transfer is to TPM Data FIFO, do not retry, exit loop.
+ //
+ if (TpmAddress == INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT) {
+ ReadCount = READ_RETRY;
+ } else {
+ ReadCount++;
+ }
+
+ mI2CPrevReadTransfer = TRUE;
+ }
+
+ } else {
+ //
+ // Other Quark platforms do not support MMIO access to TPM Device.
+ // return 0xff.
+ //
+ return (0xFF);
+ }
+
+ return ReadData;
+}
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmAccess.h b/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmAccess.h
new file mode 100644
index 0000000..586dd17
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmAccess.h
@@ -0,0 +1,127 @@
+/** @file
+ The intenal header file for TpmAccess routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _TPMACCESS_HEADER_H_
+#define _TPMACCESS_HEADER_H_
+
+#include <Guid/PlatformInfo.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/PlatformType.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/I2CHc.h>
+#include <Guid/HobList.h>
+#include <Platform.h>
+
+
+// Default TPM (Infineon SLB9645) I2C Slave Device Address on Crosshill board.
+#define TPM_I2C_SLAVE_DEVICE_ADDRESS 0x20
+
+// Default TPM MMIO Base Address
+#define TPM_MMIO_BASE_ADDRESS 0xfed40000
+
+// Default TCG MMIO mapped registers (TCG PC CLient TPM Interface Specification).
+#define TPM_ACCESS_0_ADDRESS_DEFAULT 0x0
+#define TPM_STS_0_ADDRESS_DEFAULT 0x18
+#define TPM_BURST0_COUNT_0_DEFAULT 0x19
+#define TPM_BURST1_COUNT_0_DEFAULT 0x1A
+#define TPM_DATA_FIFO_0_DEFAULT 0x24
+
+// Default Infineon SLB9645 TPM I2C mapped registers (SLB9645 I2C Comm. Protocol Application Note).
+#define INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT 0x0
+#define INFINEON_TPM_STS_0_ADDRESS_DEFAULT 0x01
+#define INFINEON_TPM_BURST0_COUNT_0_DEFAULT 0x02
+#define INFINEON_TPM_BURST1_COUNT_0_DEFAULT 0x03
+#define INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT 0x05
+#define INFINEON_TPM_DID_VID_0_DEFAULT 0x09
+
+// Max. retry count for read transfers (as recommended by Infineon).
+#define READ_RETRY 3
+
+// Guard time of 250us between I2C read and next I2C write transfer (as recommended by Infineon).
+#define GUARD_TIME 250
+
+
+/**
+ Maps a standard TCG MMIO address (offset to Locality 0)
+ to Infineon SLB9645 TPM I2C Address.
+
+ @param MMIO Address to map.
+
+ @return Mapped Infineon SLB9645 TPM I2C Address.
+
+**/
+UINTN
+MapMmioAddr2InfI2CAddr (
+ IN UINTN Address
+ );
+
+
+/**
+ Writes single byte data to TPM specified by MMIO address.
+
+ Write access to TPM is MMIO or I2C (based on platform type).
+
+ @param Address The register to write.
+ @param Data The data to write to the register.
+
+**/
+VOID
+TpmWriteByte (
+ IN UINTN Address,
+ IN UINT8 Data
+ );
+
+
+/**
+ Reads single byte data from TPM specified by MMIO address.
+
+ Read access to TPM is via MMIO or I2C (based on platform type).
+
+ Due to stability issues when using I2C combined write/read transfers (with
+ RESTART) to TPM (specifically read from status register), a single write is
+ performed followed by single read (with STOP condition in between).
+
+ @param Address of the MMIO mapped register to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+TpmReadByte (
+ IN UINTN Address
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmCommLib.inf b/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmCommLib.inf
new file mode 100644
index 0000000..4123ca9
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmCommLib.inf
@@ -0,0 +1,78 @@
+## @file
+# TpmCommLib instance implements basis TPM Interface Specification (TIS) and TPM command functions.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TpmCommLib
+ FILE_GUID = 7d9fe32e-a6a9-4cdf-abff-10cc7f22e1c9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TpmCommLib|DXE_DRIVER UEFI_DRIVER DXE_SMM_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[Sources]
+ TisPc.c
+ ../../../../../SecurityPkg/Library/TpmCommLib/TpmComm.c
+ TpmAccess.c
+ TpmAccess.h
+ ../../../../../SecurityPkg/Library/TpmCommLib/CommonHeader.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ IoLib
+ TimerLib
+ BaseCryptLib
+ MemoryAllocationLib
+ DebugLib
+ HobLib
+
+[Guids]
+ gEfiPlatformInfoGuid
+
+[Protocols]
+ gEfiGlobalNvsAreaProtocolGuid
+ gEfiI2CHcProtocolGuid
+
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.c b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.c
new file mode 100644
index 0000000..acc520d
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.c
@@ -0,0 +1,857 @@
+/** @file
+ This module implements TCG EFI Protocol.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiDxe.h>
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/SmBios.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/SmBios.h>
+#include <Guid/HobList.h>
+#include <Guid/TcgEventHob.h>
+#include <Guid/EventGroup.h>
+#include <Guid/EventExitBootServiceFailed.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/TcgService.h>
+#include <Protocol/AcpiTable.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/HobLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TpmCommLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/TimerLib.h>
+#include <Library/ResetSystemLib.h>
+
+#include "TpmComm.h"
+
+#define EFI_TCG_LOG_AREA_SIZE 0x10000
+
+#pragma pack (1)
+
+typedef struct _EFI_TCG_CLIENT_ACPI_TABLE {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT16 PlatformClass;
+ UINT32 Laml;
+ EFI_PHYSICAL_ADDRESS Lasa;
+} EFI_TCG_CLIENT_ACPI_TABLE;
+
+typedef struct _EFI_TCG_SERVER_ACPI_TABLE {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT16 PlatformClass;
+ UINT16 Reserved0;
+ UINT64 Laml;
+ EFI_PHYSICAL_ADDRESS Lasa;
+ UINT16 SpecRev;
+ UINT8 DeviceFlags;
+ UINT8 InterruptFlags;
+ UINT8 Gpe;
+ UINT8 Reserved1[3];
+ UINT32 GlobalSysInt;
+ EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE BaseAddress;
+ UINT32 Reserved2;
+ EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE ConfigAddress;
+ UINT8 PciSegNum;
+ UINT8 PciBusNum;
+ UINT8 PciDevNum;
+ UINT8 PciFuncNum;
+} EFI_TCG_SERVER_ACPI_TABLE;
+
+#pragma pack ()
+
+#define TCG_DXE_DATA_FROM_THIS(this) \
+ BASE_CR (this, TCG_DXE_DATA, TcgProtocol)
+
+typedef struct _TCG_DXE_DATA {
+ EFI_TCG_PROTOCOL TcgProtocol;
+ TCG_EFI_BOOT_SERVICE_CAPABILITY BsCap;
+ EFI_TCG_CLIENT_ACPI_TABLE *TcgClientAcpiTable;
+ EFI_TCG_SERVER_ACPI_TABLE *TcgServerAcpiTable;
+ UINTN EventLogSize;
+ UINT8 *LastEvent;
+ TIS_TPM_HANDLE TpmHandle;
+} TCG_DXE_DATA;
+
+
+
+EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate = {
+ {
+ EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,
+ sizeof (mTcgClientAcpiTemplate),
+ 0x02 //Revision
+ //
+ // Compiler initializes the remaining bytes to 0
+ // These fields should be filled in in production
+ //
+ },
+ 0, // 0 for PC Client Platform Class
+ 0, // Log Area Max Length
+ (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1) // Log Area Start Address
+};
+
+//
+// The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,
+// the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,
+// this _UID can be changed and should match with the _UID setting of the TPM
+// ACPI device object
+//
+EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate = {
+ {
+ EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,
+ sizeof (mTcgServerAcpiTemplate),
+ 0x02 //Revision
+ //
+ // Compiler initializes the remaining bytes to 0
+ // These fields should be filled in in production
+ //
+ },
+ 1, // 1 for Server Platform Class
+ 0, // Reserved
+ 0, // Log Area Max Length
+ (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address
+ 0x0100, // TCG Specification revision 1.0
+ 2, // Device Flags
+ 0, // Interrupt Flags
+ 0, // GPE
+ {0}, // Reserved 3 bytes
+ 0, // Global System Interrupt
+ {
+ EFI_ACPI_3_0_SYSTEM_MEMORY,
+ 0,
+ 0,
+ EFI_ACPI_3_0_BYTE,
+ TPM_BASE_ADDRESS // Base Address
+ },
+ 0, // Reserved
+ {0}, // Configuration Address
+ 0xFF, // ACPI _UID value of the device, can be changed for different platforms
+ 0, // ACPI _UID value of the device, can be changed for different platforms
+ 0, // ACPI _UID value of the device, can be changed for different platforms
+ 0 // ACPI _UID value of the device, can be changed for different platforms
+};
+
+UINTN mBootAttempts = 0;
+CHAR16 mBootVarName[] = L"BootOrder";
+
+/**
+ This service provides EFI protocol capability information, state information
+ about the TPM, and Event Log state information.
+
+ @param[in] This Indicates the calling context
+ @param[out] ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY
+ structure and fills in the fields with the EFI protocol
+ capability information and the current TPM state information.
+ @param[out] TCGFeatureFlags This is a pointer to the feature flags. No feature
+ flags are currently defined so this parameter
+ MUST be set to 0. However, in the future,
+ feature flags may be defined that, for example,
+ enable hash algorithm agility.
+ @param[out] EventLogLocation This is a pointer to the address of the event log in memory.
+ @param[out] EventLogLastEntry If the Event Log contains more than one entry,
+ this is a pointer to the address of the start of
+ the last entry in the event log in memory.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER ProtocolCapability does not match TCG capability.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeStatusCheck (
+ IN EFI_TCG_PROTOCOL *This,
+ OUT TCG_EFI_BOOT_SERVICE_CAPABILITY *ProtocolCapability,
+ OUT UINT32 *TCGFeatureFlags,
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry
+ )
+{
+ TCG_DXE_DATA *TcgData;
+
+ TcgData = TCG_DXE_DATA_FROM_THIS (This);
+
+ if (ProtocolCapability != NULL) {
+ *ProtocolCapability = TcgData->BsCap;
+ }
+
+ if (TCGFeatureFlags != NULL) {
+ *TCGFeatureFlags = 0;
+ }
+
+ if (EventLogLocation != NULL) {
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
+ *EventLogLocation = TcgData->TcgClientAcpiTable->Lasa;
+ } else {
+ *EventLogLocation = TcgData->TcgServerAcpiTable->Lasa;
+ }
+ }
+
+ if (EventLogLastEntry != NULL) {
+ if (TcgData->BsCap.TPMDeactivatedFlag) {
+ *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;
+ } else {
+ *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)TcgData->LastEvent;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This service abstracts the capability to do a hash operation on a data buffer.
+
+ @param[in] This Indicates the calling context
+ @param[in] HashData Pointer to the data buffer to be hashed
+ @param[in] HashDataLen Length of the data buffer to be hashed
+ @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
+ @param[in, out] HashedDataLen Resultant length of the hashed data
+ @param[in, out] HashedDataResult Resultant buffer of the hashed data
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER HashDataLen is NULL.
+ @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.
+ @retval EFI_UNSUPPORTED AlgorithmId not supported.
+ @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeHashAll (
+ IN EFI_TCG_PROTOCOL *This,
+ IN UINT8 *HashData,
+ IN UINT64 HashDataLen,
+ IN TCG_ALGORITHM_ID AlgorithmId,
+ IN OUT UINT64 *HashedDataLen,
+ IN OUT UINT8 **HashedDataResult
+ )
+{
+ if (HashedDataLen == NULL || HashedDataResult == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (AlgorithmId) {
+ case TPM_ALG_SHA:
+ if (*HashedDataLen == 0) {
+ *HashedDataLen = sizeof (TPM_DIGEST);
+ *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);
+ if (*HashedDataResult == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ if (*HashedDataLen < sizeof (TPM_DIGEST)) {
+ *HashedDataLen = sizeof (TPM_DIGEST);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *HashedDataLen = sizeof (TPM_DIGEST);
+
+ if (*HashedDataResult == NULL) {
+ *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);
+ }
+
+ return TpmCommHashAll (
+ HashData,
+ (UINTN) HashDataLen,
+ (TPM_DIGEST*)*HashedDataResult
+ );
+ default:
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Add a new entry to the Event Log.
+
+ @param[in] TcgData TCG_DXE_DATA structure.
+ @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
+EFIAPI
+TcgDxeLogEventI (
+ IN TCG_DXE_DATA *TcgData,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ )
+{
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
+ TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgClientAcpiTable->Lasa;
+ return TpmCommLogEvent (
+ &TcgData->LastEvent,
+ &TcgData->EventLogSize,
+ (UINTN)TcgData->TcgClientAcpiTable->Laml,
+ NewEventHdr,
+ NewEventData
+ );
+ } else {
+ TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgServerAcpiTable->Lasa;
+ return TpmCommLogEvent (
+ &TcgData->LastEvent,
+ &TcgData->EventLogSize,
+ (UINTN)TcgData->TcgServerAcpiTable->Laml,
+ NewEventHdr,
+ NewEventData
+ );
+ }
+}
+
+/**
+ This service abstracts the capability to add an entry to the Event Log.
+
+ @param[in] This Indicates the calling context
+ @param[in] TCGLogData Pointer to the start of the data buffer containing
+ the TCG_PCR_EVENT data structure. All fields in
+ this structure are properly filled by the caller.
+ @param[in, out] EventNumber The event number of the event just logged
+ @param[in] Flags Indicate additional flags. Only one flag has been
+ defined at this time, which is 0x01 and means the
+ extend operation should not be performed. All
+ other bits are reserved.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeLogEvent (
+ IN EFI_TCG_PROTOCOL *This,
+ IN TCG_PCR_EVENT *TCGLogData,
+ IN OUT UINT32 *EventNumber,
+ IN UINT32 Flags
+ )
+{
+ TCG_DXE_DATA *TcgData;
+
+ TcgData = TCG_DXE_DATA_FROM_THIS (This);
+
+ if (TcgData->BsCap.TPMDeactivatedFlag) {
+ return EFI_DEVICE_ERROR;
+ }
+ return TcgDxeLogEventI (
+ TcgData,
+ (TCG_PCR_EVENT_HDR*)TCGLogData,
+ TCGLogData->Event
+ );
+}
+
+/**
+ This service is a proxy for commands to the TPM.
+
+ @param[in] This Indicates the calling context
+ @param[in] TpmInputParameterBlockSize Size of the TPM input parameter block
+ @param[in] TpmInputParameterBlock Pointer to the TPM input parameter block
+ @param[in] TpmOutputParameterBlockSize Size of the TPM output parameter block
+ @param[in] TpmOutputParameterBlock Pointer to the TPM output parameter block
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid ordinal.
+ @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK.
+ @retval EFI_TIMEOUT The TIS timed-out.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxePassThroughToTpm (
+ IN EFI_TCG_PROTOCOL *This,
+ IN UINT32 TpmInputParameterBlockSize,
+ IN UINT8 *TpmInputParameterBlock,
+ IN UINT32 TpmOutputParameterBlockSize,
+ IN UINT8 *TpmOutputParameterBlock
+ )
+{
+ TCG_DXE_DATA *TcgData;
+
+ TcgData = TCG_DXE_DATA_FROM_THIS (This);
+
+ return TisPcExecute (
+ TcgData->TpmHandle,
+ "%r%/%r",
+ TpmInputParameterBlock,
+ (UINTN) TpmInputParameterBlockSize,
+ TpmOutputParameterBlock,
+ (UINTN) TpmOutputParameterBlockSize
+ );
+}
+
+/**
+ Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
+ and add an entry to the Event Log.
+
+ @param[in] TcgData TCG_DXE_DATA structure.
+ @param[in] HashData Physical address of the start of the data buffer
+ to be hashed, extended, and logged.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
+ @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeHashLogExtendEventI (
+ IN TCG_DXE_DATA *TcgData,
+ IN UINT8 *HashData,
+ IN UINT64 HashDataLen,
+ IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ )
+{
+ EFI_STATUS Status;
+
+ if (HashDataLen > 0) {
+ Status = TpmCommHashAll (
+ HashData,
+ (UINTN) HashDataLen,
+ &NewEventHdr->Digest
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = TpmCommExtend (
+ TcgData->TpmHandle,
+ &NewEventHdr->Digest,
+ NewEventHdr->PCRIndex,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = TcgDxeLogEventI (TcgData, NewEventHdr, NewEventData);
+ }
+
+ return Status;
+}
+
+/**
+ This service abstracts the capability to do a hash operation on a data buffer,
+ extend a specific TPM PCR with the hash result, and add an entry to the Event Log
+
+ @param[in] This Indicates the calling context
+ @param[in] HashData Physical address of the start of the data buffer
+ to be hashed, extended, and logged.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
+ @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
+ @param[in, out] TCGLogData The physical address of the start of the data
+ buffer containing the TCG_PCR_EVENT data structure.
+ @param[in, out] EventNumber The event number of the event just logged.
+ @param[out] EventLogLastEntry Physical address of the first byte of the entry
+ just placed in the Event Log. If the Event Log was
+ empty when this function was called then this physical
+ address will be the same as the physical address of
+ the start of the Event Log.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.
+ @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeHashLogExtendEvent (
+ IN EFI_TCG_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS HashData,
+ IN UINT64 HashDataLen,
+ IN TPM_ALGORITHM_ID AlgorithmId,
+ IN OUT TCG_PCR_EVENT *TCGLogData,
+ IN OUT UINT32 *EventNumber,
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry
+ )
+{
+ TCG_DXE_DATA *TcgData;
+
+ TcgData = TCG_DXE_DATA_FROM_THIS (This);
+
+ if (TcgData->BsCap.TPMDeactivatedFlag) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (AlgorithmId != TPM_ALG_SHA) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return TcgDxeHashLogExtendEventI (
+ TcgData,
+ (UINT8 *) (UINTN) HashData,
+ HashDataLen,
+ (TCG_PCR_EVENT_HDR*)TCGLogData,
+ TCGLogData->Event
+ );
+}
+
+TCG_DXE_DATA mTcgDxeData = {
+ {
+ TcgDxeStatusCheck,
+ TcgDxeHashAll,
+ TcgDxeLogEvent,
+ TcgDxePassThroughToTpm,
+ TcgDxeHashLogExtendEvent
+ },
+ {
+ sizeof (mTcgDxeData.BsCap),
+ { 1, 2, 0, 0 },
+ { 1, 2, 0, 0 },
+ 1,
+ TRUE,
+ FALSE
+ },
+ &mTcgClientAcpiTemplate,
+ &mTcgServerAcpiTemplate,
+ 0,
+ NULL,
+ NULL
+};
+
+/**
+ Initialize the Event Log and log events passed from the PEI phase.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupEventLog (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ TCG_PCR_EVENT *TcgEvent;
+ EFI_PEI_HOB_POINTERS GuidHob;
+ EFI_PHYSICAL_ADDRESS Lasa;
+
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
+ Lasa = mTcgClientAcpiTemplate.Lasa;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (EFI_TCG_LOG_AREA_SIZE),
+ &Lasa
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mTcgClientAcpiTemplate.Lasa = Lasa;
+ //
+ // To initialize them as 0xFF is recommended
+ // because the OS can know the last entry for that.
+ //
+ SetMem ((VOID *)(UINTN)mTcgClientAcpiTemplate.Lasa, EFI_TCG_LOG_AREA_SIZE, 0xFF);
+ mTcgClientAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;
+
+ } else {
+ Lasa = mTcgServerAcpiTemplate.Lasa;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (EFI_TCG_LOG_AREA_SIZE),
+ &Lasa
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mTcgServerAcpiTemplate.Lasa = Lasa;
+ //
+ // To initialize them as 0xFF is recommended
+ // because the OS can know the last entry for that.
+ //
+ SetMem ((VOID *)(UINTN)mTcgServerAcpiTemplate.Lasa, EFI_TCG_LOG_AREA_SIZE, 0xFF);
+ mTcgServerAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;
+ }
+
+ GuidHob.Raw = GetHobList ();
+ while (!EFI_ERROR (Status) &&
+ (GuidHob.Raw = GetNextGuidHob (&gTcgEventEntryHobGuid, GuidHob.Raw)) != NULL) {
+ TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid);
+ GuidHob.Raw = GET_NEXT_HOB (GuidHob);
+ Status = TcgDxeLogEventI (
+ &mTcgDxeData,
+ (TCG_PCR_EVENT_HDR*)TcgEvent,
+ TcgEvent->Event
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Install TCG ACPI Table when ACPI Table Protocol is available.
+
+ A system's firmware uses an ACPI table to identify the system's TCG capabilities
+ to the Post-Boot environment. The information in this ACPI table is not guaranteed
+ to be valid until the Host Platform transitions from pre-boot state to post-boot state.
+
+ @param[in] Event Event whose notification function is being invoked
+ @param[in] Context Pointer to the notification function's context
+**/
+VOID
+EFIAPI
+InstallAcpiTable (
+ IN EFI_EVENT Event,
+ IN VOID* Context
+ )
+{
+ UINTN TableKey;
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ UINT8 Checksum;
+
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
+
+ //
+ // The ACPI table must be checksumed before calling the InstallAcpiTable()
+ // service of the ACPI table protocol to install it.
+ //
+ Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));
+ mTcgClientAcpiTemplate.Header.Checksum = Checksum;
+
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ &mTcgClientAcpiTemplate,
+ sizeof (mTcgClientAcpiTemplate),
+ &TableKey
+ );
+ } else {
+
+ //
+ // The ACPI table must be checksumed before calling the InstallAcpiTable()
+ // service of the ACPI table protocol to install it.
+ //
+ Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));
+ mTcgServerAcpiTemplate.Header.Checksum = Checksum;
+
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ &mTcgServerAcpiTemplate,
+ sizeof (mTcgServerAcpiTemplate),
+ &TableKey
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+ Get TPM Deactivated state.
+
+ @param[out] TPMDeactivatedFlag Returns TPM Deactivated state.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+GetTpmStatus (
+ OUT BOOLEAN *TPMDeactivatedFlag
+ )
+{
+ EFI_STATUS Status;
+ TPM_STCLEAR_FLAGS VFlags;
+
+ Status = TpmCommGetFlags (
+ mTcgDxeData.TpmHandle,
+ TPM_CAP_FLAG_VOLATILE,
+ &VFlags,
+ sizeof (VFlags)
+ );
+ if (!EFI_ERROR (Status)) {
+ *TPMDeactivatedFlag = VFlags.deactivated;
+ }
+
+ return Status;
+}
+
+/**
+ The driver's entry point.
+
+ If TPM is present and available, TPM is Enabled+Activated (if not
+ activated already) by default (without any user confirmation).
+ A reset is performed once after successful activation of TPM to ensure
+ TPM state change takes effect. Also EFI TCG Protocols are published.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ VOID *Registration;
+ TPM_RESULT TpmResponse;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // If TPM not supported by default in build then return.
+ //
+ if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check if TPM is present and issue request to use TPM.
+ //
+ mTcgDxeData.TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;
+ Status = TisPcRequestUseTpm (mTcgDxeData.TpmHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_WARN, "TPM not detected!\n"));
+ return Status;
+ }
+
+ //
+ // Check current boot mode.
+ //
+ BootMode = GetBootModeHob();
+
+ //
+ // Issue Startup command to TPM.
+ //
+ TpmResponse = TpmCommStartup (mTcgDxeData.TpmHandle, BootMode);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Could not start the TPM!, TPM Response = %0x (hex)\n", TpmResponse));
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ }
+
+ //
+ // Issue SelfTest command to TPM (selftest is optional on S3 path, skip it to save S3 time).
+ //
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ TpmResponse = TpmCommContinueSelfTest (mTcgDxeData.TpmHandle);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "TPM Continue Selftests command failed, TPM Response = %0x (hex)\n", TpmResponse));
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ }
+
+ //
+ // Check that selftests have completed successfully.
+ // Wait 2ms to ensure selftests finished (Infineon SLB9645 spec. states ~1.2ms max).
+ //
+ MicroSecondDelay (2000);
+ TpmResponse = TpmCommGetSelfTestResult (mTcgDxeData.TpmHandle);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "TPM Selftests failed, TPM Response = %0x (hex)\n", TpmResponse));
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ }
+ }
+
+ //
+ // Get status of TPM Deactivated Flag.
+ //
+ Status = GetTpmStatus (&mTcgDxeData.BsCap.TPMDeactivatedFlag);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "Line %d in file " __FILE__ ":\n "
+ "DriverEntry: TPM not working properly\n",
+ __LINE__
+ ));
+ return Status;
+ }
+
+ //
+ // If TPM not activated already, enable+activate TPM by default.
+ //
+ if (mTcgDxeData.BsCap.TPMDeactivatedFlag) {
+ TpmResponse = TpmCommEnableActivate (mTcgDxeData.TpmHandle);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "TPM Enable+Activate command failed, TPM Response = %0x\n", TpmResponse));
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ } else {
+ DEBUG ((EFI_D_INFO, "Rebooting system due to TPM state change: Enabled+Activated\n"));
+ ResetCold();
+ }
+ }
+
+ //
+ // Install TCG DXE protocols
+ //
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gEfiTcgProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mTcgDxeData.TcgProtocol
+ );
+
+ //
+ // Install ACPI Table
+ //
+ EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);
+
+ if (!EFI_ERROR (Status) && !mTcgDxeData.BsCap.TPMDeactivatedFlag) {
+ //
+ // Setup the log area and copy event log from hob list to it
+ //
+ Status = SetupEventLog ();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TPM setup the event log failed, Status = %r\n", Status));
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
new file mode 100644
index 0000000..d1b25e9
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
@@ -0,0 +1,99 @@
+## @file
+# Component file for module TcgDxe.
+# This module will produce TCG protocol and measure boot environment.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TcgDxe
+ FILE_GUID = A5683620-7998-4bb2-A377-1C1E31E1E215
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DriverEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[Sources]
+ TcgDxe.c
+ TisDxe.c
+ TpmComm.c
+ TpmComm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiBootServicesTableLib
+ HobLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ TpmCommLib
+ PrintLib
+ UefiLib
+ PcdLib
+ ResetSystemLib
+
+
+[Guids]
+ gEfiSmbiosTableGuid # ALWAYS_CONSUMED
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED
+ gTcgEventEntryHobGuid
+ gEfiEventReadyToBootGuid
+ gEfiEventExitBootServicesGuid
+ gEventExitBootServicesFailedGuid # ALWAYS_CONSUMED
+
+[Protocols]
+ gEfiTcgProtocolGuid ## PRODUCES
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[FixedPcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass
+ gEfiSecurityPkgTokenSpaceGuid.PcdHideTpmSupport
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdHideTpm
+
+[Depex]
+ gEfiI2CHcProtocolGuid AND gEfiGlobalNvsAreaProtocolGuid
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TisDxe.c b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TisDxe.c
new file mode 100644
index 0000000..c4fe021
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TisDxe.c
@@ -0,0 +1,454 @@
+/** @file
+ TIS (TPM Interface Specification) functions used by TPM Dxe driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <IndustryStandard/Tpm12.h>
+#include <Library/TimerLib.h>
+#include <Library/TpmCommLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include "TpmComm.h"
+
+STATIC UINT8 TpmCommandBuf[TPMCMDBUFLENGTH];
+
+/**
+ Send command to TPM for execution.
+
+ @param[in] TisReg TPM register space base address.
+ @param[in] TpmBuffer Buffer for TPM command data.
+ @param[in] DataLength TPM command data length.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+
+**/
+EFI_STATUS
+TisPcSend (
+ IN TIS_PC_REGISTERS_PTR TisReg,
+ IN UINT8 *TpmBuffer,
+ IN UINT32 DataLength
+ )
+{
+ UINT16 BurstCount;
+ UINT32 Index;
+ EFI_STATUS Status;
+
+ Status = TisPcPrepareCommand (TisReg);
+ if (EFI_ERROR (Status)){
+ DEBUG ((DEBUG_ERROR, "The Tpm not ready!\n"));
+ return Status;
+ }
+ Index = 0;
+ while (Index < DataLength) {
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status)) {
+ return EFI_TIMEOUT;
+ }
+ for (; BurstCount > 0 && Index < DataLength; BurstCount--) {
+ TpmWriteByte ((UINTN) &TisReg->DataFifo, *(TpmBuffer + Index));
+ Index++;
+ }
+ }
+ //
+ // Ensure the Tpm status STS_EXPECT change from 1 to 0
+ //
+ Status = TisPcWaitRegisterBits (
+ &TisReg->Status,
+ (UINT8) TIS_PC_VALID,
+ TIS_PC_STS_EXPECT,
+ TIS_TIMEOUT_C
+ );
+ return Status;
+}
+
+/**
+ Receive response data of last command from TPM.
+
+ @param[in] TisReg TPM register space base address.
+ @param[out] TpmBuffer Buffer for response data.
+ @param[out] RespSize Response data length.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+ @retval EFI_DEVICE_ERROR Unexpected device status.
+ @retval EFI_BUFFER_TOO_SMALL Response data is too long.
+
+**/
+EFI_STATUS
+TisPcReceive (
+ IN TIS_PC_REGISTERS_PTR TisReg,
+ OUT UINT8 *TpmBuffer,
+ OUT UINT32 *RespSize
+ )
+{
+ EFI_STATUS Status;
+ UINT16 BurstCount;
+ UINT32 Index;
+ UINT32 ResponseSize;
+ UINT32 Data32;
+
+ //
+ // Wait for the command completion
+ //
+ Status = TisPcWaitRegisterBits (
+ &TisReg->Status,
+ (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA),
+ 0,
+ TIS_TIMEOUT_B
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Read the response data header and check it
+ //
+ Index = 0;
+ BurstCount = 0;
+ while (Index < sizeof (TPM_RSP_COMMAND_HDR)) {
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status)) {
+ return EFI_TIMEOUT;
+ }
+ for (; BurstCount > 0 ; BurstCount--) {
+ *(TpmBuffer + Index) = TpmReadByte ((UINTN) &TisReg->DataFifo);
+ Index++;
+ if (Index == sizeof (TPM_RSP_COMMAND_HDR))
+ break;
+ }
+ }
+ //
+ // Check the reponse data header (tag,parasize and returncode )
+ //
+ CopyMem (&Data32, (TpmBuffer + 2), sizeof (UINT32));
+ ResponseSize = SwapBytes32 (Data32);
+ *RespSize = ResponseSize;
+ if (ResponseSize == sizeof (TPM_RSP_COMMAND_HDR)) {
+ return EFI_SUCCESS;
+ }
+ if (ResponseSize < sizeof (TPM_RSP_COMMAND_HDR)) {
+ return EFI_DEVICE_ERROR;
+ }
+ if (ResponseSize > TPMCMDBUFLENGTH) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // Continue reading the remaining data
+ //
+ while (Index < ResponseSize) {
+ for (; BurstCount > 0 ; BurstCount--) {
+ *(TpmBuffer + Index) = TpmReadByte ((UINTN) &TisReg->DataFifo);
+ Index++;
+ if (Index == ResponseSize) {
+ return EFI_SUCCESS;
+ }
+ }
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status) && (Index < ResponseSize)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Format TPM command data according to the format control character.
+
+ @param[in] FmtChar Format control character.
+ @param[in, out] ap List of arguments.
+ @param[in] TpmBuffer Buffer for TPM command data.
+ @param[out] DataLength TPM command data length.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid format control character.
+ @retval EFI_BUFFER_TOO_SMALL Buffer too small for command data.
+
+**/
+EFI_STATUS
+TisPcSendV (
+ IN UINT8 FmtChar,
+ IN OUT VA_LIST *ap,
+ UINT8 *TpmBuffer,
+ UINT32 *DataLength
+ )
+{
+ UINT8 DataByte;
+ UINT16 DataWord;
+ UINT32 DataDword;
+ TPM_RQU_COMMAND_HDR TpmCmdHdr;
+ TPM_RQU_COMMAND_HDR *TpmCmdPtr;
+ UINTN Size;
+ UINT8 *Raw;
+
+ switch (FmtChar) {
+
+ case 'b':
+ DataByte = VA_ARG (*ap, UINT8);
+ Raw = &DataByte;
+ Size = sizeof (DataByte);
+ break;
+
+ case 'w':
+ DataWord = VA_ARG (*ap, UINT16);
+ DataWord = SwapBytes16 (DataWord);
+ Raw = (UINT8*)&DataWord;
+ Size = sizeof (DataWord);
+ break;
+
+ case 'd':
+ DataDword = VA_ARG (*ap, UINT32);
+ DataDword = SwapBytes32 (DataDword);
+ Raw = (UINT8*)&DataDword;
+ Size = sizeof (DataDword);
+ break;
+
+ case 'h':
+ TpmCmdPtr = VA_ARG (*ap, TPM_RQU_COMMAND_HDR*);
+ TpmCmdHdr.tag = SwapBytes16 (TpmCmdPtr->tag);
+ TpmCmdHdr.paramSize = SwapBytes32 (TpmCmdPtr->paramSize);
+ TpmCmdHdr.ordinal = SwapBytes32 (TpmCmdPtr->ordinal);
+ Raw = (UINT8*) &TpmCmdHdr;
+ Size = sizeof (TpmCmdHdr);
+ break;
+
+ case 'r':
+ Raw = VA_ARG (*ap, UINT8*);
+ Size = VA_ARG (*ap, UINTN);
+ break;
+
+ case '\0':
+ return EFI_INVALID_PARAMETER;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if(*DataLength + (UINT32) Size > TPMCMDBUFLENGTH) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ CopyMem (TpmBuffer + *DataLength, Raw, Size);
+ *DataLength += (UINT32) Size;
+ return EFI_SUCCESS;
+}
+
+/**
+ Format reponse data according to the format control character.
+
+ @param[in] FmtChar Format control character.
+ @param[in, out] ap List of arguments.
+ @param[out] TpmBuffer Buffer for reponse data.
+ @param[in, out] DataIndex Data offset in reponse data buffer.
+ @param[in] RespSize Response data length.
+ @param[out] DataFinished Reach the end of Response data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid format control character.
+ @retval EFI_BUFFER_TOO_SMALL Buffer too small for command data.
+
+**/
+EFI_STATUS
+TisPcReceiveV (
+ IN UINT8 FmtChar,
+ IN OUT VA_LIST *ap,
+ OUT UINT8 *TpmBuffer,
+ IN OUT UINT32 *DataIndex,
+ IN UINT32 RespSize,
+ OUT BOOLEAN *DataFinished
+ )
+{
+ UINT8 *Raw;
+ TPM_RSP_COMMAND_HDR *TpmRspPtr;
+ UINTN Size;
+
+ Raw = VA_ARG (*ap, UINT8*);
+ switch (FmtChar) {
+
+ case 'b':
+ Size = sizeof (UINT8);
+ break;
+
+ case 'w':
+ Size = sizeof (UINT16);
+ break;
+
+ case 'd':
+ Size = sizeof (UINT32);
+ break;
+
+ case 'h':
+ Size = sizeof (*TpmRspPtr);
+ break;
+
+ case 'r':
+ Size = VA_ARG (*ap, UINTN);
+ if(*DataIndex + (UINT32) Size <= RespSize) {
+ break;
+ }
+ *DataFinished = TRUE;
+ if (*DataIndex >= RespSize) {
+ return EFI_SUCCESS;
+ }
+ CopyMem (Raw, TpmBuffer + *DataIndex, RespSize - *DataIndex);
+ *DataIndex += RespSize - *DataIndex;
+ return EFI_SUCCESS;
+
+ case '\0':
+ return EFI_INVALID_PARAMETER;
+
+ default:
+ return EFI_WARN_UNKNOWN_GLYPH;
+ }
+
+ if(*DataIndex + (UINT32) Size > RespSize) {
+ *DataFinished = TRUE;
+ return EFI_SUCCESS;
+ }
+
+ if( *DataIndex + (UINT32) Size > TPMCMDBUFLENGTH )
+ return EFI_BUFFER_TOO_SMALL;
+
+ CopyMem (Raw, TpmBuffer + *DataIndex, Size);
+ *DataIndex += (UINT32) Size;
+
+ switch (FmtChar) {
+
+ case 'w':
+ *(UINT16*)Raw = SwapBytes16 (*(UINT16*) Raw);
+ break;
+
+ case 'd':
+ *(UINT32*)Raw = SwapBytes32 (*(UINT32*) Raw);
+ break;
+
+ case 'h':
+ TpmRspPtr = (TPM_RSP_COMMAND_HDR*) Raw;
+ TpmRspPtr->tag = SwapBytes16 (TpmRspPtr->tag);
+ TpmRspPtr->paramSize = SwapBytes32 (TpmRspPtr->paramSize);
+ TpmRspPtr->returnCode = SwapBytes32 (TpmRspPtr->returnCode);
+ break;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Send formatted command to TPM for execution and return formatted data from response.
+
+ @param[in] TisReg TPM Handle.
+ @param[in] Fmt Format control string.
+ @param[in] ... The variable argument list.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+
+**/
+EFI_STATUS
+EFIAPI
+TisPcExecute (
+ IN TIS_TPM_HANDLE TisReg,
+ IN CONST CHAR8 *Fmt,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Ap;
+ UINT32 BufSize;
+ UINT32 ResponseSize;
+ BOOLEAN DataFinished;
+
+ VA_START (Ap, Fmt);
+
+ //
+ // Put the formatted command to the TpmCommandBuf
+ //
+ BufSize = 0;
+ while (*Fmt != '\0') {
+ if (*Fmt == '%') Fmt++;
+ if (*Fmt == '/') break;
+ Status = TisPcSendV (*Fmt, &Ap, TpmCommandBuf, &BufSize);
+ if (EFI_ERROR( Status )) {
+ goto Error;
+ }
+ Fmt++;
+ }
+ //
+ // Send the command to TPM
+ //
+ Status = TisPcSend (TisReg, TpmCommandBuf, BufSize);
+ if (EFI_ERROR (Status)) {
+ //
+ // Ensure the TPM state change from "Reception" to "Idle/Ready"
+ //
+ TpmWriteByte ((UINTN) &(((TIS_PC_REGISTERS_PTR) TisReg)->Status), TIS_PC_STS_READY);
+ goto Error;
+ }
+
+ TpmWriteByte ((UINTN) &(((TIS_PC_REGISTERS_PTR) TisReg)->Status), TIS_PC_STS_GO);
+ Fmt++;
+ //
+ // Receive the response data from TPM
+ //
+ ZeroMem (TpmCommandBuf, TPMCMDBUFLENGTH);
+ Status = TisPcReceive (TisReg, TpmCommandBuf, &ResponseSize);
+ //
+ // Ensure the TPM state change from "Execution" or "Completion" to "Idle/Ready"
+ //
+ TpmWriteByte ((UINTN) &(((TIS_PC_REGISTERS_PTR) TisReg)->Status), TIS_PC_STS_READY);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // Get the formatted data from the TpmCommandBuf.
+ //
+ BufSize =0;
+ DataFinished = FALSE;
+ while (*Fmt != '\0') {
+ if (*Fmt == '%') {
+ Fmt++;
+ }
+ Status = TisPcReceiveV (*Fmt, &Ap, TpmCommandBuf, &BufSize, ResponseSize, &DataFinished);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ if (DataFinished) {
+ VA_END (Ap);
+ return EFI_SUCCESS;
+ }
+ Fmt++;
+ }
+
+Error:
+ VA_END (Ap);
+ return Status;
+}
+
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TpmComm.c b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TpmComm.c
new file mode 100644
index 0000000..d5f6ca1
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TpmComm.c
@@ -0,0 +1,440 @@
+/** @file
+ Utility functions used by TPM Dxe driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/TpmCommLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+#include "TpmComm.h"
+
+#ifndef TPM_PP_BIOS_FAILURE
+#define TPM_PP_BIOS_FAILURE ((TPM_RESULT)(-0x0f))
+#endif
+
+/**
+ Extend a TPM PCR.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] DigestToExtend The 160 bit value representing the event to be recorded.
+ @param[in] PcrIndex The PCR to be updated.
+ @param[out] NewPcrValue New PCR value after extend.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+TpmCommExtend (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_DIGEST *DigestToExtend,
+ IN TPM_PCRINDEX PcrIndex,
+ OUT TPM_DIGEST *NewPcrValue
+ )
+{
+ EFI_STATUS Status;
+ TPM_DIGEST NewValue;
+ TPM_RQU_COMMAND_HDR CmdHdr;
+ TPM_RSP_COMMAND_HDR RspHdr;
+
+ if (NewPcrValue == NULL) {
+ NewPcrValue = &NewValue;
+ }
+
+ CmdHdr.tag = TPM_TAG_RQU_COMMAND;
+ CmdHdr.paramSize =
+ sizeof (CmdHdr) + sizeof (PcrIndex) + sizeof (*DigestToExtend);
+ CmdHdr.ordinal = TPM_ORD_Extend;
+ Status = TisPcExecute (
+ TpmHandle,
+ "%h%d%r%/%h%r",
+ &CmdHdr,
+ PcrIndex,
+ DigestToExtend,
+ (UINTN)sizeof (*DigestToExtend),
+ &RspHdr,
+ NewPcrValue,
+ (UINTN)sizeof (*NewPcrValue)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (RspHdr.returnCode != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get TPM capability flags.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] FlagSubcap Flag subcap.
+ @param[out] FlagBuffer Pointer to the buffer for returned flag structure.
+ @param[in] FlagSize Size of the buffer.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+TpmCommGetFlags (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN UINT32 FlagSubcap,
+ OUT VOID *FlagBuffer,
+ IN UINTN FlagSize
+ )
+{
+ EFI_STATUS Status;
+ TPM_RQU_COMMAND_HDR CmdHdr;
+ TPM_RSP_COMMAND_HDR RspHdr;
+ UINT32 Size;
+
+ CmdHdr.tag = TPM_TAG_RQU_COMMAND;
+ CmdHdr.paramSize = sizeof (CmdHdr) + sizeof (UINT32) * 3;
+ CmdHdr.ordinal = TPM_ORD_GetCapability;
+
+ Status = TisPcExecute (
+ TpmHandle,
+ "%h%d%d%d%/%h%d%r",
+ &CmdHdr,
+ TPM_CAP_FLAG,
+ sizeof (FlagSubcap),
+ FlagSubcap,
+ &RspHdr,
+ &Size,
+ FlagBuffer,
+ FlagSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (RspHdr.returnCode != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Add a new entry to the Event Log.
+
+ @param[in, out] EventLogPtr Pointer to the Event Log data.
+ @param[in, out] LogSize Size of the Event Log.
+ @param[in] MaxSize Maximum size of 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
+TpmCommLogEvent (
+ IN OUT UINT8 **EventLogPtr,
+ IN OUT UINTN *LogSize,
+ IN UINTN MaxSize,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ )
+{
+ UINT32 NewLogSize;
+
+ NewLogSize = sizeof (*NewEventHdr) + NewEventHdr->EventSize;
+ if (NewLogSize + *LogSize > MaxSize) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *EventLogPtr += *LogSize;
+ *LogSize += NewLogSize;
+ CopyMem (*EventLogPtr, NewEventHdr, sizeof (*NewEventHdr));
+ CopyMem (
+ *EventLogPtr + sizeof (*NewEventHdr),
+ NewEventData,
+ NewEventHdr->EventSize
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Send TPM_Startup command to TPM.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] BootMode Boot mode.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommStartup (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN EFI_BOOT_MODE BootMode
+ )
+{
+ TPM_STARTUP_TYPE TpmSt;
+ TPM_RESULT TpmResponse;
+
+ TpmSt = TPM_ST_CLEAR;
+ if (BootMode == BOOT_ON_S3_RESUME) {
+ TpmSt = TPM_ST_STATE;
+ }
+
+ //
+ // send Tpm command TPM_ORD_Startup
+ //
+ TpmSt = SwapBytes16 (TpmSt);
+ TpmResponse = TpmCommandNoReturnData (TpmHandle, TPM_ORD_Startup, (UINTN)sizeof TpmSt, &TpmSt);
+
+ return TpmResponse;
+}
+
+/**
+ Send TPM_ContinueSelfTest command to TPM.
+
+ @param[in] TpmHandle TPM handle.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommContinueSelfTest (
+ IN TIS_TPM_HANDLE TpmHandle
+ )
+{
+ TPM_RESULT TpmResponse;
+
+ //
+ // send Tpm command TPM_ORD_ContinueSelfTest
+ //
+ TpmResponse = TpmCommandNoReturnData (TpmHandle, TPM_ORD_ContinueSelfTest, 0, NULL);
+
+ return TpmResponse;
+}
+
+/**
+ Send TPM_GetSelfTestResult command to TPM.
+
+ @param[in] TpmHandle TPM handle.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommGetSelfTestResult (
+ IN TIS_TPM_HANDLE TpmHandle
+ )
+{
+ TPM_RESULT TpmResponse;
+
+ //
+ // send Tpm command TPM_ORD_ContinueSelfTest
+ //
+ TpmResponse = TpmCommandNoReturnData (TpmHandle, TPM_ORD_GetTestResult, 0, NULL);
+
+ return TpmResponse;
+}
+
+/**
+ Issue TSC_PhysicalPresence command to TPM.
+
+ Adapted from: SecurityPkg/Tcg/TcgPei/TpmComm.c
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] PhysicalPresence The state to set the TPM's Physical Presence flags.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommPhysicalPresence (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_PHYSICAL_PRESENCE PhysicalPresence
+ )
+{
+ EFI_STATUS Status;
+ TPM_RQU_COMMAND_HDR *TpmRqu;
+ TPM_PHYSICAL_PRESENCE *TpmPp;
+ TPM_RSP_COMMAND_HDR TpmRsp;
+ UINT8 Buffer[sizeof (*TpmRqu) + sizeof (*TpmPp)];
+
+ TpmRqu = (TPM_RQU_COMMAND_HDR*)Buffer;
+ TpmPp = (TPM_PHYSICAL_PRESENCE*)(TpmRqu + 1);
+
+ TpmRqu->tag = SwapBytes16 (TPM_TAG_RQU_COMMAND);
+ TpmRqu->paramSize = SwapBytes32 (sizeof (Buffer));
+ TpmRqu->ordinal = SwapBytes32 (TSC_ORD_PhysicalPresence);
+ WriteUnaligned16 (TpmPp, (TPM_PHYSICAL_PRESENCE) SwapBytes16 (PhysicalPresence));
+
+ Status = TisPcExecute (
+ TpmHandle,
+ "%r%/%r",
+ (UINT8*)TpmRqu,
+ (UINTN) sizeof (Buffer),
+ (UINT8*)&TpmRsp,
+ (UINTN)sizeof (TpmRsp)
+ );
+
+ if (EFI_ERROR (Status) || (TpmRsp.tag != SwapBytes16 (TPM_TAG_RSP_COMMAND))) {
+ return TPM_PP_BIOS_FAILURE;
+ }
+
+ return SwapBytes32 (TpmRsp.returnCode);
+}
+
+
+/**
+ Issue a TPM command for which no additional output data will be returned.
+
+ Adapted from: SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] Ordinal TPM command code.
+ @param[in] AdditionalParameterSize Additional parameter size.
+ @param[in] AdditionalParameters Pointer to the Additional paramaters.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommandNoReturnData (
+ IN TIS_TPM_HANDLE TpmHandle,
+ 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 = SwapBytes16 (TPM_TAG_RQU_COMMAND);
+ Size = (UINT32)(sizeof (*TpmRqu) + AdditionalParameterSize);
+ TpmRqu->paramSize = SwapBytes32 (Size);
+ TpmRqu->ordinal = SwapBytes32 (Ordinal);
+ CopyMem (TpmRqu + 1, AdditionalParameters, AdditionalParameterSize);
+
+ Status = TisPcExecute (
+ TpmHandle,
+ "%r%/%r",
+ (UINT8*)TpmRqu,
+ (UINTN) Size,
+ (UINT8*)&TpmRsp,
+ (UINTN)sizeof (TpmRsp)
+ );
+
+ FreePool (TpmRqu);
+ if (EFI_ERROR (Status) || (TpmRsp.tag != SwapBytes16 (TPM_TAG_RSP_COMMAND))) {
+ return TPM_PP_BIOS_FAILURE;
+ }
+
+ return SwapBytes32 (TpmRsp.returnCode);
+}
+
+
+/**
+ Send following commands in order to ENABLE+ACTIVATE TPM
+
+ (i) TSC_PhysicalPresence(physicalPresenceCMDEnable) - flag that software going to set physical presence
+ (ii) TSC_PhysicalPresence(physicalPresencePresent) - set physical presence by default
+ (iii) TPM_PhysicalEnable - enable
+ (iv) TPM_PhysicalSetDeactivated(FALSE), i.e. activate
+ (v) TSC_PhysicalPresence(physicalPresenceNotPresent) - unset physical presence
+
+ @param[in] TpmHandle TPM handle.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommEnableActivate (
+ IN TIS_TPM_HANDLE TpmHandle
+ )
+{
+ TPM_RESULT TpmResponse;
+ BOOLEAN DeactivateTPM;
+
+ //
+ // Set flag that software going to set physical presence.
+ //
+ TpmResponse = TpmCommPhysicalPresence (TpmHandle, TPM_PHYSICAL_PRESENCE_CMD_ENABLE);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "TpmCommEnableActivate(): TPM_PHYSICAL_PRESENCE_CMD_ENABLE failed\n"));
+ return TpmResponse;
+ }
+
+ //
+ // Set physical presence
+ //
+ TpmResponse = TpmCommPhysicalPresence (TpmHandle, TPM_PHYSICAL_PRESENCE_PRESENT);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "TpmCommEnableActivate(): TPM_PHYSICAL_PRESENCE_PRESENT failed\n"));
+ return TpmResponse;
+ }
+
+ //
+ // Enable the TPM
+ //
+ TpmResponse = TpmCommandNoReturnData (TpmHandle, TPM_ORD_PhysicalEnable, 0, NULL);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "TpmCommEnableActivate(): TPM_ORD_PhysicalEnable failed\n"));
+ return TpmResponse;
+ }
+
+ //
+ // Activate the TPM
+ //
+ DeactivateTPM = FALSE;
+ TpmResponse = TpmCommandNoReturnData (TpmHandle, TPM_ORD_PhysicalSetDeactivated, sizeof (DeactivateTPM), &DeactivateTPM);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "TpmCommEnableActivate(): TPM_ORD_PhysicalSetDeactivated(false) failed\n"));
+ return TpmResponse;
+ }
+
+ //
+ // Unset Physical Presence
+ //
+ TpmResponse = TpmCommPhysicalPresence (TpmHandle, TPM_PHYSICAL_PRESENCE_NOTPRESENT);
+ if (TpmResponse != TPM_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "TpmCommEnableActivate(): TPM_PHYSICAL_PRESENCE_NOTPRESENT failed\n"));
+ }
+
+ return TpmResponse;
+}
diff --git a/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TpmComm.h b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TpmComm.h
new file mode 100644
index 0000000..8aa3985
--- /dev/null
+++ b/QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TpmComm.h
@@ -0,0 +1,301 @@
+/** @file
+ Definitions and function prototypes used by TPM DXE driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _TPM_COMM_H_
+#define _TPM_COMM_H_
+
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+
+/**
+ Add a new entry to the Event Log.
+
+ @param[in, out] EventLogPtr Pointer to the Event Log data.
+ @param[in, out] LogSize Size of the Event Log.
+ @param[in] MaxSize Maximum size of 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
+TpmCommLogEvent (
+ IN OUT UINT8 **EventLogPtr,
+ IN OUT UINTN *LogSize,
+ IN UINTN MaxSize,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ );
+
+/**
+ Extend a TPM PCR.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] DigestToExtend The 160 bit value representing the event to be recorded.
+ @param[in] PcrIndex The PCR to be updated.
+ @param[out] NewPcrValue New PCR value after extend.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+TpmCommExtend (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_DIGEST *DigestToExtend,
+ IN TPM_PCRINDEX PcrIndex,
+ OUT TPM_DIGEST *NewPcrValue
+ );
+
+/**
+ Get TPM capability flags.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] FlagSubcap Flag subcap.
+ @param[out] FlagBuffer Pointer to the buffer for returned flag structure.
+ @param[in] FlagSize Size of the buffer.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+TpmCommGetFlags (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN UINT32 FlagSubcap,
+ OUT VOID *Buffer,
+ IN UINTN Size
+ );
+
+/**
+ Send formatted command to TPM for execution and return formatted data from response.
+
+ @param[in] TisReg TPM Handle.
+ @param[in] Fmt Format control string.
+ @param[in] ... The variable argument list.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+
+**/
+EFI_STATUS
+EFIAPI
+TisPcExecute (
+ IN TIS_TPM_HANDLE TisReg,
+ IN CONST CHAR8 *Fmt,
+ ...
+ );
+
+/**
+ Send command to TPM for execution.
+
+ @param[in] TisReg TPM register space base address.
+ @param[in] TpmBuffer Buffer for TPM command data.
+ @param[in] DataLength TPM command data length.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+
+**/
+EFI_STATUS
+TisPcSend (
+ IN TIS_PC_REGISTERS_PTR TisReg,
+ IN UINT8 *TpmBuffer,
+ IN UINT32 DataLength
+ );
+
+/**
+ Set Legacy GPIO Level
+
+ @param[in] LevelRegOffset GPIO level register Offset from GPIO Base Address.
+ @param[in] GpioNum GPIO bit to change.
+ @param[in] HighLevel Set or clear GPIO bit.
+
+**/
+STATIC
+VOID
+LegacyGpioSetLevel (
+ IN CONST UINT32 LevelRegOffset,
+ IN CONST UINT32 GpioNum,
+ IN CONST BOOLEAN HighLevel
+ );
+
+/**
+ Initialise the TPM (TPM_INIT).
+
+ Pull TPM reset low for 80us (equivalent to cold reset, Table 39
+ Infineon SLB9645 Databook), then high and wait for 150ms to give
+ time for TPM to stabilise (Section 4.7 Infineon SLB9645 Databook).
+ Infineon SLB9645 TPM on Crosshill board driven by GPIOSUS5.
+
+**/
+VOID
+TpmCommInit (
+ );
+
+/**
+ Send TPM_Startup command to TPM.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] BootMode Boot mode.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommStartup (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN EFI_BOOT_MODE BootMode
+ );
+
+/**
+ Send TPM_ContinueSelfTest command to TPM.
+
+ @param[in] TpmHandle TPM handle.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommContinueSelfTest (
+ IN TIS_TPM_HANDLE TpmHandle
+ );
+
+/**
+ Send TPM_GetSelfTestResult command to TPM.
+
+ @param[in] TpmHandle TPM handle.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommGetSelfTestResult (
+ IN TIS_TPM_HANDLE TpmHandle
+ );
+
+/**
+ Issue TSC_PhysicalPresence command to TPM.
+
+ Adapted from: SecurityPkg/Tcg/TcgPei/TpmComm.c
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] PhysicalPresence The state to set the TPM's Physical Presence flags.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommPhysicalPresence (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_PHYSICAL_PRESENCE PhysicalPresence
+ );
+
+/**
+ Issue a TPM command for which no additional output data will be returned.
+
+ Adapted from: SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] Ordinal TPM command code.
+ @param[in] AdditionalParameterSize Additional parameter size.
+ @param[in] AdditionalParameters Pointer to the Additional paramaters.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommandNoReturnData (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_COMMAND_CODE Ordinal,
+ IN UINTN AdditionalParameterSize,
+ IN VOID *AdditionalParameters
+ );
+
+/**
+ Send following commands in order to ENABLE+ACTIVATE TPM
+
+ (i) TSC_PhysicalPresence(physicalPresenceCMDEnable) - flag that software going to set physical presence
+ (ii) TSC_PhysicalPresence(physicalPresencePresent) - set physical presence by default
+ (iii) TPM_PhysicalEnable - enable
+ (iv) TPM_PhysicalSetDeactivated(FALSE), i.e. activate
+ (v) TSC_PhysicalPresence(physicalPresenceNotPresent) - unset physical presence
+
+ @param[in] TpmHandle TPM handle.
+
+ @retval TPM_RESULT TPM return code.
+
+**/
+TPM_RESULT
+TpmCommEnableActivate (
+ IN TIS_TPM_HANDLE TpmHandle
+ );
+
+/**
+ Writes single byte data to TPM specified by MMIO address.
+
+ Write access to TPM is MMIO or I2C (based on platform type).
+
+ This function is implemented in TpmCommLib (TpmAccess.c)
+
+ @param Address The register to write.
+ @param Data The data to write to the register.
+
+**/
+VOID
+TpmWriteByte (
+ IN UINTN Address,
+ IN UINT8 Data
+ );
+
+/**
+ Reads single byte data from TPM specified by MMIO address.
+
+ Read access to TPM is via MMIO or I2C (based on platform type).
+
+ This function is implemented in TpmCommLib (TpmAccess.c)
+
+ @param Address of the MMIO mapped register to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+TpmReadByte (
+ IN UINTN Address
+ );
+
+#endif // _TPM_COMM_H_
diff --git a/QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c b/QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
new file mode 100755
index 0000000..5a4be74
--- /dev/null
+++ b/QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
@@ -0,0 +1,1106 @@
+/** @file
+ This module produces the EFI_PEI_S3_RESUME_PPI.
+ This module works with StandAloneBootScriptExecutor to S3 resume to OS.
+ This module will excute the boot script saved during last boot and after that,
+ control is passed to OS waking up handler.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiPei.h>
+
+#include <Guid/AcpiS3Context.h>
+#include <Guid/BootScriptExecutorVariable.h>
+#include <Guid/Performance.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/S3Resume2.h>
+#include <Ppi/SmmAccess.h>
+#include <Ppi/PostBootScriptTable.h>
+#include <Ppi/EndOfPeiPhase.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/HobLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HobLib.h>
+#include <Library/LockBoxLib.h>
+#include <IndustryStandard/Acpi.h>
+
+#pragma pack(1)
+typedef union {
+ struct {
+ UINT32 LimitLow : 16;
+ UINT32 BaseLow : 16;
+ UINT32 BaseMid : 8;
+ UINT32 Type : 4;
+ UINT32 System : 1;
+ UINT32 Dpl : 2;
+ UINT32 Present : 1;
+ UINT32 LimitHigh : 4;
+ UINT32 Software : 1;
+ UINT32 Reserved : 1;
+ UINT32 DefaultSize : 1;
+ UINT32 Granularity : 1;
+ UINT32 BaseHigh : 8;
+ } Bits;
+ UINT64 Uint64;
+} IA32_GDT;
+
+//
+// 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;
+} PAGE_MAP_AND_DIRECTORY_POINTER;
+
+//
+// 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;
+} PAGE_TABLE_ENTRY;
+
+//
+// Page Table Entry 1GB
+//
+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:17; // Must be zero;
+ UINT64 PageTableBaseAddress:22; // 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;
+} PAGE_TABLE_1G_ENTRY;
+
+#pragma pack()
+
+//
+// Function prototypes
+//
+/**
+ a ASM function to transfer control to OS.
+
+ @param S3WakingVector The S3 waking up vector saved in ACPI Facs table
+ @param AcpiLowMemoryBase a buffer under 1M which could be used during the transfer
+**/
+typedef
+VOID
+(EFIAPI *ASM_TRANSFER_CONTROL) (
+ IN UINT32 S3WakingVector,
+ IN UINT32 AcpiLowMemoryBase
+ );
+
+/**
+ Restores the platform to its preboot configuration for an S3 resume and
+ jumps to the OS waking vector.
+
+ This function will restore the platform to its pre-boot configuration that was
+ pre-stored in the boot script table and transfer control to OS waking vector.
+ Upon invocation, this function is responsible for locating the following
+ information before jumping to OS waking vector:
+ - ACPI tables
+ - boot script table
+ - any other information that it needs
+
+ The S3RestoreConfig() function then executes the pre-stored boot script table
+ and transitions the platform to the pre-boot state. The boot script is recorded
+ during regular boot using the EFI_S3_SAVE_STATE_PROTOCOL.Write() and
+ EFI_S3_SMM_SAVE_STATE_PROTOCOL.Write() functions. Finally, this function
+ transfers control to the OS waking vector. If the OS supports only a real-mode
+ waking vector, this function will switch from flat mode to real mode before
+ jumping to the waking vector. If all platform pre-boot configurations are
+ successfully restored and all other necessary information is ready, this
+ function will never return and instead will directly jump to the OS waking
+ vector. If this function returns, it indicates that the attempt to resume
+ from the ACPI S3 sleep state failed.
+
+ @param[in] This Pointer to this instance of the PEI_S3_RESUME_PPI
+
+ @retval EFI_ABORTED Execution of the S3 resume boot script table failed.
+ @retval EFI_NOT_FOUND Some necessary information that is used for the S3
+ resume boot path could not be located.
+
+**/
+EFI_STATUS
+EFIAPI
+S3RestoreConfig2 (
+ IN EFI_PEI_S3_RESUME2_PPI *This
+ );
+
+//
+// Globals
+//
+EFI_PEI_S3_RESUME2_PPI mS3ResumePpi = { S3RestoreConfig2 };
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiS3Resume2PpiGuid,
+ &mS3ResumePpi
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListPostScriptTable = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiPostScriptTablePpiGuid,
+ 0
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListEndOfPeiTable = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ 0
+};
+
+//
+// Global Descriptor Table (GDT)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
+/* selector { Global Segment Descriptor } */
+/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x08 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x10 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}},
+/* 0x18 */ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}},
+/* 0x20 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+/* 0x28 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 0, 1, 0}},
+/* 0x30 */ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 0, 1, 0}},
+/* 0x38 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}},
+/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+};
+
+//
+// IA32 Gdt register
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
+ sizeof (mGdtEntries) - 1,
+ (UINTN) mGdtEntries
+ };
+
+/**
+ Performance measure function to get S3 detailed performance data.
+
+ This function will getS3 detailed performance data and saved in pre-reserved ACPI memory.
+**/
+VOID
+WriteToOsS3PerformanceData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase;
+ PERF_HEADER *PerfHeader;
+ PERF_DATA *PerfData;
+ UINT64 Ticker;
+ UINTN Index;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
+ UINTN VarSize;
+ UINTN LogEntryKey;
+ CONST VOID *Handle;
+ CONST CHAR8 *Token;
+ CONST CHAR8 *Module;
+ UINT64 StartTicker;
+ UINT64 EndTicker;
+ UINT64 StartValue;
+ UINT64 EndValue;
+ BOOLEAN CountUp;
+ UINT64 Freq;
+
+ //
+ // Retrive time stamp count as early as possilbe
+ //
+ Ticker = GetPerformanceCounter ();
+
+ Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
+
+ Freq = DivU64x32 (Freq, 1000);
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &VariableServices
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
+ Status = VariableServices->GetVariable (
+ VariableServices,
+ L"PerfDataMemAddr",
+ &gPerformanceProtocolGuid,
+ NULL,
+ &VarSize,
+ &mAcpiLowMemoryBase
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Fail to retrieve variable to log S3 performance data \n"));
+ return;
+ }
+
+ PerfHeader = (PERF_HEADER *) (UINTN) mAcpiLowMemoryBase;
+
+ if (PerfHeader->Signiture != PERFORMANCE_SIGNATURE) {
+ DEBUG ((EFI_D_ERROR, "Performance data in ACPI memory get corrupted! \n"));
+ return;
+ }
+
+ //
+ // Record total S3 resume time.
+ //
+ if (EndValue >= StartValue) {
+ PerfHeader->S3Resume = Ticker - StartValue;
+ CountUp = TRUE;
+ } else {
+ PerfHeader->S3Resume = StartValue - Ticker;
+ CountUp = FALSE;
+ }
+
+ //
+ // Get S3 detailed performance data
+ //
+ Index = 0;
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurement (
+ LogEntryKey,
+ &Handle,
+ &Token,
+ &Module,
+ &StartTicker,
+ &EndTicker)) != 0) {
+ if (EndTicker != 0) {
+ PerfData = &PerfHeader->S3Entry[Index];
+
+ //
+ // Use File Handle to specify the different performance log for PEIM.
+ // File Handle is the base address of PEIM FFS file.
+ //
+ if ((AsciiStrnCmp (Token, "PEIM", PEI_PERFORMANCE_STRING_SIZE) == 0) && (Handle != NULL)) {
+ AsciiSPrint (PerfData->Token, PERF_TOKEN_LENGTH, "0x%11p", Handle);
+ } else {
+ AsciiStrnCpy (PerfData->Token, Token, PERF_TOKEN_LENGTH);
+ }
+ if (StartTicker == 1) {
+ StartTicker = StartValue;
+ }
+ if (EndTicker == 1) {
+ EndTicker = StartValue;
+ }
+ Ticker = CountUp? (EndTicker - StartTicker) : (StartTicker - EndTicker);
+ PerfData->Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
+
+ //
+ // Only Record > 1ms performance data so that more big performance can be recorded.
+ //
+ if ((Ticker > Freq) && (++Index >= PERF_PEI_ENTRY_MAX_NUM)) {
+ //
+ // Reach the maximum number of PEI performance log entries.
+ //
+ break;
+ }
+ }
+ }
+ PerfHeader->S3EntryNum = (UINT32) Index;
+}
+
+/**
+ The function will check if current waking vector is long mode.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+
+ @retval TRUE Current context need long mode waking vector.
+ @retval FALSE Current context need not long mode waking vector.
+**/
+BOOLEAN
+IsLongModeWakingVector (
+ IN ACPI_S3_CONTEXT *AcpiS3Context
+ )
+{
+ EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+
+ Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable));
+ if ((Facs == NULL) ||
+ (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
+ ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) {
+ // Something wrong with FACS
+ return FALSE;
+ }
+ if (Facs->XFirmwareWakingVector != 0) {
+ if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
+ ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
+ ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) {
+ // Both BIOS and OS wants 64bit vector
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Jump to OS waking vector.
+ The function will install boot script done PPI, report S3 resume status code, and then jump to OS waking vector.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+ @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
+**/
+VOID
+EFIAPI
+S3ResumeBootOs (
+ IN ACPI_S3_CONTEXT *AcpiS3Context,
+ IN PEI_S3_RESUME_STATE *PeiS3ResumeState
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+ ASM_TRANSFER_CONTROL AsmTransferControl;
+ UINTN TempStackTop;
+ UINTN TempStack[0x10];
+
+ //
+ // Restore IDT
+ //
+ AsmWriteIdtr (&PeiS3ResumeState->Idtr);
+
+ if (PeiS3ResumeState->ReturnStatus != EFI_SUCCESS) {
+ //
+ // Report Status code that boot script execution is failed
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_BOOT_SCRIPT_ERROR)
+ );
+ }
+
+ PERF_END (NULL, "ScriptExec", NULL, 0);
+
+ //
+ // Install BootScriptDonePpi
+ //
+ Status = PeiServicesInstallPpi (&mPpiListPostScriptTable);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get ACPI Table Address
+ //
+ Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable));
+
+ if ((Facs == NULL) ||
+ (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
+ ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) {
+ //
+ // Report Status code that no valid vector is found
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_OS_WAKE_ERROR)
+ );
+ CpuDeadLoop ();
+ return ;
+ }
+
+ //
+ // Install EndOfPeiPpi
+ //
+ Status = PeiServicesInstallPpi (&mPpiListEndOfPeiTable);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // report status code on S3 resume
+ //
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);
+
+ PERF_CODE (
+ WriteToOsS3PerformanceData ();
+ );
+
+ AsmTransferControl = (ASM_TRANSFER_CONTROL)(UINTN)PeiS3ResumeState->AsmTransferControl;
+ if (Facs->XFirmwareWakingVector != 0) {
+ //
+ // Switch to native waking vector
+ //
+ TempStackTop = (UINTN)&TempStack + sizeof(TempStack);
+ if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
+ ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
+ ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) {
+ //
+ // X64 long mode waking vector
+ //
+ DEBUG (( EFI_D_INFO, "Transfer to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ AsmEnablePaging64 (
+ 0x38,
+ Facs->XFirmwareWakingVector,
+ 0,
+ 0,
+ (UINT64)(UINTN)TempStackTop
+ );
+ } else {
+ //
+ // Report Status code that no valid waking vector is found
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_OS_WAKE_ERROR)
+ );
+ DEBUG (( EFI_D_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ return ;
+ }
+ } else {
+ //
+ // IA32 protected mode waking vector (Page disabled)
+ //
+ DEBUG (( EFI_D_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT) (UINTN) Facs->XFirmwareWakingVector,
+ NULL,
+ NULL,
+ (VOID *)(UINTN)TempStackTop
+ );
+ }
+ } else {
+ //
+ // 16bit Realmode waking vector
+ //
+ DEBUG (( EFI_D_INFO, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));
+ AsmTransferControl (Facs->FirmwareWakingVector, 0x0);
+ }
+
+ //
+ // Report Status code the failure of S3Resume
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_OS_WAKE_ERROR)
+ );
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop();
+}
+
+/**
+ Restore S3 page table because we do not trust ACPINvs content.
+ If BootScriptExector driver will not run in 64-bit mode, this function will do nothing.
+
+ @param S3NvsPageTableAddress PageTableAddress in ACPINvs
+ @param Build4GPageTableOnly If BIOS just build 4G page table only
+**/
+VOID
+RestoreS3PageTables (
+ IN UINTN S3NvsPageTableAddress,
+ IN BOOLEAN Build4GPageTableOnly
+ )
+{
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ UINT8 PhysicalAddressBits;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN IndexOfPml4Entries;
+ UINTN IndexOfPdpEntries;
+ UINTN IndexOfPageDirectoryEntries;
+ UINT32 NumberOfPml4EntriesNeeded;
+ UINT32 NumberOfPdpEntriesNeeded;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;
+ VOID *Hob;
+ BOOLEAN Page1GSupport;
+ PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
+
+ //
+ // NOTE: We have to ASSUME the page table generation format, because we do not know whole page table information.
+ // The whole page table is too large to be saved in SMRAM.
+ //
+ // The assumption is : whole page table is allocated in CONTINOUS memory and CR3 points to TOP page.
+ //
+ DEBUG ((EFI_D_INFO, "S3NvsPageTableAddress - %x (%x)\n", (UINTN)S3NvsPageTableAddress, (UINTN)Build4GPageTableOnly));
+
+ //
+ // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.
+ //
+ PageMap = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;
+ S3NvsPageTableAddress += SIZE_4KB;
+
+ Page1GSupport = FALSE;
+ if (PcdGetBool(PcdUse1GPageTable)) {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT26) != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+ }
+
+ //
+ // Get physical address bits supported.
+ //
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ if (Hob != NULL) {
+ PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
+ } else {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8) RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+ }
+
+ //
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
+ //
+ ASSERT (PhysicalAddressBits <= 52);
+ if (PhysicalAddressBits > 48) {
+ PhysicalAddressBits = 48;
+ }
+
+ //
+ // NOTE: In order to save time to create full page table, we just create 4G page table by default.
+ // And let PF handler in BootScript driver to create more on request.
+ //
+ if (Build4GPageTableOnly) {
+ PhysicalAddressBits = 32;
+ ZeroMem (PageMap, EFI_PAGES_TO_SIZE(2));
+ }
+ //
+ // Calculate the table entries needed.
+ //
+ if (PhysicalAddressBits <= 39) {
+ NumberOfPml4EntriesNeeded = 1;
+ NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
+ } else {
+ NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
+ NumberOfPdpEntriesNeeded = 512;
+ }
+
+ PageMapLevel4Entry = PageMap;
+ PageAddress = 0;
+ for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {
+ //
+ // Each PML4 entry points to a page of Page Directory Pointer entires.
+ // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
+ //
+ PageDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;
+ S3NvsPageTableAddress += SIZE_4KB;
+
+ //
+ // Make a PML4 Entry
+ //
+ PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
+ PageMapLevel4Entry->Bits.ReadWrite = 1;
+ PageMapLevel4Entry->Bits.Present = 1;
+
+ if (Page1GSupport) {
+ PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectory1GEntry->Bits.ReadWrite = 1;
+ PageDirectory1GEntry->Bits.Present = 1;
+ PageDirectory1GEntry->Bits.MustBe1 = 1;
+ }
+ } else {
+ for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+ //
+ // Each Directory Pointer entries points to a page of Page Directory entires.
+ // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
+ //
+ PageDirectoryEntry = (PAGE_TABLE_ENTRY *)S3NvsPageTableAddress;
+ S3NvsPageTableAddress += SIZE_4KB;
+
+ //
+ // Fill in a Page Directory Pointer Entries
+ //
+ PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;
+ PageDirectoryPointerEntry->Bits.ReadWrite = 1;
+ PageDirectoryPointerEntry->Bits.Present = 1;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
+ PageDirectoryEntry->Bits.ReadWrite = 1;
+ PageDirectoryEntry->Bits.Present = 1;
+ PageDirectoryEntry->Bits.MustBe1 = 1;
+ }
+ }
+ }
+ }
+ return ;
+ } else {
+ //
+ // If DXE is running 32-bit mode, no need to establish page table.
+ //
+ return ;
+ }
+}
+
+/**
+ Jump to boot script executor driver.
+
+ The function will close and lock SMRAM and then jump to boot script execute driver to executing S3 boot script table.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+ @param EfiBootScriptExecutorVariable The function entry to executing S3 boot Script table. This function is build in
+ boot script execute driver
+**/
+VOID
+EFIAPI
+S3ResumeExecuteBootScript (
+ IN ACPI_S3_CONTEXT *AcpiS3Context,
+ IN BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_ACCESS_PPI *SmmAccess;
+ UINTN Index;
+ VOID *GuidHob;
+ IA32_DESCRIPTOR *IdtDescriptor;
+ VOID *IdtBuffer;
+ PEI_S3_RESUME_STATE *PeiS3ResumeState;
+
+ DEBUG ((EFI_D_INFO, "S3ResumeExecuteBootScript()\n"));
+
+ //
+ // Attempt to use content from SMRAM first
+ //
+ GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+ if (GuidHob != NULL) {
+ //
+ // Last step for SMM - send SMI for initialization
+ //
+
+ //
+ // Send SMI to APs
+ //
+ SendSmiIpiAllExcludingSelf ();
+ //
+ // Send SMI to BSP
+ //
+ SendSmiIpi (GetApicId ());
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SmmAccess
+ );
+
+ DEBUG ((EFI_D_INFO, "Close all SMRAM regions before executing boot script\n"));
+
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+
+ DEBUG ((EFI_D_INFO, "Lock all SMRAM regions before executing boot script\n"));
+
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+ }
+
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ AsmWriteCr3 ((UINTN)AcpiS3Context->S3NvsPageTableAddress);
+ }
+
+ if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
+ //
+ // On some platform, such as ECP, a dispatch node in boot script table may execute a 32-bit PEIM which may need PeiServices
+ // pointer. So PeiServices need preserve in (IDTBase- sizeof (UINTN)).
+ //
+ IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);
+ //
+ // Make sure the newly allcated IDT align with 16-bytes
+ //
+ IdtBuffer = AllocatePages (EFI_SIZE_TO_PAGES((IdtDescriptor->Limit + 1) + 16));
+ ASSERT (IdtBuffer != NULL);
+ CopyMem ((VOID*)((UINT8*)IdtBuffer + 16),(VOID*)(IdtDescriptor->Base), (IdtDescriptor->Limit + 1));
+ IdtDescriptor->Base = (UINTN)((UINT8*)IdtBuffer + 16);
+ *(UINTN*)(IdtDescriptor->Base - sizeof(UINTN)) = (UINTN)GetPeiServicesTablePointer ();
+ }
+
+ //
+ // Need to make sure the GDT is loaded with values that support long mode and real mode.
+ //
+ AsmWriteGdtr (&mGdt);
+
+ //
+ // Prepare data for return back
+ //
+ PeiS3ResumeState = AllocatePool (sizeof(*PeiS3ResumeState));
+ ASSERT (PeiS3ResumeState != NULL);
+ DEBUG (( EFI_D_INFO, "PeiS3ResumeState - %x\r\n", PeiS3ResumeState));
+ PeiS3ResumeState->ReturnCs = 0x10;
+ PeiS3ResumeState->ReturnEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeBootOs;
+ PeiS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;
+ //
+ // Save IDT
+ //
+ AsmReadIdtr (&PeiS3ResumeState->Idtr);
+
+ //
+ // Report Status Code to indicate S3 boot script execution
+ //
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_S3_BOOT_SCRIPT);
+
+ PERF_START (NULL, "ScriptExec", NULL, 0);
+
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ //
+ // X64 S3 Resume
+ //
+ DEBUG (( EFI_D_INFO, "Enable X64 and transfer control to Standalone Boot Script Executor\r\n"));
+
+ //
+ // Switch to long mode to complete resume.
+ //
+ AsmEnablePaging64 (
+ 0x38,
+ EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint,
+ (UINT64)(UINTN)AcpiS3Context,
+ (UINT64)(UINTN)PeiS3ResumeState,
+ (UINT64)(UINTN)(AcpiS3Context->BootScriptStackBase + AcpiS3Context->BootScriptStackSize)
+ );
+ } else {
+ //
+ // IA32 S3 Resume
+ //
+ DEBUG (( EFI_D_INFO, "transfer control to Standalone Boot Script Executor\r\n"));
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT) (UINTN) EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint,
+ (VOID *)AcpiS3Context,
+ (VOID *)PeiS3ResumeState,
+ (VOID *)(UINTN)(AcpiS3Context->BootScriptStackBase + AcpiS3Context->BootScriptStackSize)
+ );
+ }
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop();
+}
+/**
+ Restores the platform to its preboot configuration for an S3 resume and
+ jumps to the OS waking vector.
+
+ This function will restore the platform to its pre-boot configuration that was
+ pre-stored in the boot script table and transfer control to OS waking vector.
+ Upon invocation, this function is responsible for locating the following
+ information before jumping to OS waking vector:
+ - ACPI tables
+ - boot script table
+ - any other information that it needs
+
+ The S3RestoreConfig() function then executes the pre-stored boot script table
+ and transitions the platform to the pre-boot state. The boot script is recorded
+ during regular boot using the EFI_S3_SAVE_STATE_PROTOCOL.Write() and
+ EFI_S3_SMM_SAVE_STATE_PROTOCOL.Write() functions. Finally, this function
+ transfers control to the OS waking vector. If the OS supports only a real-mode
+ waking vector, this function will switch from flat mode to real mode before
+ jumping to the waking vector. If all platform pre-boot configurations are
+ successfully restored and all other necessary information is ready, this
+ function will never return and instead will directly jump to the OS waking
+ vector. If this function returns, it indicates that the attempt to resume
+ from the ACPI S3 sleep state failed.
+
+ @param[in] This Pointer to this instance of the PEI_S3_RESUME_PPI
+
+ @retval EFI_ABORTED Execution of the S3 resume boot script table failed.
+ @retval EFI_NOT_FOUND Some necessary information that is used for the S3
+ resume boot path could not be located.
+
+**/
+EFI_STATUS
+EFIAPI
+S3RestoreConfig2 (
+ IN EFI_PEI_S3_RESUME2_PPI *This
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_ACCESS_PPI *SmmAccess;
+ UINTN Index;
+ ACPI_S3_CONTEXT *AcpiS3Context;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
+ EFI_PHYSICAL_ADDRESS TempEfiBootScriptExecutorVariable;
+ EFI_PHYSICAL_ADDRESS TempAcpiS3Context;
+ BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
+ UINTN VarSize;
+ EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
+ SMM_S3_RESUME_STATE *SmmS3ResumeState;
+ VOID *GuidHob;
+ BOOLEAN Build4GPageTableOnly;
+
+ DEBUG ((EFI_D_INFO, "Enter S3 PEIM\r\n"));
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SmmAccess
+ );
+ for (Index = 0; !EFI_ERROR (Status); Index++) {
+ Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &VariableServices
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
+ Status = RestoreLockBox (
+ &gEfiAcpiVariableGuid,
+ &TempAcpiS3Context,
+ &VarSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ AcpiS3Context = (ACPI_S3_CONTEXT *)(UINTN)TempAcpiS3Context;
+ ASSERT (AcpiS3Context != NULL);
+
+ Status = RestoreLockBox (
+ &gEfiAcpiS3ContextGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ VarSize = sizeof (TempEfiBootScriptExecutorVariable);
+ Status = RestoreLockBox (
+ &gEfiBootScriptExecutorVariableGuid,
+ &TempEfiBootScriptExecutorVariable,
+ &VarSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = RestoreLockBox (
+ &gEfiBootScriptExecutorContextGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *) (UINTN) TempEfiBootScriptExecutorVariable;
+
+ DEBUG (( EFI_D_INFO, "AcpiS3Context = %x\n", AcpiS3Context));
+ DEBUG (( EFI_D_INFO, "Waking Vector = %x\n", ((EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable)))->FirmwareWakingVector));
+ DEBUG (( EFI_D_INFO, "AcpiS3Context->AcpiFacsTable = %x\n", AcpiS3Context->AcpiFacsTable));
+ DEBUG (( EFI_D_INFO, "AcpiS3Context->S3NvsPageTableAddress = %x\n", AcpiS3Context->S3NvsPageTableAddress));
+ DEBUG (( EFI_D_INFO, "AcpiS3Context->S3DebugBufferAddress = %x\n", AcpiS3Context->S3DebugBufferAddress));
+ DEBUG (( EFI_D_INFO, "EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = %x\n", EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint));
+
+ //
+ // Additional step for BootScript integrity - we only handle BootScript and BootScriptExecutor.
+ // Script dispatch image and context (parameter) are handled by platform.
+ // We just use restore all lock box in place, no need restore one by one.
+ //
+ Status = RestoreAllLockBoxInPlace ();
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ // Something wrong
+ CpuDeadLoop ();
+ }
+
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ //
+ // Need reconstruct page table here, since we do not trust ACPINvs.
+ //
+ if (IsLongModeWakingVector (AcpiS3Context)) {
+ Build4GPageTableOnly = FALSE;
+ } else {
+ Build4GPageTableOnly = TRUE;
+ }
+ RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress, Build4GPageTableOnly);
+ }
+
+ //
+ // Attempt to use content from SMRAM first
+ //
+ GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+ if (GuidHob != NULL) {
+ SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
+ SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
+
+ SmmS3ResumeState->ReturnCs = AsmReadCs ();
+ SmmS3ResumeState->ReturnEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeExecuteBootScript;
+ SmmS3ResumeState->ReturnContext1 = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;
+ SmmS3ResumeState->ReturnContext2 = (EFI_PHYSICAL_ADDRESS)(UINTN)EfiBootScriptExecutorVariable;
+ SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;
+
+ DEBUG (( EFI_D_INFO, "SMM S3 Signature = %x\n", SmmS3ResumeState->Signature));
+ DEBUG (( EFI_D_INFO, "SMM S3 Stack Base = %x\n", SmmS3ResumeState->SmmS3StackBase));
+ DEBUG (( EFI_D_INFO, "SMM S3 Stack Size = %x\n", SmmS3ResumeState->SmmS3StackSize));
+ DEBUG (( EFI_D_INFO, "SMM S3 Resume Entry Point = %x\n", SmmS3ResumeState->SmmS3ResumeEntryPoint));
+ DEBUG (( EFI_D_INFO, "SMM S3 CR0 = %x\n", SmmS3ResumeState->SmmS3Cr0));
+ DEBUG (( EFI_D_INFO, "SMM S3 CR3 = %x\n", SmmS3ResumeState->SmmS3Cr3));
+ DEBUG (( EFI_D_INFO, "SMM S3 CR4 = %x\n", SmmS3ResumeState->SmmS3Cr4));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return CS = %x\n", SmmS3ResumeState->ReturnCs));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return Entry Point = %x\n", SmmS3ResumeState->ReturnEntryPoint));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return Context1 = %x\n", SmmS3ResumeState->ReturnContext1));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return Context2 = %x\n", SmmS3ResumeState->ReturnContext2));
+ DEBUG (( EFI_D_INFO, "SMM S3 Return Stack Pointer = %x\n", SmmS3ResumeState->ReturnStackPointer));
+ DEBUG (( EFI_D_INFO, "SMM S3 Smst = %x\n", SmmS3ResumeState->Smst));
+
+ //
+ // Disable interrupt of Debug timer.
+ //
+ SaveAndSetDebugTimerInterrupt (FALSE);
+
+ if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->SmmS3ResumeEntryPoint,
+ (VOID *)AcpiS3Context,
+ 0,
+ (VOID *)(UINTN)(SmmS3ResumeState->SmmS3StackBase + SmmS3ResumeState->SmmS3StackSize)
+ );
+ }
+ if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {
+ //
+ // Switch to long mode to complete resume.
+ //
+
+ //
+ // Need to make sure the GDT is loaded with values that support long mode and real mode.
+ //
+ AsmWriteGdtr (&mGdt);
+ AsmWriteCr3 ((UINTN)SmmS3ResumeState->SmmS3Cr3);
+ AsmEnablePaging64 (
+ 0x38,
+ SmmS3ResumeState->SmmS3ResumeEntryPoint,
+ (UINT64)(UINTN)AcpiS3Context,
+ 0,
+ SmmS3ResumeState->SmmS3StackBase + SmmS3ResumeState->SmmS3StackSize
+ );
+ }
+
+ }
+
+ S3ResumeExecuteBootScript (AcpiS3Context, EfiBootScriptExecutorVariable );
+ return EFI_SUCCESS;
+}
+/**
+ Main entry for S3 Resume PEIM.
+
+ This routine is to install EFI_PEI_S3_RESUME2_PPI.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Pointer to PEI Services table.
+
+ @retval EFI_SUCCESS S3Resume Ppi is installed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimS3ResumeEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install S3 Resume Ppi
+ //
+ Status = (**PeiServices).InstallPpi (PeiServices, &mPpiList);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf b/QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
new file mode 100755
index 0000000..910aa07
--- /dev/null
+++ b/QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
@@ -0,0 +1,98 @@
+## @file
+# S3 Resume Module:
+# This module works with StandAloneBootScriptExecutor to S3 resume to OS.
+# This module will excute the boot script saved during last boot and after that,
+# control is passed to OS waking up handler.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = S3Resume2Pei
+ FILE_GUID = 89E549B0-7CFE-449d-9BA3-10D8B2312D71
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PeimS3ResumeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ S3Resume.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ PeiServicesTablePointerLib
+ PerformanceLib
+ HobLib
+ PeiServicesLib
+ PeimEntryPoint
+ TimerLib
+ BaseLib
+ DebugLib
+ PcdLib
+ IoLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ DebugAgentLib
+ LocalApicLib
+ ReportStatusCodeLib
+ LockBoxLib
+ PrintLib
+
+[Guids]
+ gEfiBootScriptExecutorVariableGuid # SOMETIMES_CONSUMED
+ gEfiBootScriptExecutorContextGuid # SOMETIMES_CONSUMED
+ gPerformanceProtocolGuid # ALWAYS_CONSUMED L"PerfDataMemAddr"
+ gEfiAcpiVariableGuid # ALWAYS_CONSUMED Hob: GUID_EXTENSION
+ gEfiAcpiS3ContextGuid # ALWAYS_CONSUMED
+
+[Ppis]
+ gEfiPeiReadOnlyVariable2PpiGuid # PPI ALWAYS_CONSUMED
+ gEfiPeiS3Resume2PpiGuid # PPI ALWAYS_PRODUCED
+ gPeiSmmAccessPpiGuid # PPI ALWAYS_CONSUMED
+ gPeiPostScriptTablePpiGuid # PPI ALWAYS_PRODUCED
+ gEfiEndOfPeiSignalPpiGuid # PPI ALWAYS_PRODUCED
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+
+[Depex]
+ gEfiPeiReadOnlyVariable2PpiGuid
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.c b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.c
new file mode 100755
index 0000000..18b4379
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.c
@@ -0,0 +1,1484 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciHostBridge.c
+
+Abstract:
+
+ Pci Host Bridge driver for a simple IIO. There is only one PCI Root Bridge in the system.
+ Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
+
+Revision History:
+
+--*/
+
+#include "PciHostBridge.h"
+#include "PciRootBridge.h"
+#include "Iio/IioRegs.h"
+
+//
+// We can hardcode the following for a Simple IIO -
+// Root Bridge Count within the host bridge
+// Root Bridge's device path
+// Root Bridge's resource appeture
+//
+STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[ROOT_BRIDGE_COUNT] = {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8),
+ EISA_PNP_ID(0x0A03),
+ 0,
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+};
+
+
+
+STATIC EFI_HANDLE mDriverImageHandle;
+
+EFI_IIO_UDS_PROTOCOL *mIioUds;
+PCI_ROOT_BRIDGE_RESOURCE_APERTURE *mResAperture;
+
+
+//
+// Implementation
+//
+EFI_STATUS
+EFIAPI
+InitializePciHostBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Entry point of this driver.
+
+Arguments:
+
+ ImageHandle - Image handle of this driver.
+ SystemTable - Pointer to standard EFI system table.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_DEVICE_ERROR - Fail to install PCI_ROOT_BRIDGE_IO protocol.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN TotalRootBridgeFound;
+ UINTN IioResourceMapEntry;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINT64 AllocAttributes;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+
+ PrivateData = NULL;
+
+ mDriverImageHandle = ImageHandle;
+
+ //
+ // Located the IIO Protocol Interface
+ //
+ Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid, NULL, &mIioUds);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Most systems in the world including complex servers
+ // have only one Host Bridge. Create Host Bridge Device Handle
+ //
+ Status = gBS->AllocatePool(EfiBootServicesData, sizeof(PCI_HOST_BRIDGE_INSTANCE), &HostBridge);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem (HostBridge, sizeof (PCI_HOST_BRIDGE_INSTANCE));
+
+ HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;
+ HostBridge->RootBridgeCount = mIioUds->IioUdsPtr->PlatformData.numofIIO;
+ HostBridge->ResourceSubmited = FALSE;
+ HostBridge->CanRestarted = TRUE;
+ //
+ // InitializeListHead (&HostBridge->Head);
+ //
+ HostBridge->ResAlloc.NotifyPhase = NotifyPhase;
+ HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;
+ HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;
+ HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;
+ HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;
+ HostBridge->ResAlloc.SubmitResources = SubmitResources;
+ HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
+ HostBridge->ResAlloc.PreprocessController = PreprocessController;
+
+ Status = gBS->InstallProtocolInterface (
+ &HostBridge->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &HostBridge->ResAlloc
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (HostBridge);
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = gBS->AllocatePool (EfiBootServicesData,
+ HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE),
+ &mResAperture);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem (mResAperture, HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE));
+
+ DEBUG ((EFI_D_INFO, "Address of resource Aperture: %x\n", mResAperture));
+
+ //
+ // Create Root Bridge Device Handle in this Host Bridge
+ //
+ InitializeListHead (&HostBridge->Head);
+
+ for (TotalRootBridgeFound = 0, IioResourceMapEntry = 0; TotalRootBridgeFound < HostBridge->RootBridgeCount, IioResourceMapEntry < MaxIIO; IioResourceMapEntry++) {
+ if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].Valid) continue; // No guarantee that the valid IIOs are sequential starting at 0!
+
+ Status = gBS->AllocatePool ( EfiBootServicesData,sizeof (PCI_ROOT_BRIDGE_INSTANCE),&PrivateData);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem (PrivateData, sizeof (PCI_ROOT_BRIDGE_INSTANCE));
+
+ PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
+ PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mEfiPciRootBridgeDevicePath[TotalRootBridgeFound];
+ AllocAttributes = GetAllocAttributes (TotalRootBridgeFound);
+
+ SimpleIioRootBridgeConstructor (
+ &PrivateData->Io,
+ HostBridge->HostBridgeHandle,
+ &(mResAperture[TotalRootBridgeFound]),
+ AllocAttributes
+ );
+ //
+ // Update Root Bridge with UDS resource information
+ //
+ PrivateData->Aperture.BusBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].BusBase;
+ PrivateData->Aperture.BusLimit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].BusLimit;
+ PrivateData->Aperture.Mem32Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Base;
+ PrivateData->Aperture.Mem32Limit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Limit;
+ if ((mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Limit > mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Base) &&
+ (mIioUds->IioUdsPtr->PlatformData.Pci64BitResourceAllocation)) {
+ PrivateData->Aperture.Mem64Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Base;
+ PrivateData->Aperture.Mem64Limit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Limit;
+ }
+ PrivateData->Aperture.IoBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoBase;
+ PrivateData->Aperture.IoLimit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoLimit;
+
+
+ DEBUG ((EFI_D_INFO, "\nIIO_resource[%x].BusBase: %x\n", IioResourceMapEntry, mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].BusBase));
+ DEBUG ((EFI_D_INFO, "IIO_resource[%x].BusLimit: %x\n", IioResourceMapEntry, mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].BusLimit));
+ DEBUG ((EFI_D_INFO, "IIO_resource[%x].PciResourceMem32Base: %x\n", IioResourceMapEntry, mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Base));
+ DEBUG ((EFI_D_INFO, "IIO_resource[%x].PciResourceMem32Limit: %x\n", IioResourceMapEntry, mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Limit));
+ DEBUG ((EFI_D_INFO, "IIO_resource[%x].PciResourceMem64Base: %lX\n", IioResourceMapEntry, mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Base));
+ DEBUG ((EFI_D_INFO, "IIO_resource[%x].PciResourceMem64Limit: %lX\n", IioResourceMapEntry, mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Limit));
+ DEBUG ((EFI_D_INFO, "IIO_resource[%x].PciResourceIoBase: %x\n", IioResourceMapEntry, mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoBase));
+ DEBUG ((EFI_D_INFO, "IIO_resource[%x].PciResourceIoLimit: %x\n\n", IioResourceMapEntry, mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoLimit));
+
+
+
+ PrivateData->Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &PrivateData->Io,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ InsertTailList (&HostBridge->Head, &PrivateData->Link);
+ TotalRootBridgeFound++; // This is a valid rootbridge so imcrement total root bridges found
+
+ }
+
+ //
+ // Add PCIE base into Runtime memory so that it can be reported in E820 table
+ //
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ mIioUds->IioUdsPtr->PlatformData.PciExpressBase,
+ mIioUds->IioUdsPtr->PlatformData.PciExpressSize,
+ EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ BaseAddress = mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 0,
+ mIioUds->IioUdsPtr->PlatformData.PciExpressSize,
+ &BaseAddress,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ mIioUds->IioUdsPtr->PlatformData.PciExpressBase,
+ mIioUds->IioUdsPtr->PlatformData.PciExpressSize,
+ EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ for (TotalRootBridgeFound = 0, IioResourceMapEntry = 0; TotalRootBridgeFound < HostBridge->RootBridgeCount, IioResourceMapEntry < MaxIIO; IioResourceMapEntry++) {
+
+ if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].Valid) continue; // No guarantee that the valid IIOs are sequential starting at 0!
+
+ TotalRootBridgeFound++; // This is a valid rootbridge so imcrement total root bridges found
+
+ if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoLimit > mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoBase) {
+ //
+ // At present, we use up the first 4k for fixed ranges like
+ // ICH GPIO, ACPI and ISA devices. The first 4k is not
+ // tracked through GCD. It should be.
+ //
+ Status = gDS->AddIoSpace (
+ EfiGcdIoTypeIo,
+ mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoBase ,
+ mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoLimit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceIoBase + 1
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Limit > mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Base) {
+ //
+ // Shouldn't the capabilities be UC?
+ //
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Base ,
+ mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem32Base + 1,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if ((mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Limit > mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Base) &&
+ (mIioUds->IioUdsPtr->PlatformData.Pci64BitResourceAllocation)) {
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Base ,
+ mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioResourceMapEntry].PciResourceMem64Base + 1,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+NotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+ Enter a certain phase of the PCI enumeration process.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ Phase - The phase during enumeration.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - Wrong phase parameter passed in.
+ EFI_NOT_READY - Resources have not been submitted yet.
+
+--*/
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ PCI_RESOURCE_TYPE Index;
+ EFI_LIST_ENTRY *List;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 AddrLen;
+ UINTN BitsOfAlignment;
+ UINT64 Alignment;
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+ PCI_RESOURCE_TYPE Index1;
+ PCI_RESOURCE_TYPE Index2;
+ BOOLEAN ResNodeHandled[TypeMax];
+ UINT64 MaxAlignment;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ switch (Phase) {
+ case EfiPciHostBridgeBeginEnumeration:
+ if (HostBridgeInstance->CanRestarted) {
+ //
+ // Reset Root Bridge
+ //
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeMax; Index++) {
+ RootBridgeInstance->ResAllocNode[Index].Type = Index;
+ RootBridgeInstance->ResAllocNode[Index].Base = 0;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+ } // for
+
+ List = List->ForwardLink;
+ } // while
+
+ HostBridgeInstance->ResourceSubmited = FALSE;
+ HostBridgeInstance->CanRestarted = TRUE;
+ } else {
+ //
+ // Can not restart
+ //
+ return EFI_NOT_READY;
+ } // if
+ break;
+
+ case EfiPciHostBridgeBeginBusAllocation:
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+ HostBridgeInstance->CanRestarted = FALSE;
+ return EFI_SUCCESS;
+ break;
+
+ case EfiPciHostBridgeEndBusAllocation:
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+ // HostBridgeInstance->CanRestarted = FALSE;
+ //
+ return EFI_SUCCESS;
+ break;
+
+ case EfiPciHostBridgeBeginResourceAllocation:
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+ // HostBridgeInstance->CanRestarted = FALSE;
+ //
+ return EFI_SUCCESS;
+ break;
+
+ case EfiPciHostBridgeAllocateResources:
+ ReturnStatus = EFI_SUCCESS;
+ if (HostBridgeInstance->ResourceSubmited) {
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
+ ResNodeHandled[Index1] = FALSE;
+ }
+
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ DEBUG ((EFI_D_INFO, "Address of RootBridgeInstance: %x)\n", RootBridgeInstance));
+ DEBUG ((EFI_D_INFO, " Signature: %x\n", RootBridgeInstance->Signature));
+ DEBUG ((EFI_D_INFO, " Bus Number Assigned: %x\n", RootBridgeInstance->BusNumberAssigned));
+ DEBUG ((EFI_D_INFO, " Bus Scan Count: %x\n", RootBridgeInstance->BusScanCount));
+
+ for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
+ if (RootBridgeInstance->ResAllocNode[Index1].Status == ResNone) {
+ ResNodeHandled[Index1] = TRUE;
+ } else {
+ //
+ // Allocate the resource node with max alignment at first
+ //
+ MaxAlignment = 0;
+ Index = TypeMax;
+ for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
+ if (ResNodeHandled[Index2]) {
+ continue;
+ }
+ if (MaxAlignment <= RootBridgeInstance->ResAllocNode[Index2].Alignment) {
+ MaxAlignment = RootBridgeInstance->ResAllocNode[Index2].Alignment;
+ Index = Index2;
+ }
+ } // for
+
+ if (Index < TypeMax) {
+ ResNodeHandled[Index] = TRUE;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;
+
+ //
+ // Get the number of '1' in Alignment.
+ //
+ for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) {
+ Alignment = RShiftU64 (Alignment, 1);
+ }
+
+ AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;
+
+ DEBUG ((EFI_D_INFO, "\n\nResource Type to assign : %x\n", Index));
+ DEBUG ((EFI_D_INFO, " Length to allocate: %x\n", RootBridgeInstance->ResAllocNode[Index].Length));
+ DEBUG ((EFI_D_INFO, " Aligment: %x\n", Alignment));
+
+ switch (Index) {
+ case TypeIo:
+ if (RootBridgeInstance->Aperture.IoBase < RootBridgeInstance->Aperture.IoLimit) {
+ //
+ // It is impossible for 0xFFFF Alignment for IO16
+ //
+ if (BitsOfAlignment >= 16)
+ Alignment = 0;
+
+ BaseAddress = RootBridgeInstance->Aperture.IoBase;
+
+ //
+ // Have to make sure Aligment is handled seeing we are doing direct address allocation
+ //
+ if ((BaseAddress & ~(Alignment)) != BaseAddress)
+ BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));
+
+ while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.IoLimit + 1) {
+
+ Status = gDS->AllocateIoSpace ( EfiGcdAllocateAddress, EfiGcdIoTypeIo, BitsOfAlignment,
+ AddrLen, &BaseAddress, mDriverImageHandle, NULL );
+
+ if (!EFI_ERROR (Status)) {
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ goto TypeIoFound;
+ }
+
+ BaseAddress += (Alignment + 1);
+ } // while
+
+ } // if
+
+ TypeIoFound:
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
+ //
+ // No Room at the Inn for this resources request
+ //
+ ReturnStatus = EFI_OUT_OF_RESOURCES;
+ } // if
+
+ break;
+
+ case TypeMem32:
+ if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) {
+
+ BaseAddress = RootBridgeInstance->Aperture.Mem32Base;
+ //
+ // Have to make sure Aligment is handled seeing we are doing direct address allocation
+ //
+ if ((BaseAddress & ~(Alignment)) != BaseAddress)
+ BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));
+
+ while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.Mem32Limit + 1) {
+
+ Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
+
+ if (!EFI_ERROR (Status)) {
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ goto TypeMem32Found;
+ } // if
+
+ BaseAddress += (Alignment + 1);
+ } // while
+ } // if
+
+ TypeMem32Found:
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
+ //
+ // No Room at the Inn for this resources request
+ //
+ ReturnStatus = EFI_OUT_OF_RESOURCES;
+ }
+
+ break;
+
+ case TypePMem32:
+ StartTypePMem32:
+ if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) {
+
+ BaseAddress = RootBridgeInstance->Aperture.Mem32Limit + 1;
+ BaseAddress -= AddrLen;
+
+ //
+ // Have to make sure Aligment is handled seeing we are doing direct address allocation
+ //
+ if ((BaseAddress & ~(Alignment)) != BaseAddress)
+ BaseAddress = ((BaseAddress) & ~(Alignment));
+
+ while(RootBridgeInstance->Aperture.Mem32Base <= BaseAddress) {
+
+ DEBUG ((EFI_D_INFO, " Attempting %x allocation at 0x%lx .....", Index, BaseAddress));
+ Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
+
+ if (!EFI_ERROR (Status)) {
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ DEBUG ((EFI_D_INFO, "... Passed!!\n"));
+ goto TypePMem32Found;
+ }
+ DEBUG ((EFI_D_INFO, "... Failed!!\n"));
+ BaseAddress -= (Alignment + 1);
+ } // while
+ } // if
+
+ TypePMem32Found:
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
+ //
+ // No Room at the Inn for this resources request
+ //
+ ReturnStatus = EFI_OUT_OF_RESOURCES;
+ }
+
+ break;
+
+ case TypeMem64:
+ case TypePMem64:
+ if ((RootBridgeInstance->Aperture.Mem64Limit > RootBridgeInstance->Aperture.Mem64Base) &&
+ (mIioUds->IioUdsPtr->PlatformData.Pci64BitResourceAllocation)) {
+
+ BaseAddress = RootBridgeInstance->Aperture.Mem64Limit + 1;
+ BaseAddress -= AddrLen;
+
+ //
+ // Have to make sure Aligment is handled seeing we are doing direct address allocation
+ //
+ if ((BaseAddress & ~(Alignment)) != BaseAddress)
+ BaseAddress = ((BaseAddress) & ~(Alignment));
+
+ while(RootBridgeInstance->Aperture.Mem64Base <= BaseAddress) {
+
+ DEBUG ((EFI_D_INFO, " Attempting %x allocation at 0x%x .....", Index, BaseAddress));
+ Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
+
+ if (!EFI_ERROR (Status)) {
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ DEBUG ((EFI_D_INFO, "... Passed!!\n"));
+ goto TypeMem64Found;
+ }
+ DEBUG ((EFI_D_INFO, "... Failed!!\n"));
+ BaseAddress -= (Alignment + 1);
+ } // while
+ } // if
+
+ TypeMem64Found:
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
+ //
+ // If 64-bit resourcing is not available, then try as PMem32
+ //
+ goto StartTypePMem32;
+ }
+
+ break;
+ } // End switch (Index)
+
+ DEBUG ((EFI_D_INFO, "Resource Type Assigned: %x\n", Index));
+ if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
+ DEBUG ((EFI_D_INFO, " Base Address Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Base));
+ DEBUG ((EFI_D_INFO, " Length Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Length));
+ } else {
+ DEBUG ((DEBUG_ERROR, " Resource Allocation failed! There was no room at the inn\n"));
+ }
+
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+
+ if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
+ DEBUG ((DEBUG_ERROR, "Resource allocation Failed. Continue booting the system.\n"));
+ }
+
+ //
+ // Set resource to zero for nodes where allocation fails
+ //
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ }
+ }
+ List = List->ForwardLink;
+ }
+ return ReturnStatus;
+ } else {
+ return EFI_NOT_READY;
+ }
+ //
+ // HostBridgeInstance->CanRestarted = FALSE;
+ //
+ break;
+
+ case EfiPciHostBridgeSetResources:
+ //
+ // HostBridgeInstance->CanRestarted = FALSE;
+ //
+ break;
+
+ case EfiPciHostBridgeFreeResources:
+ //
+ // HostBridgeInstance->CanRestarted = FALSE;
+ //
+ ReturnStatus = EFI_SUCCESS;
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
+ AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) RootBridgeInstance->ResAllocNode[Index].Base;
+ switch (Index) {
+ case TypeIo:
+ Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+ break;
+
+ case TypeMem32:
+ Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+ break;
+
+ case TypePMem32:
+ break;
+
+ case TypeMem64:
+ break;
+
+ case TypePMem64:
+ Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+
+ break;
+ } // end switch (Index)
+
+ RootBridgeInstance->ResAllocNode[Index].Type = Index;
+ RootBridgeInstance->ResAllocNode[Index].Base = 0;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+
+ HostBridgeInstance->ResourceSubmited = FALSE;
+ HostBridgeInstance->CanRestarted = TRUE;
+ return ReturnStatus;
+ break;
+
+ case EfiPciHostBridgeEndResourceAllocation:
+ //
+ // Resource enumeration is done. Perform any activities that
+ // must wait until that time.
+ //
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ } // End switch (Phase)
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetNextRootBridge (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+ Return the device handle of the next PCI root bridge that is associated with
+ this Host Bridge.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - Returns the device handle of the next PCI Root Bridge.
+ On input, it holds the RootBridgeHandle returned by the most
+ recent call to GetNextRootBridge().The handle for the first
+ PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_NOT_FOUND - Next PCI root bridge not found.
+ EFI_INVALID_PARAMETER - Wrong parameter passed in.
+
+--*/
+{
+ BOOLEAN NoRootBridge;
+ EFI_LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ NoRootBridge = TRUE;
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ NoRootBridge = FALSE;
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (*RootBridgeHandle == NULL) {
+ //
+ // Return the first Root Bridge Handle of the Host Bridge
+ //
+ *RootBridgeHandle = RootBridgeInstance->Handle;
+ return EFI_SUCCESS;
+ } else {
+ if (*RootBridgeHandle == RootBridgeInstance->Handle) {
+ //
+ // Get next if have
+ //
+ List = List->ForwardLink;
+ if (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ *RootBridgeHandle = RootBridgeInstance->Handle;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ List = List->ForwardLink;
+ //
+ // end while
+ //
+ }
+
+ if (NoRootBridge) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+EFI_STATUS
+EFIAPI
+GetAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ )
+/*++
+
+Routine Description:
+ Returns the attributes of a PCI Root Bridge.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The device handle of the PCI Root Bridge
+ that the caller is interested in.
+ Attributes - The pointer to attributes of the PCI Root Bridge.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or
+ RootBridgeHandle is not an EFI_HANDLE
+ that was returned on a previous call to
+ GetNextRootBridge().
+
+--*/
+{
+ EFI_LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ if (Attributes == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ *Attributes = RootBridgeInstance->RootBridgeAllocAttrib;
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+ //
+ // RootBridgeHandle is not an EFI_HANDLE
+ // that was returned on a previous call to GetNextRootBridge()
+ //
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+StartBusEnumeration (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+/*++
+
+Routine Description:
+ This is the request from the PCI enumerator to set up
+ the specified PCI Root Bridge for bus enumeration process.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge to be set up.
+ Configuration - Pointer to the pointer to the PCI bus resource descriptor.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
+ EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+
+--*/
+{
+ EFI_LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ VOID *Buffer;
+ UINT8 *Temp;
+ EFI_STATUS Status;
+ UINTN BusStart;
+ UINTN BusEnd;
+ UINT64 BusReserve;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ //
+ // Set up the Root Bridge for Bus Enumeration
+ //
+ BusStart = RootBridgeInstance->Aperture.BusBase;
+ BusEnd = RootBridgeInstance->Aperture.BusLimit;
+ BusReserve = RootBridgeInstance->Aperture.BusReserve;
+ //
+ // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Temp = (UINT8 *) Buffer;
+
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Len = 0x2B;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->GenFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->SpecificFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrSpaceGranularity = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMin = BusStart;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMax = BusReserve;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrTranslationOffset = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrLen = BusEnd - BusStart + 1;
+
+ Temp = Temp + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+SetBusNumbers (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+/*++
+
+Routine Description:
+ This function programs the PCI Root Bridge hardware so that
+ it decodes the specified PCI bus range.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge whose bus range is to be programmed.
+ Configuration - The pointer to the PCI bus resource descriptor.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - Wrong parameters passed in.
+
+--*/
+{
+ EFI_LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Ptr;
+ UINTN BusStart;
+ UINTN BusEnd;
+ UINTN BusLen;
+
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr = Configuration;
+
+ //
+ // Check the Configuration is valid
+ //
+ if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ Ptr = Configuration;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ BusStart = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrRangeMin;
+ BusLen = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrLen;
+ BusEnd = BusStart + BusLen - 1;
+
+ if (BusStart > BusEnd) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BusStart < RootBridgeInstance->Aperture.BusBase) || (BusEnd > RootBridgeInstance->Aperture.BusLimit)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Update the Bus Range
+ //
+ RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
+ RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
+ RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
+ RootBridgeInstance->BusScanCount++;
+ if (RootBridgeInstance->BusScanCount > 0) {
+ //
+ // Only care about the 2nd PCI bus scanning
+ //
+ RootBridgeInstance->BusNumberAssigned = TRUE;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+SubmitResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+/*++
+
+Routine Description:
+
+ Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
+
+Arguments:
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge whose I/O and memory resource requirements.
+ are being submitted.
+ Configuration - The pointer to the PCI I/O and PCI memory resource descriptor.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - Wrong parameters passed in.
+
+--*/
+{
+ EFI_LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
+ UINT64 AddrLen;
+ UINT64 Alignment;
+ UINT64 Value;
+
+ //
+ // Check the input parameter: Configuration
+ //
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ Temp = (UINT8 *) Configuration;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ //
+ // Check the resource descriptors.
+ // If the Configuration includes one or more invalid resource descriptors, all the resource
+ // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
+ //
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+ DEBUG ((EFI_D_INFO, " ptr->ResType:%x \n",ptr->ResType));
+ DEBUG ((EFI_D_INFO, " ptr->AddrLen:0x%lx AddrRangeMin:0x%lx AddrRangeMax:0x%lx\n\n",ptr->AddrLen,ptr->AddrRangeMin,ptr->AddrRangeMax));
+
+ switch (ptr->ResType) {
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:
+ if (ptr->AddrSpaceGranularity != 32 && ptr->AddrSpaceGranularity != 64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ptr->AddrSpaceGranularity == 32 && ptr->AddrLen > 0xffffffff) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // If the PCI root bridge does not support separate windows for nonprefetchable and
+ // prefetchable memory, then the PCI bus driver needs to include requests for
+ // prefetchable memory in the nonprefetchable memory pool.
+ //
+ if ((RootBridgeInstance->RootBridgeAllocAttrib & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 &&
+ ((ptr->SpecificFlag & (BIT2 | BIT1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ case ACPI_ADDRESS_SPACE_TYPE_IO:
+ //
+ // Check aligment, it should be of the form 2^n-1
+ //
+ Value = Power2MaxMemory (ptr->AddrRangeMax + 1);
+ if (Value != (ptr->AddrRangeMax + 1)) {
+ CpuDeadLoop();
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ case ACPI_ADDRESS_SPACE_TYPE_BUS:
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
+ }
+ if (*Temp != ACPI_END_TAG_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Temp = (UINT8 *) Configuration;
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+
+ switch (ptr->ResType) {
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:
+ AddrLen = (UINT64) ptr->AddrLen;
+ Alignment = (UINT64) ptr->AddrRangeMax;
+ if (ptr->AddrSpaceGranularity == 32) {
+ if (ptr->SpecificFlag == 0x06) {
+ //
+ // Apply from GCD
+ //
+ RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
+ } else {
+ RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ }
+ }
+
+ if (ptr->AddrSpaceGranularity == 64) {
+ if (ptr->SpecificFlag == 0x06) {
+ RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
+ } else {
+ RootBridgeInstance->ResAllocNode[TypeMem64].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypeMem64].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ }
+ }
+ break;
+
+ case ACPI_ADDRESS_SPACE_TYPE_IO:
+ AddrLen = (UINT64) ptr->AddrLen;
+ Alignment = (UINT64) ptr->AddrRangeMax;
+ RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+GetProposedResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+/*++
+
+Routine Description:
+ This function returns the proposed resource settings for the specified
+ PCI Root Bridge.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge handle.
+ Configuration - The pointer to the pointer to the PCI I/O
+ and memory resource descriptor.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
+ EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+
+--*/
+{
+ EFI_LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINTN Index;
+ UINTN Number;
+ VOID *Buffer;
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
+ EFI_STATUS Status;
+ UINT64 ResStatus;
+
+ Buffer = NULL;
+ Number = 0;
+ //
+ // Get the Host Bridge Instance from the resource allocation protocol
+ //
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ //
+ // Enumerate the root bridges in this host bridge
+ //
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ for (Index = 0; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ Number++;
+ }
+ }
+
+ if (Number > 0) {
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (Buffer, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Number + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ }
+
+ ASSERT (Buffer != NULL);
+ Temp = Buffer;
+ for (Index = 0; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+ ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
+
+ switch (Index) {
+
+ case TypeIo:
+ //
+ // Io
+ //
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 1;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 0;
+ ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypeMem32:
+ //
+ // Memory 32
+ //
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 0;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 0;
+ ptr->AddrSpaceGranularity = 32;
+ ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypePMem32:
+ //
+ // Prefetch memory 32
+ //
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 0;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 6;
+ ptr->AddrSpaceGranularity = 32;
+ ptr->AddrRangeMin = 0;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ ptr->AddrLen = 0;
+ break;
+
+ case TypeMem64:
+ //
+ // Memory 64
+ //
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 0;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 0;
+ ptr->AddrSpaceGranularity = 64;
+ ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypePMem64:
+ //
+ // Prefetch memory 64
+ //
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 0;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 6;
+ ptr->AddrSpaceGranularity = 64;
+ ptr->AddrRangeMin = 0;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ ptr->AddrLen = 0;
+ break;
+ }
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+ }
+
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = 0x79;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+PreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+ This function is called for all the PCI controllers that the PCI
+ bus driver finds. Can be used to Preprogram the controller.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge handle.
+ PciAddress - Address of the controller on the PCI bus.
+ Phase - The Phase during resource allocation.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+
+--*/
+{
+ BOOLEAN RootBridgeFound;
+ EFI_LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ if (RootBridgeHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RootBridgeFound = FALSE;
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ RootBridgeFound = TRUE;
+ break;
+ }
+ //
+ // Get next if have
+ //
+ List = List->ForwardLink;
+ }
+
+ if (RootBridgeFound == FALSE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ Calculate maximum memory length that can be fit to a mtrr.
+
+Arguments:
+
+ MemoryLength - Input memory length.
+
+Returns:
+
+ Returned Maximum length.
+
+--*/
+{
+ UINT64 Result;
+
+ if (RShiftU64 (MemoryLength, 32)) {
+ Result = LShiftU64 ((UINT64) GetPowerOfTwo64 ((UINT32) RShiftU64 (MemoryLength, 32)), 32);
+ } else {
+ Result = (UINT64) GetPowerOfTwo64 ((UINT32) MemoryLength);
+ }
+
+ return Result;
+}
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.h b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.h
new file mode 100755
index 0000000..b53aef2
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.h
@@ -0,0 +1,422 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciHostBridge.h
+
+Abstract:
+
+ The Header file of the Pci Host Bridge Driver.
+
+Revision History:
+
+--*/
+
+#ifndef _PCI_HOST_BRIDGE_H_
+#define _PCI_HOST_BRIDGE_H_
+
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+#include <PciRootBridge.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/UefiLib.h>
+#include <Guid/HobList.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+
+#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32 ('e', 'h', 's', 't')
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE HostBridgeHandle;
+ UINTN RootBridgeCount;
+ EFI_LIST_ENTRY Head;
+ BOOLEAN ResourceSubmited;
+ BOOLEAN CanRestarted;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;
+} PCI_HOST_BRIDGE_INSTANCE;
+
+#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) CR (a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
+
+typedef enum {
+ SocketResourceRatioChanged,
+ SocketResourceRatioNotChanged,
+ SocketResourceAdjustMax
+} SOCKET_RESOURCE_ADJUSTMENT_RESULT;
+
+//
+// Driver Entry Point
+//
+EFI_STATUS
+EFIAPI
+InitializePciHostBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Entry point of this driver.
+
+Arguments:
+
+ ImageHandle - Image handle of this driver.
+ SystemTable - Pointer to standard EFI system table.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_DEVICE_ERROR - Fail to install PCI_ROOT_BRIDGE_IO protocol.
+
+--*/
+;
+
+//
+// HostBridge Resource Allocation interface
+//
+EFI_STATUS
+EFIAPI
+NotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+ Enter a certain phase of the PCI enumeration process.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ Phase - The phase during enumeration.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - Wrong phase parameter passed in.
+ EFI_NOT_READY - Resources have not been submitted yet.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+GetNextRootBridge (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ Return the device handle of the next PCI root bridge that is associated with
+ this Host Bridge.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - Returns the device handle of the next PCI Root Bridge.
+ On input, it holds the RootBridgeHandle returned by the most
+ recent call to GetNextRootBridge().The handle for the first
+ PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_NOT_FOUND - Next PCI root bridge not found.
+ EFI_INVALID_PARAMETER - Wrong parameter passed in.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+GetAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ )
+/*++
+
+Routine Description:
+
+ Returns the attributes of a PCI Root Bridge.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ RootBridgeHandle - The device handle of the PCI Root Bridge
+ that the caller is interested in
+ Attributes - The pointer to attributes of the PCI Root Bridge
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or
+ RootBridgeHandle is not an EFI_HANDLE
+ that was returned on a previous call to
+ GetNextRootBridge().
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+StartBusEnumeration (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+/*++
+
+Routine Description:
+
+ This is the request from the PCI enumerator to set up
+ the specified PCI Root Bridge for bus enumeration process.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge to be set up.
+ Configuration - Pointer to the pointer to the PCI bus resource descriptor.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
+ EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SetBusNumbers (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+/*++
+
+Routine Description:
+
+ This function programs the PCI Root Bridge hardware so that
+ it decodes the specified PCI bus range.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge whose bus range is to be programmed.
+ Configuration - The pointer to the PCI bus resource descriptor.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - Wrong parameters passed in.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SubmitResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+/*++
+
+Routine Description:
+
+ Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ RootBridgeHandle - The PCI Root Bridge whose I/O and memory resource requirements
+ are being submitted
+ Configuration - The pointer to the PCI I/O and PCI memory resource descriptor
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - Wrong parameters passed in.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+GetProposedResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+/*++
+
+Routine Description:
+
+ This function returns the proposed resource settings for the specified
+ PCI Root Bridge.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge handle.
+ Configuration - The pointer to the pointer to the PCI I/O
+ and memory resource descriptor.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
+ EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+ This function is called for all the PCI controllers that the PCI
+ bus driver finds. Can be used to Preprogram the controller.
+
+Arguments:
+
+ This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ RootBridgeHandle - The PCI Root Bridge handle.
+ PciAddress - Address of the controller on the PCI bus.
+ Phase - The Phase during resource allocation.
+
+Returns:
+
+ EFI_SUCCESS - Succeed.
+ EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+
+--*/
+;
+
+//
+// Host Bridge Silicon specific hooks
+//
+UINT64
+GetAllocAttributes (
+ IN UINTN RootBridgeIndex
+ )
+/*++
+
+Routine Description:
+
+ Returns the Allocation attributes for the BNB Root Bridge.
+
+Arguments:
+
+ RootBridgeIndex - The root bridge number. 0 based.
+
+Returns:
+
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE
+
+--*/
+;
+
+EFI_STATUS
+GetHostBridgeMemApertures (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ OUT UINT32 *Mem32Base,
+ OUT UINT32 *Mem32Limit,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *Mem64Limit
+ )
+/*++
+
+Routine Description:
+
+ Returns memory apertures for the BNB Root Bridge.
+
+Arguments:
+
+ PciRootBridgeIo - Pointer to Efi Pci root bridge Io protocol interface instance.
+ Mem32Base - Pointer to 32 bit memory base. This is the lowest 32 bit memory address
+ that is decoded by the Host Bridge.
+ Mem32Limit - Pointer to 32 bit memory limit.This is the highest 32 bit memory address
+ that is decoded by the Host Bridge. The size of the 32 bit window is
+ (Mem32Limit - Mem32base + 1).
+ Mem64Base - Pointer to 64 bit memory base. This is the lowest 64 bit memory address
+ that is decoded by the Host Bridge.
+ Mem64Limit - Pointer to 64 bit memory limit.This is the highest 64 bit memory address
+ that is decoded by the Host Bridge. The size of the 64 bit window is
+ (Mem64Limit - Mem64base + 1). Set Mem64Limit < Mem64Base if the host bridge
+ does not support 64 bit memory addresses.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+
+--*/
+;
+
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ Calculate maximum memory length that can be fit to a mtrr.
+
+Arguments:
+
+ MemoryLength - Input memory length.
+
+Returns:
+
+ Returned Maximum length.
+
+--*/
+;
+
+#endif
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.inf b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.inf
new file mode 100755
index 0000000..c3d242b
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.inf
@@ -0,0 +1,91 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Module Name:
+#
+# PciHostBridge.inf
+#
+# Abstract:
+#
+# Component description file for PciHostBridge module
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PciHostBridge
+ FILE_GUID = D58EBCE1-AF26-488d-BE66-C164417F8C13
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializePciHostBridge
+
+
+[Sources]
+ PciHostBridge.h
+ PciRootBridge.h
+ PciHostBridge.c
+ PciRootBridgeIo.c
+ PciHostBridgeSupport.c
+ PciHostResource.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ DebugLib
+ UefiLib
+ DxeServicesTableLib
+ UefiRuntimeServicesTableLib
+ DevicePathLib
+ BaseMemoryLib
+ BaseLib
+
+[Protocols]
+gEfiMetronomeArchProtocolGuid
+gEfiCpuIoProtocolGuid
+gEfiIioUdsProtocolGuid
+gEfiDevicePathProtocolGuid
+gEfiPciRootBridgeIoProtocolGuid
+gEfiPciHostBridgeResourceAllocationProtocolGuid
+
+[Guids]
+ gEfiSetupVariableGuid
+
+[Depex]
+ gEfiCpuIoProtocolGuid AND
+ gEfiMetronomeArchProtocolGuid AND
+ gEfiIioUdsProtocolGuid
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridgeSupport.c b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridgeSupport.c
new file mode 100755
index 0000000..a86fa83
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridgeSupport.c
@@ -0,0 +1,171 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciHostBridgeSupport.c
+
+Abstract:
+
+ Do platform initialization for PCI bridge.
+
+--*/
+
+#include "PciHostBridge.h"
+
+EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mPciRootBridgeIo;
+
+EFI_STATUS
+ChipsetPreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+ This function is called for all the PCI controllers that the PCI
+ bus driver finds. Can be used to Preprogram the controller.
+
+Arguments:
+ This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ RootBridgeHandle -- The PCI Root Bridge handle
+ PciBusAddress -- Address of the controller on the PCI bus
+ Phase -- The Phase during resource allocation
+
+Returns:
+ EFI_SUCCESS
+
+--*/
+
+// GC_TODO: PciAddress - add argument and description to function comment
+//
+// GC_TODO: PciAddress - add argument and description to function comment
+//
+// GC_TODO: PciAddress - add argument and description to function comment
+//
+// GC_TODO: PciAddress - add argument and description to function comment
+//
+{
+
+ EFI_STATUS Status;
+ UINT8 Latency;
+ UINT8 CacheLineSize;
+
+ if (mPciRootBridgeIo == NULL) {
+ //
+ // Get root bridge in the system.
+ //
+ Status = gBS->HandleProtocol (RootBridgeHandle, &gEfiPciRootBridgeIoProtocolGuid, &mPciRootBridgeIo);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (Phase == EfiPciBeforeResourceCollection) {
+ //
+ // Program the latency register, CLS register
+ //
+ PciAddress.Register = PCI_LATENCY_TIMER_OFFSET;
+ mPciRootBridgeIo->Pci.Read (
+ mPciRootBridgeIo,
+ EfiPciWidthUint8,
+ *((UINT64 *) &PciAddress),
+ 1,
+ &Latency
+ );
+
+ //
+ // PCI-x cards come up with a default latency of 0x40. Don't touch them.
+ //
+ if (Latency == 0) {
+ Latency = DEFAULT_PCI_LATENCY;
+ mPciRootBridgeIo->Pci.Write (
+ mPciRootBridgeIo,
+ EfiPciWidthUint8,
+ *((UINT64 *) &PciAddress),
+ 1,
+ &Latency
+ );
+ }
+ //
+ // Program Cache Line Size as 64bytes
+ // 16 of DWORDs = 64bytes (0x10)
+ //
+ PciAddress.Register = PCI_CACHELINE_SIZE_OFFSET;
+ CacheLineSize = 0x10;
+ mPciRootBridgeIo->Pci.Write (
+ mPciRootBridgeIo,
+ EfiPciWidthUint8,
+ *((UINT64 *) &PciAddress),
+ 1,
+ &CacheLineSize
+ );
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+UINT64
+GetAllocAttributes (
+ IN UINTN RootBridgeIndex
+ )
+/*++
+
+Routine Description:
+
+ Returns the Allocation attributes for the BNB Root Bridge.
+
+Arguments:
+
+ RootBridgeIndex - The root bridge number. 0 based.
+
+Returns:
+
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE
+
+--*/
+{
+ //
+ // Cannot have more than one Root bridge
+ //
+ //ASSERT (RootBridgeIndex == 0);
+
+ //
+ // PCI Root Bridge does not support separate windows for Non-prefetchable
+ // and Prefetchable memory. A PCI bus driver needs to include requests for
+ // Prefetchable memory in the Non-prefetchable memory pool.
+ // Further TNB does not support 64 bit memory apertures for PCI. BNB
+ // can only have system memory above 4 GB,
+ //
+
+ return EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
+}
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostResource.h b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostResource.h
new file mode 100755
index 0000000..4d6acaf
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostResource.h
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciHostResource.h
+
+Abstract:
+
+ The Header file of the Pci Host Bridge Driver.
+
+Revision History:
+
+--*/
+
+#ifndef _PCI_HOST_RESOURCE_H_
+#define _PCI_HOST_RESOURCE_H_
+
+#include <PiDxe.h>
+
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFF
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFE
+
+typedef struct {
+ UINTN BusBase;
+ UINTN BusLimit;
+ UINTN BusReserve;
+
+ UINT32 Mem32Base;
+ UINT32 Mem32Limit;
+
+ UINT64 Mem64Base;
+ UINT64 Mem64Limit;
+
+ UINTN IoBase;
+ UINTN IoLimit;
+} PCI_ROOT_BRIDGE_RESOURCE_APERTURE;
+
+typedef enum {
+ TypeIo = 0,
+ TypeMem32,
+ TypePMem32,
+ TypeMem64,
+ TypePMem64,
+ TypeBus,
+ TypeMax
+} PCI_RESOURCE_TYPE;
+
+typedef enum {
+ ResNone = 0,
+ ResSubmitted,
+ ResRequested,
+ ResAllocated,
+ ResStatusMax
+} RES_STATUS;
+
+typedef struct {
+ PCI_RESOURCE_TYPE Type;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Alignment;
+ RES_STATUS Status;
+} PCI_RES_NODE;
+
+#endif
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridge.h b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridge.h
new file mode 100755
index 0000000..62eede7
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridge.h
@@ -0,0 +1,727 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciRootBridge.h
+
+Abstract:
+
+ The PCI Root Bridge header file.
+
+Revision History:
+
+--*/
+
+#ifndef _PCI_ROOT_BRIDGE_H_
+#define _PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+#include <PciHostResource.h>
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/Metronome.h>
+#include <Protocol/CpuIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/IioUds.h>
+#include <Protocol/Runtime.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+
+
+//
+// Define the region of memory used for DMA memory
+//
+#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL
+
+//
+// The number of PCI root bridges
+//
+#define ROOT_BRIDGE_COUNT MaxIIO
+
+//
+// The default latency for controllers
+//
+#define DEFAULT_PCI_LATENCY 0x20
+
+//
+// Define resource status constant
+//
+typedef struct {
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
+ UINTN NumberOfBytes;
+ UINTN NumberOfPages;
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;
+} MAP_INFO;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('e', '2', 'p', 'b')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_LIST_ENTRY Link;
+ EFI_HANDLE Handle;
+ UINT64 RootBridgeAllocAttrib;
+ UINT64 Attributes;
+ UINT64 Supports;
+ PCI_RES_NODE ResAllocNode[6];
+ PCI_ROOT_BRIDGE_RESOURCE_APERTURE Aperture;
+ EFI_LOCK PciLock;
+ UINTN PciAddress;
+ UINTN PciData;
+ UINT32 HecBase;
+ UINT32 HecLen;
+ UINTN BusScanCount;
+ BOOLEAN BusNumberAssigned;
+ VOID *ConfigBuffer;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+} PCI_ROOT_BRIDGE_INSTANCE;
+
+//
+// Driver Instance Data Macros
+//
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+#define DRIVER_INSTANCE_FROM_LIST_ENTRY(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)
+
+EFI_STATUS
+SimpleIioRootBridgeConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAppeture,
+ IN UINT64 AllocAttributes
+ )
+/*++
+
+Routine Description:
+
+ Construct the Pci Root Bridge Io protocol.
+
+Arguments:
+
+ Protocol - Protocol to initialize.
+ HostBridgeHandle - Handle to the HostBridge.
+ ResAppeture - Resource apperture of the root bridge.
+ AllocAttributes - Attribute of resouce allocated.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ Others - Fail.
+
+--*/
+;
+
+//
+// Protocol Member Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ Poll an address in memory mapped space until an exit condition is met
+ or a timeout occurs.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - Width of the memory operation.
+ Address - The base address of the memory operation.
+ Mask - Mask used for polling criteria.
+ Value - Comparison value used for polling exit criteria.
+ Delay - Number of 100ns units to poll.
+ Result - Pointer to the last value read from memory location.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_TIMEOUT - Delay expired before a match occurred.
+ EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ Poll an address in I/O space until an exit condition is met
+ or a timeout occurs.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - Width of I/O operation.
+ Address - The base address of the I/O operation.
+ Mask - Mask used for polling criteria.
+ Value - Comparison value used for polling exit criteria.
+ Delay - Number of 100ns units to poll.
+ Result - Pointer to the last value read from memory location.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_TIMEOUT - Delay expired before a match occurred.
+ EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allow read from memory mapped I/O space.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - The width of memory operation.
+ Address - Base address of the memory operation.
+ Count - Number of memory opeartion to perform.
+ Buffer - The destination buffer to store data.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allow write to memory mapped I/O space.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - The width of memory operation.
+ Address - Base address of the memory operation.
+ Count - Number of memory opeartion to perform.
+ Buffer - The source buffer to write data from.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+/*++
+
+Routine Description:
+
+ Enable a PCI driver to read PCI controller registers in the
+ PCI root bridge I/O space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Width - Signifies the width of the memory operation.
+ UserAddress - The base address of the I/O operation.
+ Count - The number of I/O operations to perform.
+ UserBuffer - The destination buffer to store the results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the PCI root bridge.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+/*++
+
+Routine Description:
+
+ Enable a PCI driver to write to PCI controller registers in the
+ PCI root bridge I/O space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Width - Signifies the width of the memory operation.
+ UserAddress - The base address of the I/O operation.
+ Count - The number of I/O operations to perform.
+ UserBuffer - The source buffer to write data from.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the PCI root bridge.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ )
+/*++
+
+Routine Description:
+
+ Copy one region of PCI root bridge memory space to be copied to
+ another region of PCI root bridge memory space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - Signifies the width of the memory operation.
+ DestAddress - Destination address of the memory operation.
+ SrcAddress - Source address of the memory operation.
+ Count - Number of memory operations to perform.
+
+Returns:
+
+ EFI_SUCCESS - The data was copied successfully.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allows read from PCI configuration space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Width - Signifies the width of the memory operation.
+ Address - The address within the PCI configuration space
+ for the PCI controller.
+ Count - The number of PCI configuration operations
+ to perform.
+ Buffer - The destination buffer to store the results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the PCI root bridge.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allows write to PCI configuration space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Width - Signifies the width of the memory operation.
+ Address - The address within the PCI configuration space
+ for the PCI controller.
+ Count - The number of PCI configuration operations
+ to perform.
+ Buffer - The source buffer to get the results.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the PCI root bridge.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ Provides the PCI controller-specific address needed to access
+ system memory for DMA.
+
+Arguments:
+
+ This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ Operation - Indicate if the bus master is going to read or write
+ to system memory.
+ HostAddress - The system memory address to map on the PCI controller.
+ NumberOfBytes - On input the number of bytes to map.
+ On output the number of bytes that were mapped.
+ DeviceAddress - The resulting map address for the bus master PCI
+ controller to use to access the system memory's HostAddress.
+ Mapping - The value to pass to Unmap() when the bus master DMA
+ operation is complete.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common
+ buffer.
+ EFI_DEVICE_ERROR - The System hardware could not map the requested
+ address.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to
+ lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ Completes the Map() operation and releases any corresponding resources.
+
+Arguments:
+
+ This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Mapping - The value returned from Map() operation.
+
+Returns:
+
+ EFI_SUCCESS - The range was unmapped successfully.
+ EFI_INVALID_PARAMETER - Mapping is not a value that was returned
+ by Map operation.
+ EFI_DEVICE_ERROR - The data was not committed to the target
+ system memory.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages that are suitable for a common buffer mapping.
+
+Arguments:
+
+ This - Pointer to EFI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Type - Not used and can be ignored.
+ MemoryType - Type of memory to allocate.
+ Pages - Number of pages to allocate.
+ HostAddress - Pointer to store the base system memory address
+ of the allocated range.
+ Attributes - Requested bit mask of attributes of the allocated
+ range.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory range were allocated.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_UNSUPPORTED - Attributes is unsupported.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Free memory allocated in AllocateBuffer.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ instance.
+ Pages - Number of pages to free.
+ HostAddress - The base system memory address of the
+ allocated range.
+
+Returns:
+
+ EFI_SUCCESS - Requested memory pages were freed.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Flushes all PCI posted write transactions from a PCI host
+ bridge to system memory.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+
+Returns:
+
+ EFI_SUCCESS - PCI posted write transactions were flushed
+ from PCI host bridge to system memory.
+ EFI_DEVICE_ERROR - Fail due to hardware error.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ )
+/*++
+
+Routine Description:
+
+ Get the attributes that a PCI root bridge supports and
+ the attributes the PCI root bridge is currently using.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ instance.
+ Supports - A pointer to the mask of attributes that
+ this PCI root bridge supports.
+ Attributes - A pointer to the mask of attributes that
+ this PCI root bridge is currently using.
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+
+--*/
+
+// GC_TODO: Supported - add argument and description to function comment
+//
+// GC_TODO: Supported - add argument and description to function comment
+//
+// GC_TODO: Supported - add argument and description to function comment
+//
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+/*++
+
+Routine Description:
+
+ Sets the attributes for a resource range on a PCI root bridge.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Attributes - The mask of attributes to set.
+ ResourceBase - Pointer to the base address of the resource range
+ to be modified by the attributes specified by Attributes.
+ ResourceLength - Pointer to the length of the resource range to be modified.
+
+Returns:
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_OUT_OF_RESOURCES - Not enough resources to set the attributes upon.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the current resource settings of this PCI root bridge
+ in the form of a set of ACPI 2.0 resource descriptor.
+
+Arguments:
+
+ This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Resources - Pointer to the ACPI 2.0 resource descriptor that
+ describe the current configuration of this PCI root
+ bridge.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_UNSUPPORTED - Current configuration of the PCI root bridge
+ could not be retrieved.
+
+--*/
+;
+
+#endif
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c
new file mode 100755
index 0000000..697525e
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c
@@ -0,0 +1,1640 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciRootBridgeIo.c
+
+Abstract:
+
+ IIO PCI Root Bridge Io Protocol code. Generic enough to work for all IIOs.
+ Does not support configuration accesses to the extended PCI Express registers yet.
+
+--*/
+
+#include "PciRootBridge.h"
+#include "Iio/IioRegs.h"
+#include "Iio/PciAccess.h"
+
+
+//
+// Pci Root Bridge Io Module Variables
+//
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+EFI_CPU_IO_PROTOCOL *mCpuIo;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+EFI_STATUS
+SimpleIioRootBridgeConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture,
+ UINT64 AllocAttributes
+
+ )
+/*++
+
+Routine Description:
+
+ Construct the Pci Root Bridge Io protocol.
+
+Arguments:
+
+ Protocol - Protocol to initialize.
+ HostBridgeHandle - Handle to the HostBridge.
+ ResAperture - Resource apperture of the root bridge.
+ AllocAttributes - Attribute of resouce allocated.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ Others - Fail.
+
+--*/
+{
+ EFI_STATUS Status;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ PCI_RESOURCE_TYPE Index;
+ UINT32 HecBase;
+ UINT32 HecSize;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
+
+ //
+ // Initialize the apertures with default values
+ //
+ CopyMem (
+ &PrivateData->Aperture,
+ ResAperture,
+ sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE)
+ );
+
+ for (Index = TypeIo; Index < TypeMax; Index++) {
+ PrivateData->ResAllocNode[Index].Type = Index;
+ PrivateData->ResAllocNode[Index].Base = 0;
+ PrivateData->ResAllocNode[Index].Length = 0;
+ PrivateData->ResAllocNode[Index].Status = ResNone;
+ }
+
+ EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
+ PrivateData->PciAddress = 0xCF8;
+ PrivateData->PciData = 0xCFC;
+
+ PrivateData->RootBridgeAllocAttrib = AllocAttributes;
+ PrivateData->Attributes = 0;
+ PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
+ EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 |
+ EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 |
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY |
+ EFI_PCI_ATTRIBUTE_VGA_IO_16;
+
+ //
+ // Don't support BASE above 4GB currently
+ // Position to bit 39:28
+ //
+ HecBase = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
+ HecSize = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressSize;
+
+ ASSERT ((HecBase & (HecSize - 1)) == 0);
+ ASSERT (HecBase != 0);
+
+ PrivateData->HecBase = HecBase;
+ PrivateData->HecLen = HecSize;
+
+ PrivateData->BusNumberAssigned = FALSE;
+ PrivateData->BusScanCount = 0;
+
+ Protocol->ParentHandle = HostBridgeHandle;
+
+ Protocol->PollMem = RootBridgeIoPollMem;
+ Protocol->PollIo = RootBridgeIoPollIo;
+
+ Protocol->Mem.Read = RootBridgeIoMemRead;
+ Protocol->Mem.Write = RootBridgeIoMemWrite;
+
+ Protocol->Io.Read = RootBridgeIoIoRead;
+ Protocol->Io.Write = RootBridgeIoIoWrite;
+
+ Protocol->CopyMem = RootBridgeIoCopyMem;
+
+ Protocol->Pci.Read = RootBridgeIoPciRead;
+ Protocol->Pci.Write = RootBridgeIoPciWrite;
+
+ Protocol->Map = RootBridgeIoMap;
+ Protocol->Unmap = RootBridgeIoUnmap;
+
+ Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
+ Protocol->FreeBuffer = RootBridgeIoFreeBuffer;
+
+ Protocol->Flush = RootBridgeIoFlush;
+
+ Protocol->GetAttributes = RootBridgeIoGetAttributes;
+ Protocol->SetAttributes = RootBridgeIoSetAttributes;
+
+ Protocol->Configuration = RootBridgeIoConfiguration;
+
+ Protocol->SegmentNumber = 0;
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, &mMetronome);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (
+ &gEfiCpuIoProtocolGuid,
+ NULL,
+ &mCpuIo
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ Poll an address in memory mapped space until an exit condition is met
+ or a timeout occurs.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - Width of the memory operation.
+ Address - The base address of the memory operation.
+ Mask - Mask used for polling criteria.
+ Value - Comparison value used for polling exit criteria.
+ Delay - Number of 100ns units to poll.
+ Result - Pointer to the last value read from memory location.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_TIMEOUT - Delay expired before a match occurred.
+ EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // No matter what, always do a single poll.
+ //
+ Status = This->Mem.Read (
+ This,
+ Width,
+ Address,
+ 1,
+ Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay != 0) {
+ //
+ // Determine the proper # of metronome ticks to wait for polling the
+ // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ // The "+1" to account for the possibility of the first tick being short
+ // because we started in the middle of a tick.
+ //
+ // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
+ // protocol definition is updated.
+ //
+ NumberOfTicks = DivU64x32Remainder (
+ Delay,
+ (UINT32) mMetronome->TickPeriod,
+ &Remainder
+ );
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks) {
+
+ mMetronome->WaitForTick (mMetronome, 1);
+
+ Status = This->Mem.Read (
+ This,
+ Width,
+ Address,
+ 1,
+ Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ Poll an address in I/O space until an exit condition is met
+ or a timeout occurs.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - Width of I/O operation.
+ Address - The base address of the I/O operation.
+ Mask - Mask used for polling criteria.
+ Value - Comparison value used for polling exit criteria.
+ Delay - Number of 100ns units to poll.
+ Result - Pointer to the last value read from memory location.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_TIMEOUT - Delay expired before a match occurred.
+ EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+
+ //
+ // No matter what, always do a single poll.
+ //
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = This->Io.Read (
+ This,
+ Width,
+ Address,
+ 1,
+ Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay != 0) {
+ //
+ // Determine the proper # of metronome ticks to wait for polling the
+ // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ // The "+1" to account for the possibility of the first tick being short
+ // because we started in the middle of a tick.
+ //
+ NumberOfTicks = DivU64x32Remainder (
+ Delay,
+ (UINT32) mMetronome->TickPeriod,
+ &Remainder
+ );
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks) {
+
+ mMetronome->WaitForTick (mMetronome, 1);
+
+ Status = This->Io.Read (
+ This,
+ Width,
+ Address,
+ 1,
+ Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allow read from memory mapped I/O space.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - The width of memory operation.
+ Address - Base address of the memory operation.
+ Count - Number of memory opeartion to perform.
+ Buffer - The destination buffer to store data.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
+
+--*/
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 ||
+ Width == EfiPciWidthUint64 ||
+ Width == EfiPciWidthFifoUint64 ||
+ Width == EfiPciWidthFillUint64 ||
+ Width >= EfiPciWidthMaximum
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ //
+ // Check memory access limit
+ //
+ if (PrivateData->Aperture.Mem64Limit > PrivateData->Aperture.Mem64Base) {
+ if (Address > PrivateData->Aperture.Mem64Limit) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ if (Address > PrivateData->Aperture.Mem32Limit) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return mCpuIo->Mem.Read (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allow write to memory mapped I/O space.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - The width of memory operation.
+ Address - Base address of the memory operation.
+ Count - Number of memory opeartion to perform.
+ Buffer - The source buffer to write data from.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
+
+--*/
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 ||
+ Width == EfiPciWidthUint64 ||
+ Width == EfiPciWidthFifoUint64 ||
+ Width == EfiPciWidthFillUint64 ||
+ Width >= EfiPciWidthMaximum
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ //
+ // Check memory access limit
+ //
+ if (PrivateData->Aperture.Mem64Limit > PrivateData->Aperture.Mem64Base) {
+ if (Address > PrivateData->Aperture.Mem64Limit) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ if (Address > PrivateData->Aperture.Mem32Limit) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return mCpuIo->Mem.Write (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Enable a PCI driver to read PCI controller registers in the
+ PCI root bridge I/O space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Width - Signifies the width of the memory operation.
+ Address - The base address of the I/O operation.
+ Count - The number of I/O operations to perform.
+ Buffer - The destination buffer to store the results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the PCI root bridge.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+{
+
+ UINTN AlignMask;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 ||
+ Width == EfiPciWidthUint64 ||
+ Width == EfiPciWidthFifoUint64 ||
+ Width == EfiPciWidthFillUint64 ||
+ Width >= EfiPciWidthMaximum
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ //
+ // AlignMask = (1 << Width) - 1;
+ //
+ AlignMask = (1 << (Width & 0x03)) - 1;
+
+ //
+ // check Io access limit
+ //
+ if (Address > PrivateData->Aperture.IoLimit) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return mCpuIo->Io.Read (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Enable a PCI driver to write to PCI controller registers in the
+ PCI root bridge I/O space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Width - Signifies the width of the memory operation.
+ Address - The base address of the I/O operation.
+ Count - The number of I/O operations to perform.
+ Buffer - The source buffer to write data from.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the PCI root bridge.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+{
+ UINTN AlignMask;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 ||
+ Width == EfiPciWidthUint64 ||
+ Width == EfiPciWidthFifoUint64 ||
+ Width == EfiPciWidthFillUint64 ||
+ Width >= EfiPciWidthMaximum
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ //
+ // AlignMask = (1 << Width) - 1;
+ //
+ AlignMask = (1 << (Width & 0x03)) - 1;
+
+ //
+ // Check Io access limit
+ //
+ if (Address > PrivateData->Aperture.IoLimit) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return mCpuIo->Io.Write (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ )
+/*++
+
+Routine Description:
+
+ Copy one region of PCI root bridge memory space to be copied to
+ another region of PCI root bridge memory space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Width - Signifies the width of the memory operation.
+ DestAddress - Destination address of the memory operation.
+ SrcAddress - Source address of the memory operation.
+ Count - Number of memory operations to perform.
+
+Returns:
+
+ EFI_SUCCESS - The data was copied successfully.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN Direction;
+ UINTN Stride;
+ UINTN Index;
+ UINT64 Result;
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddress == SrcAddress) {
+ return EFI_SUCCESS;
+ }
+
+ Stride = (UINTN)1 << Width;
+
+ Direction = TRUE;
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+ Direction = FALSE;
+ SrcAddress = SrcAddress + (Count - 1) * Stride;
+ DestAddress = DestAddress + (Count - 1) * Stride;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ Status = RootBridgeIoMemRead (
+ This,
+ Width,
+ SrcAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = RootBridgeIoMemWrite (
+ This,
+ Width,
+ DestAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Direction) {
+ SrcAddress += Stride;
+ DestAddress += Stride;
+ } else {
+ SrcAddress -= Stride;
+ DestAddress -= Stride;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+RootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ PCI_CONFIG_ACCESS_CF8 Pci;
+ PCI_CONFIG_ACCESS_CF8 PciAligned;
+ UINT32 Stride;
+ UINTN PciData;
+ UINTN PciDataStride;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*)&UserAddress)->ExtendedRegister == 0x00);
+
+ Stride = 1 << Width;
+
+ Pci.Bits.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register;
+ Pci.Bits.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Function;
+ Pci.Bits.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Device;
+ Pci.Bits.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Bus;
+ Pci.Bits.Reserved = 0;
+ Pci.Bits.Enable = 1;
+
+ //
+ // PCI Configure access are all 32-bit aligned, but by accessing the
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ // are possible on PCI.
+ //
+ // To read a byte of PCI configuration space you load 0xcf8 and
+ // read 0xcfc, 0xcfd, 0xcfe, 0xcff
+ //
+ PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register & 0x03;
+
+ while (Count) {
+ PciAligned = Pci;
+ PciAligned.Bits.Reg &= 0xfc;
+ PciData = PrivateData->PciData + PciDataStride;
+ EfiAcquireLock(&PrivateData->PciLock);
+ This->Io.Write (This, EfiPciWidthUint32, \
+ PrivateData->PciAddress, 1, &PciAligned);
+ if (Write) {
+ This->Io.Write (This, Width, PciData, 1, UserBuffer);
+ } else {
+ This->Io.Read (This, Width, PciData, 1, UserBuffer);
+ }
+ EfiReleaseLock(&PrivateData->PciLock);
+ UserBuffer = ((UINT8 *)UserBuffer) + Stride;
+ PciDataStride = (PciDataStride + Stride) % 4;
+ Count -= 1;
+
+ //
+ // Only increment the PCI address if Width is not a FIFO.
+ //
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
+ Pci.Bits.Reg += Stride;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allows read from PCI configuration space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Width - Signifies the width of the memory operation.
+ Address - The address within the PCI configuration space
+ for the PCI controller.
+ Count - The number of PCI configuration operations
+ to perform.
+ Buffer - The destination buffer to store the results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the PCI root bridge.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFn;
+ UINT32 PciExtReg;
+ UINT64 ExtConfigAdd;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 ||
+ Width == EfiPciWidthUint64 ||
+ Width == EfiPciWidthFifoUint64 ||
+ Width == EfiPciWidthFillUint64 ||
+ Width >= EfiPciWidthMaximum
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Read Pci configuration space
+ //
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (PrivateData->HecBase == 0) {
+ return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+ }
+
+ if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
+ PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
+ } else {
+ PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
+ }
+
+ PciBus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
+ PciDev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
+ PciFn = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
+
+ ExtConfigAdd = (UINT64) PrivateData->HecBase + PCIE_OFF (PciBus, PciDev, PciFn, PciExtReg);
+
+ return mCpuIo->Mem.Read (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ ExtConfigAdd,
+ Count,
+ Buffer
+ );
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allows write to PCI configuration space.
+
+Arguments:
+
+ This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Width - Signifies the width of the memory operation.
+ Address - The address within the PCI configuration space
+ for the PCI controller.
+ Count - The number of PCI configuration operations
+ to perform.
+ Buffer - The source buffer to get the results.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the PCI root bridge.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
+ resources.
+--*/
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFn;
+ UINT32 PciExtReg;
+ UINT64 ExtConfigAdd;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Write Pci configuration space
+ //
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (PrivateData->HecBase == 0) {
+ return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+ }
+
+ if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
+ PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
+ } else {
+ PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
+ }
+
+ PciBus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
+ PciDev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
+ PciFn = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
+
+ ExtConfigAdd = (UINT64) PrivateData->HecBase + PCIE_OFF (PciBus, PciDev, PciFn, PciExtReg);
+
+ return mCpuIo->Mem.Write (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ ExtConfigAdd,
+ Count,
+ Buffer
+ );
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ Provides the PCI controller-specific address needed to access
+ system memory for DMA.
+
+Arguments:
+
+ This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ Operation - Indicate if the bus master is going to read or write
+ to system memory.
+ HostAddress - The system memory address to map on the PCI controller.
+ NumberOfBytes - On input the number of bytes to map.
+ On output the number of bytes that were mapped.
+ DeviceAddress - The resulting map address for the bus master PCI
+ controller to use to access the system memory's HostAddress.
+ Mapping - The value to pass to Unmap() when the bus master DMA
+ operation is complete.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameters found.
+ EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common
+ buffer.
+ EFI_DEVICE_ERROR - The System hardware could not map the requested
+ address.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to
+ lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ MAP_INFO *MapInfo;
+
+ if (NumberOfBytes == NULL || Mapping == NULL || DeviceAddress == NULL || HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize the return values to their defaults
+ //
+ *Mapping = NULL;
+
+ //
+ // Make sure that Operation is valid
+ //
+ if ((Operation < 0) || (Operation > EfiPciOperationBusMasterCommonBuffer64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Most PCAT like chipsets can not handle performing DMA above 4GB.
+ // If any part of the DMA transfer being mapped is above 4GB, then
+ // map the DMA transfer to a buffer below 4GB.
+ //
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+ if ((PhysicalAddress +*NumberOfBytes) > 0x100000000) {
+ //
+ // Common Buffer operations can not be remapped. If the common buffer
+ // if above 4GB, then it is not possible to generate a mapping, so return
+ // an error.
+ //
+ if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if ((PhysicalAddress + *NumberOfBytes) > (DMA_MEMORY_TOP+1)) {
+
+ //
+ // Common Buffer operations can not be remapped.
+ //
+ if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+ *DeviceAddress = PhysicalAddress;
+ return EFI_SUCCESS;
+ }
+ //
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+ // called later.
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (MAP_INFO),
+ &MapInfo
+ );
+ if (EFI_ERROR (Status)) {
+ *NumberOfBytes = 0;
+ return Status;
+ }
+ //
+ // Return a pointer to the MAP_INFO structure in Mapping
+ //
+ *Mapping = MapInfo;
+
+ //
+ // Initialize the MAP_INFO structure
+ //
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
+ MapInfo->HostAddress = PhysicalAddress;
+ MapInfo->MappedHostAddress = DMA_MEMORY_TOP;
+
+ //
+ // Allocate a buffer below DMA_MEMORY_TOP to map the transfer to.
+ //
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ MapInfo->NumberOfPages,
+ &MapInfo->MappedHostAddress
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (MapInfo);
+ *NumberOfBytes = 0;
+ return Status;
+ }
+ //
+ // If this is a read operation from the Bus Master's point of view,
+ // then copy the contents of the real buffer into the mapped buffer
+ // so the Bus Master can read the contents of the real buffer.
+ //
+ if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
+ CopyMem (
+ (VOID *) (UINTN) MapInfo->MappedHostAddress,
+ (VOID *) (UINTN) MapInfo->HostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+ //
+ // The DeviceAddress is the address of the maped buffer below DMA_MEMORY_TOP
+ //
+ *DeviceAddress = MapInfo->MappedHostAddress;
+ } else {
+ //
+ // The transfer is below DMA_MEMORY_TOP, so the DeviceAddress is simply the HostAddress
+ //
+ *DeviceAddress = PhysicalAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ Completes the Map() operation and releases any corresponding resources.
+
+Arguments:
+
+ This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Mapping - The value returned from Map() operation.
+
+Returns:
+
+ EFI_SUCCESS - The range was unmapped successfully.
+ EFI_INVALID_PARAMETER - Mapping is not a value that was returned
+ by Map operation.
+ EFI_DEVICE_ERROR - The data was not committed to the target
+ system memory.
+
+--*/
+{
+ MAP_INFO *MapInfo;
+
+ //
+ // See if the Map() operation associated with this Unmap() required a mapping buffer.
+ // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
+ //
+ if (Mapping != NULL) {
+ //
+ // Get the MAP_INFO structure from Mapping
+ //
+ MapInfo = (MAP_INFO *) Mapping;
+
+ //
+ // If this is a write operation from the Bus Master's point of view,
+ // then copy the contents of the mapped buffer into the real buffer
+ // so the processor can read the contents of the real buffer.
+ //
+ if ((MapInfo->Operation == EfiPciOperationBusMasterWrite) ||
+ (MapInfo->Operation == EfiPciOperationBusMasterWrite64)
+ ) {
+ CopyMem (
+ (VOID *) (UINTN) MapInfo->HostAddress,
+ (VOID *) (UINTN) MapInfo->MappedHostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+ //
+ // Free the mapped buffer and the MAP_INFO structure.
+ //
+ gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
+ gBS->FreePool (Mapping);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages that are suitable for a common buffer mapping.
+
+Arguments:
+
+ This - Pointer to EFI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Type - Not used and can be ignored.
+ MemoryType - Type of memory to allocate.
+ Pages - Number of pages to allocate.
+ HostAddress - Pointer to store the base system memory address
+ of the allocated range.
+ Attributes - Requested bit mask of attributes of the allocated
+ range.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory range were allocated.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_UNSUPPORTED - Attributes is unsupported.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+
+ //
+ // Validate Attributes
+ //
+ if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Check for invalid inputs
+ //
+ if (HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+ //
+ if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Limit allocations to memory below DMA_MEMORY_TOP
+ //
+ PhysicalAddress = DMA_MEMORY_TOP;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ MemoryType,
+ Pages,
+ &PhysicalAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *HostAddress = (VOID *) (UINTN) PhysicalAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Free memory allocated in AllocateBuffer.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ instance.
+ Pages - Number of pages to free.
+ HostAddress - The base system memory address of the
+ allocated range.
+
+Returns:
+
+ EFI_SUCCESS - Requested memory pages were freed.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+
+--*/
+{
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Flushes all PCI posted write transactions from a PCI host
+ bridge to system memory.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+
+Returns:
+
+ EFI_SUCCESS - PCI posted write transactions were flushed
+ from PCI host bridge to system memory.
+ EFI_DEVICE_ERROR - Fail due to hardware error.
+
+--*/
+{
+ //
+ // not supported yet
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ )
+/*++
+
+Routine Description:
+
+ Get the attributes that a PCI root bridge supports and
+ the attributes the PCI root bridge is currently using.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ instance.
+ Supports - A pointer to the mask of attributes that
+ this PCI root bridge supports.
+ Attributes - A pointer to the mask of attributes that
+ this PCI root bridge is currently using.
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+
+--*/
+
+// GC_TODO: Supported - add argument and description to function comment
+//
+// GC_TODO: Supported - add argument and description to function comment
+//
+// GC_TODO: Supported - add argument and description to function comment
+//
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (Attributes == NULL && Supported == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Set the return value for Supported and Attributes
+ //
+ if (Supported) {
+ *Supported = PrivateData->Supports;
+ }
+
+ if (Attributes) {
+ *Attributes = PrivateData->Attributes;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+/*++
+
+Routine Description:
+
+ Sets the attributes for a resource range on a PCI root bridge.
+
+Arguments:
+
+ This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Attributes - The mask of attributes to set.
+ ResourceBase - Pointer to the base address of the resource range
+ to be modified by the attributes specified by Attributes.
+ ResourceLength - Pointer to the length of the resource range to be modified.
+
+Returns:
+ EFI_SUCCESS - Success.
+ EFI_INVALID_PARAMETER - Invalid parameter found.
+ EFI_OUT_OF_RESOURCES - Not enough resources to set the attributes upon.
+
+--*/
+
+//
+// GC_TODO: EFI_UNSUPPORTED - add return value to function comment
+//
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (Attributes != 0) {
+ Attributes &= (PrivateData->Supports);
+ if (Attributes == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ if (Attributes == PrivateData->Attributes) {
+ return EFI_SUCCESS;
+ }
+ //
+ // It is just a trick for some attribute can only be enabled or disabled
+ // otherwise it can impact on other devices
+ //
+ PrivateData->Attributes = Attributes;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the current resource settings of this PCI root bridge
+ in the form of a set of ACPI 2.0 resource descriptor.
+
+Arguments:
+
+ This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ Resources - Pointer to the ACPI 2.0 resource descriptor that
+ describe the current configuration of this PCI root
+ bridge.
+
+Returns:
+
+ EFI_SUCCESS - Success.
+ EFI_UNSUPPORTED - Current configuration of the PCI root bridge
+ could not be retrieved.
+
+--*/
+
+//
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+//
+{
+ EFI_STATUS Status;
+ UINTN Idx;
+
+ PCI_ROOT_BRIDGE_INSTANCE *RbPrivateData;
+ PCI_RES_NODE *ResAllocNode;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Config;
+
+ //
+ // Get this instance of the Root Bridge.
+ //
+ RbPrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ //
+ // If the pointer is not NULL, it points to a buffer already allocated.
+ //
+ if (RbPrivateData->ConfigBuffer == NULL) {
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &RbPrivateData->ConfigBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ Config = RbPrivateData->ConfigBuffer;
+
+ ZeroMem (Config, TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+
+ for (Idx = 0; Idx < TypeMax; Idx++) {
+
+ ResAllocNode = &RbPrivateData->ResAllocNode[Idx];
+
+ if (ResAllocNode->Status != ResAllocated) {
+ continue;
+ }
+
+ switch (ResAllocNode->Type) {
+
+ case TypeIo:
+ Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ Config->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ Config->AddrRangeMin = ResAllocNode->Base;
+ Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
+ Config->AddrLen = ResAllocNode->Length;
+ break;
+
+ case TypeMem32:
+ Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Config->AddrSpaceGranularity = 32;
+ Config->AddrRangeMin = ResAllocNode->Base;
+ Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
+ Config->AddrLen = ResAllocNode->Length;
+ break;
+
+ case TypePMem32:
+ Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Config->SpecificFlag = 6;
+ Config->AddrSpaceGranularity = 32;
+ Config->AddrRangeMin = ResAllocNode->Base;
+ Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
+ Config->AddrLen = ResAllocNode->Length;
+ break;
+
+ case TypeMem64:
+ Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Config->SpecificFlag = 6;
+ Config->AddrSpaceGranularity = 64;
+ Config->AddrRangeMin = ResAllocNode->Base;
+ Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
+ Config->AddrLen = ResAllocNode->Length;
+ break;
+
+ case TypePMem64:
+ Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Config->SpecificFlag = 6;
+ Config->AddrSpaceGranularity = 64;
+ Config->AddrRangeMin = ResAllocNode->Base;
+ Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
+ Config->AddrLen = ResAllocNode->Length;
+ break;
+
+ case TypeBus:
+ Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ Config->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
+ Config->AddrRangeMin = ResAllocNode->Base;
+ Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
+ Config->AddrLen = ResAllocNode->Length;
+ break;
+
+ default:
+ break;
+ }
+
+ Config++;
+ }
+ //
+ // Terminate the entries.
+ //
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Checksum = 0x0;
+
+ *Resources = RbPrivateData->ConfigBuffer;
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciPlatform/CommonHeader.h b/QuarkPlatformPkg/Pci/Dxe/PciPlatform/CommonHeader.h
new file mode 100644
index 0000000..c9151c1
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciPlatform/CommonHeader.h
@@ -0,0 +1,56 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+
+#include <PiDxe.h>
+#include <QuarkPlatformDxe.h>
+#include <IntelQNCDxe.h>
+
+#include <Protocol/PciPlatform.h>
+#include <Protocol/PciIo.h>
+
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/IohLib.h>
+
+#endif
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.c b/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.c
new file mode 100644
index 0000000..9a5ef05
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.c
@@ -0,0 +1,226 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciPlatform.c
+
+Abstract:
+
+ Registers onboard PCI ROMs with PCI.IO
+Revision History
+
+--*/
+
+#include "CommonHeader.h"
+
+#include "PciPlatform.h"
+
+
+PCI_OPTION_ROM_TABLE mPciOptionRomTable[] = {
+ { NULL_ROM_FILE_GUID, 0, 0, 0, 0, 0xffff, 0xffff }
+};
+EFI_PCI_PLATFORM_PROTOCOL mPciPlatform = {
+ PhaseNotify,
+ PlatformPrepController,
+ GetPlatformPolicy,
+ GetPciRom
+};
+
+EFI_HANDLE mPciPlatformHandle = NULL;
+EFI_HANDLE mImageHandle = NULL;
+
+
+EFI_STATUS
+PhaseNotify (
+ IN EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE HostBridge,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase,
+ IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
+ )
+{
+ UINT8 UsbHostBusNumber = 0;
+ if (Phase == EfiPciHostBridgeEndResourceAllocation) {
+ // Required for QuarkSouthCluster.
+ // Enable USB controller memory, io and bus master before Ehci driver.
+ EnableUsbMemIoBusMaster (UsbHostBusNumber);
+ return EFI_SUCCESS;
+ }
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+PlatformPrepController (
+ IN EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE HostBridge,
+ IN EFI_HANDLE RootBridge,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase,
+ IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+GetPlatformPolicy (
+ IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
+ OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
+ )
+{
+ if (PciPolicy == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+GetPciRom (
+ IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE PciHandle,
+ OUT VOID **RomImage,
+ OUT UINTN *RomSize
+ )
+/*++
+
+ Routine Description:
+ Return a PCI ROM image for the onboard device represented by PciHandle
+
+ Arguments:
+ This - Protocol instance pointer.
+ PciHandle - PCI device to return the ROM image for.
+ RomImage - PCI Rom Image for onboard device
+ RomSize - Size of RomImage in bytes
+
+ Returns:
+ EFI_SUCCESS - RomImage is valid
+ EFI_NOT_FOUND - No RomImage
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 DeviceClass;
+ UINTN TableIndex;
+
+ Status = gBS->HandleProtocol (
+ PciHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0x0A, 1, &DeviceClass);
+
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0, 1, &VendorId);
+
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 2, 1, &DeviceId);
+
+ //
+ // Loop through table of video option rom descriptions
+ //
+ for (TableIndex = 0; mPciOptionRomTable[TableIndex].VendorId != 0xffff; TableIndex++) {
+
+ //
+ // See if the PCI device specified by PciHandle matches at device in mPciOptionRomTable
+ //
+ if (VendorId != mPciOptionRomTable[TableIndex].VendorId ||
+ DeviceId != mPciOptionRomTable[TableIndex].DeviceId ||
+ Segment != mPciOptionRomTable[TableIndex].Segment ||
+ Bus != mPciOptionRomTable[TableIndex].Bus ||
+ Device != mPciOptionRomTable[TableIndex].Device ||
+ Function != mPciOptionRomTable[TableIndex].Function) {
+ continue;
+ }
+
+ Status = GetSectionFromFv (
+ &mPciOptionRomTable[TableIndex].FileName,
+ EFI_SECTION_RAW,
+ 0,
+ RomImage,
+ RomSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+PciPlatformDriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ mImageHandle = ImageHandle;
+
+ //
+ // Install on a new handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mPciPlatformHandle,
+ &gEfiPciPlatformProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPciPlatform
+ );
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.h b/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.h
new file mode 100644
index 0000000..d481a27
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.h
@@ -0,0 +1,112 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PciPlatform.h
+
+Abstract:
+ This code supports a the private implementation
+ of the Legacy BIOS Platform protocol
+
+--*/
+
+#ifndef PCI_PLATFORM_H_
+#define PCI_PLATFORM_H_
+
+#include <IndustryStandard/Pci.h>
+#include <Library/PcdLib.h>
+//
+// Global variables for Option ROMs
+//
+#define NULL_ROM_FILE_GUID \
+{ 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+
+#define ONBOARD_VIDEO_OPTION_ROM_FILE_GUID \
+{ 0x8dfae5d4, 0xb50e, 0x4c10, 0x96, 0xe6, 0xf2, 0xc2, 0x66, 0xca, 0xcb, 0xb6 }
+
+#define IDE_RAID_OPTION_ROM_FILE_GUID \
+{ 0x3392A8E1, 0x1881, 0x4398, 0x83, 0xa6, 0x53, 0xd3, 0x87, 0xdb, 0x20, 0x20 }
+
+#define TANX_UNDI_OPTION_ROM_FILE_GUID \
+{ 0x84c24ab0, 0x124e, 0x4aed, 0x8e, 0xfe, 0xf9, 0x1b, 0xb9, 0x73, 0x69, 0xf4 }
+
+#define PXE_UNDI_OPTION_ROM_FILE_GUID \
+{ 0xea34cd48, 0x5fdf, 0x46f0, 0xb5, 0xfa, 0xeb, 0xe0, 0x76, 0xa4, 0xf1, 0x2c }
+
+
+typedef struct {
+ EFI_GUID FileName;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ UINT16 VendorId;
+ UINT16 DeviceId;
+} PCI_OPTION_ROM_TABLE;
+
+
+EFI_STATUS
+PhaseNotify (
+ IN EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE HostBridge,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase,
+ IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
+ );
+
+
+EFI_STATUS
+PlatformPrepController (
+ IN EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE HostBridge,
+ IN EFI_HANDLE RootBridge,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase,
+ IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
+ );
+
+EFI_STATUS
+GetPlatformPolicy (
+ IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
+ OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
+ );
+
+EFI_STATUS
+GetPciRom (
+ IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE PciHandle,
+ OUT VOID **RomImage,
+ OUT UINTN *RomSize
+ );
+
+#endif
+
+
diff --git a/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.inf b/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.inf
new file mode 100644
index 0000000..2cc374b
--- /dev/null
+++ b/QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.inf
@@ -0,0 +1,79 @@
+## @file
+# Component description file for PciPlatform module.
+#
+# This driver installs pciplatform protocol to provide access interfaces to the onboard pci roms.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PciPlatform
+ FILE_GUID = 2E8CD01A-BDB7-40b4-8376-E7C26EAC21FF
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PciPlatformDriverEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PciPlatform.c
+ PciPlatform.h
+ CommonHeader.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PciLib
+ PcdLib
+ IohLib
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DxeServicesLib
+
+[Guids]
+
+[Protocols]
+ gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiPciPlatformProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[Pcd]
+
+[Depex]
+ TRUE
diff --git a/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.c b/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.c
new file mode 100644
index 0000000..b864240
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.c
@@ -0,0 +1,459 @@
+/**@file
+ This is the driver that locates the MemoryConfigurationData Variable, if it
+ exists, and reports the data to the DataHub.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "MemorySubClass.h"
+
+extern UINT8 MemorySubClassStrings[];
+
+EFI_GUID gEfiMemorySubClassDriverGuid = EFI_MEMORY_SUBCLASS_DRIVER_GUID;
+
+EFI_STATUS
+MemorySubClassEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+ Routine Description:
+ This is the standard EFI driver point that detects whether there is a
+ MemoryConfigurationData Variable and, if so, reports memory configuration info
+ to the DataHub.
+
+ Arguments:
+ ImageHandle - Handle for the image of this driver
+ SystemTable - Pointer to the EFI System Table
+
+ Returns:
+ EFI_SUCCESS if the data is successfully reported
+ EFI_NOT_FOUND if the HOB list could not be located.
+
+--*/
+{
+// UINT8 Index;
+ UINTN DataSize;
+ UINT8 Dimm;
+ UINTN StringBufferSize;
+ UINT8 NumSlots;
+ UINTN DevLocStrLen;
+ UINTN BankLocStrLen;
+ UINTN ManuStrLen;
+ UINTN SerialNumStrLen;
+ UINTN AssertTagStrLen;
+ UINTN PartNumStrLen;
+ UINTN MemoryDeviceSize;
+ CHAR8* OptionalStrStart;
+ UINT16 ArrayInstance;
+ UINT64 DimmMemorySize;
+ UINT64 TotalMemorySize;
+ UINT32 Data;
+ UINT32 MemoryCapacity;
+ BOOLEAN MemoryDeviceSizeUnitMega;
+ EFI_STATUS Status;
+ EFI_STRING StringBuffer;
+ EFI_STRING DevLocStr;
+ EFI_STRING BankLocStr;
+ EFI_STRING ManuStr;
+ EFI_STRING SerialNumStr;
+ EFI_STRING AssertTagStr;
+ EFI_STRING PartNumStr;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_SMBIOS_HANDLE MemArraySmbiosHandle;
+ EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle;
+ EFI_SMBIOS_HANDLE MemDevSmbiosHandle;
+ EFI_SMBIOS_HANDLE MemDevMappedAddrSmbiosHandle;
+ EFI_SMBIOS_HANDLE MemModuleInfoSmbiosHandle;
+ SMBIOS_TABLE_TYPE6 *Type6Record;
+ SMBIOS_TABLE_TYPE16 *Type16Record;
+ SMBIOS_TABLE_TYPE17 *Type17Record;
+ SMBIOS_TABLE_TYPE19 *Type19Record;
+ SMBIOS_TABLE_TYPE20 *Type20Record;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+ EFI_MEMORY_ARRAY_LINK_DATA ArrayLink;
+ EFI_MEMORY_ARRAY_LOCATION_DATA ArrayLocationData;
+ EFI_MEMORY_DEVICE_START_ADDRESS_DATA DeviceStartAddress;
+
+
+ DataSize = 0;
+ Dimm = 0;
+
+
+ //
+ // Allocate Buffers
+ //
+ StringBufferSize = (sizeof (CHAR16)) * 100;
+ StringBuffer = AllocateZeroPool (StringBufferSize);
+ ASSERT (StringBuffer != NULL);
+
+ //
+ // Locate dependent protocols
+ //
+ Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Add our default strings to the HII database. They will be modified later.
+ //
+ HiiHandle = HiiAddPackages (
+ &gEfiMemorySubClassDriverGuid,
+ NULL,
+ MemorySubClassStrings,
+ NULL
+ );
+ ASSERT (HiiHandle != NULL);
+
+ //
+ // Create physical array and associated data for all mainboard memory
+ // This will translate into a Type 16 SMBIOS Record
+ //
+ ArrayInstance = 1;
+
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_READ_DW (0x3, 0x8);
+ TotalMemorySize = McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
+
+ ArrayLocationData.MemoryArrayLocation = EfiMemoryArrayLocationSystemBoard;
+ ArrayLocationData.MemoryArrayUse = EfiMemoryArrayUseSystemMemory;
+
+ ArrayLocationData.MemoryErrorCorrection = EfiMemoryErrorCorrectionNone;
+
+ Data = 0x40000000;//(UINT32) RShiftU64(MemConfigData->RowInfo.MaxMemory, 10);
+
+ ArrayLocationData.MaximumMemoryCapacity.Exponent = (UINT16) LowBitSet32 (Data);
+ ArrayLocationData.MaximumMemoryCapacity.Value = (UINT16) (Data >> ArrayLocationData.MaximumMemoryCapacity.Exponent);
+
+ NumSlots = 2;// (UINT8)(MemConfigData->RowInfo.MaxRows >> 1);
+ ArrayLocationData.NumberMemoryDevices = (UINT16)(NumSlots);
+
+ //
+ // Report top level physical array to Type 16 SMBIOS Record
+ //
+ Type16Record = AllocatePool(sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1);
+ ZeroMem(Type16Record, sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1);
+
+ Type16Record->Hdr.Type = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY;
+ Type16Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE16);
+ Type16Record->Hdr.Handle = 0;
+
+ Type16Record->Location = (UINT8)ArrayLocationData.MemoryArrayLocation;
+
+ Type16Record->Use = (UINT8)ArrayLocationData.MemoryArrayUse;
+
+ Type16Record->MemoryErrorCorrection = (UINT8)ArrayLocationData.MemoryErrorCorrection;
+
+ MemoryCapacity = (UINT32) ArrayLocationData.MaximumMemoryCapacity.Value * (1 << ((UINT32) ArrayLocationData.MaximumMemoryCapacity.Exponent - 10));
+ Type16Record->MaximumCapacity = MemoryCapacity;
+
+ Type16Record->MemoryErrorInformationHandle = 0xfffe;
+
+ Type16Record->NumberOfMemoryDevices = ArrayLocationData.NumberMemoryDevices;
+ //
+ // Don't change it. This handle will be referenced by type 17 records
+ //
+ MemArraySmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (Smbios, NULL, &MemArraySmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type16Record);
+ FreePool(Type16Record);
+ ASSERT_EFI_ERROR (Status);
+
+ // Do associated data for each DIMM
+ //RowConfArray = &MemConfigData->RowConfArray;
+
+ //
+ // Get total memory size for the construction of smbios record type 19
+ //
+ //TotalMemorySize = 0;// MSG_BUS_READ(0x0208);
+
+ //
+ // Generate Memory Array Mapped Address info
+ //
+ Type19Record = AllocatePool(sizeof (SMBIOS_TABLE_TYPE19));
+ ZeroMem(Type19Record, sizeof(SMBIOS_TABLE_TYPE19));
+ Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS;
+ Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19);
+ Type19Record->Hdr.Handle = 0;
+ Type19Record->StartingAddress = 0;
+ Type19Record->EndingAddress = (UINT32)RShiftU64(TotalMemorySize, 10) - 1;
+ Type19Record->MemoryArrayHandle = MemArraySmbiosHandle;
+ Type19Record->PartitionWidth = (UINT8)(NumSlots);
+
+ //
+ // Generate Memory Array Mapped Address info (TYPE 19)
+ //
+ MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (Smbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type19Record);
+ FreePool(Type19Record);
+ ASSERT_EFI_ERROR (Status);
+
+
+ // Use SPD data to generate Device Type info
+ ZeroMem (&ArrayLink, sizeof (EFI_MEMORY_ARRAY_LINK_DATA));
+ ArrayLink.MemoryDeviceLocator = STRING_TOKEN(STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_0);
+ ArrayLink.MemoryBankLocator = STRING_TOKEN(STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_0);
+ ArrayLink.MemoryAssetTag = STRING_TOKEN(STR_MEMORY_SUBCLASS_UNKNOWN);
+ ArrayLink.MemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ ArrayLink.MemoryArrayLink.Instance = ArrayInstance;
+ ArrayLink.MemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+ ArrayLink.MemorySubArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ ArrayLink.MemorySubArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+ ArrayLink.MemoryFormFactor = EfiMemoryFormFactorChip;
+ ArrayLink.MemoryType = EfiMemoryTypeDdr2;
+
+
+ StrCpy (StringBuffer, L"NO DIMM,MEMROY DOWN");
+ ArrayLink.MemoryManufacturer = HiiSetString (
+ HiiHandle,
+ 0,
+ StringBuffer,
+ NULL
+ );
+ ArrayLink.MemorySerialNumber = HiiSetString (
+ HiiHandle,
+ 0,
+ StringBuffer,
+ NULL
+ );
+
+ ArrayLink.MemoryPartNumber = HiiSetString (
+ HiiHandle,
+ 0,
+ StringBuffer,
+ NULL
+ );
+
+ //
+ // Hardcode value. Need to revise for different configuration.
+ //
+ ArrayLink.MemoryTotalWidth = 64;
+ ArrayLink.MemoryDataWidth = 64;
+
+ DimmMemorySize = TotalMemorySize;// MSG_BUS_READ(0x0208);
+
+ ArrayLink.MemoryDeviceSize.Exponent = (UINT16) LowBitSet64 (DimmMemorySize);
+ ArrayLink.MemoryDeviceSize.Value = (UINT16) RShiftU64(DimmMemorySize, ArrayLink.MemoryDeviceSize.Exponent);
+ ArrayLink.MemoryTypeDetail.Synchronous = 1;
+ Data = 800;
+ ArrayLink.MemorySpeed = *((EFI_EXP_BASE10_DATA *) &Data);
+
+
+
+ DevLocStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryDeviceLocator, NULL);
+ DevLocStrLen = StrLen(DevLocStr);
+ ASSERT(DevLocStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ BankLocStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryBankLocator, NULL);
+ BankLocStrLen = StrLen(BankLocStr);
+ ASSERT(BankLocStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ ManuStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryManufacturer, NULL);
+ ManuStrLen = StrLen(ManuStr);
+ ASSERT(ManuStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ SerialNumStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemorySerialNumber, NULL);
+ SerialNumStrLen = StrLen(SerialNumStr);
+ ASSERT(SerialNumStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ AssertTagStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryAssetTag, NULL);
+ AssertTagStrLen = StrLen(AssertTagStr);
+ ASSERT(AssertTagStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ PartNumStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryPartNumber, NULL);
+ PartNumStrLen = StrLen(PartNumStr);
+ ASSERT(PartNumStrLen <= SMBIOS_STRING_MAX_LENGTH);
+
+ //
+ // Report DIMM level memory module information to smbios (Type 6)
+ //
+ DataSize = sizeof(SMBIOS_TABLE_TYPE6) + DevLocStrLen + 1 + 1;
+ Type6Record = AllocatePool(DataSize);
+ ZeroMem(Type6Record, DataSize);
+ Type6Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_MODULE_INFORMATON;
+ Type6Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE6);
+ Type6Record->Hdr.Handle = 0;
+ Type6Record->SocketDesignation = 1;
+ if (ArrayLink.MemorySpeed.Value == 0) {
+ Type6Record->CurrentSpeed = 0;
+ } else {
+ //
+ // Memory speed is in ns unit
+ //
+ Type6Record->CurrentSpeed = (UINT8)(1000 / (ArrayLink.MemorySpeed.Value));
+ }
+ //
+ // Device Size
+ //
+ MemoryDeviceSize = (UINTN)(ArrayLink.MemoryDeviceSize.Value) * (UINTN)(1 << ArrayLink.MemoryDeviceSize.Exponent);
+ if (MemoryDeviceSize == 0) {
+ *(UINT8*)&(Type6Record->InstalledSize) = 0x7F;
+ *(UINT8*)&(Type6Record->EnabledSize) = 0x7F;
+ } else {
+ MemoryDeviceSize = (UINTN) RShiftU64 ((UINT64) MemoryDeviceSize, 21);
+ while (MemoryDeviceSize != 0) {
+ (*(UINT8*)&(Type6Record->InstalledSize))++;
+ (*(UINT8*)&(Type6Record->EnabledSize))++;
+ MemoryDeviceSize = (UINTN) RShiftU64 ((UINT64) MemoryDeviceSize,1);
+ }
+ }
+
+ if (ArrayLink.MemoryFormFactor == EfiMemoryFormFactorDimm ||
+ ArrayLink.MemoryFormFactor == EfiMemoryFormFactorFbDimm) {
+ *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<8;
+ }
+ if (ArrayLink.MemoryFormFactor == EfiMemoryFormFactorSimm) {
+ *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<7;
+ }
+ if (ArrayLink.MemoryType == EfiMemoryTypeSdram) {
+ *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<10;
+ }
+ if (ArrayLink.MemoryTypeDetail.Edo == 1) {
+ *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<4;
+ }
+ if (ArrayLink.MemoryTypeDetail.FastPaged == 1) {
+ *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<3;
+ }
+ OptionalStrStart = (CHAR8 *)(Type6Record + 1);
+ UnicodeStrToAsciiStr(DevLocStr, OptionalStrStart);
+ MemModuleInfoSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (Smbios, NULL, &MemModuleInfoSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type6Record);
+ FreePool(Type6Record);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Report DIMM level Device Type to smbios (Type 17)
+ //
+ DataSize = sizeof (SMBIOS_TABLE_TYPE17) + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1 + PartNumStrLen + 1 + 1;
+ Type17Record = AllocatePool(DataSize);
+ ZeroMem(Type17Record, DataSize);
+ Type17Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
+ Type17Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17);
+ Type17Record->Hdr.Handle = 0;
+
+ Type17Record->MemoryArrayHandle = MemArraySmbiosHandle;
+ Type17Record->MemoryErrorInformationHandle = 0xfffe;
+ Type17Record->TotalWidth = ArrayLink.MemoryTotalWidth;
+ Type17Record->DataWidth = ArrayLink.MemoryDataWidth;
+ //
+ // Device Size
+ //
+ MemoryDeviceSize = ((UINTN) ArrayLink.MemoryDeviceSize.Value) << (ArrayLink.MemoryDeviceSize.Exponent - 10);
+ MemoryDeviceSizeUnitMega = FALSE;
+ //
+ // kilo as unit
+ //
+ if (MemoryDeviceSize > 0xffff) {
+ MemoryDeviceSize = MemoryDeviceSize >> 10;
+ //
+ // Mega as unit
+ //
+ MemoryDeviceSizeUnitMega = TRUE;
+ }
+
+ MemoryDeviceSize = MemoryDeviceSize & 0x7fff;
+ if (MemoryDeviceSize != 0 && MemoryDeviceSizeUnitMega == FALSE) {
+ MemoryDeviceSize |= 0x8000;
+ }
+ Type17Record->Size = (UINT16)MemoryDeviceSize;
+
+ Type17Record->FormFactor = (UINT8)ArrayLink.MemoryFormFactor;
+ Type17Record->DeviceLocator = 1;
+ Type17Record->BankLocator = 2;
+ Type17Record->MemoryType = (UINT8)ArrayLink.MemoryType;
+ CopyMem (
+ (UINT8 *) &Type17Record->TypeDetail,
+ &ArrayLink.MemoryTypeDetail,
+ 2
+ );
+
+ Type17Record->Speed = ArrayLink.MemorySpeed.Value;
+ Type17Record->Manufacturer = 3;
+ Type17Record->SerialNumber = 4;
+ Type17Record->AssetTag = 5;
+ Type17Record->PartNumber = 6;
+ //
+ // temporary solution for save device label information.
+ //
+ Type17Record->Attributes = (UINT8)(Dimm + 1);
+
+ OptionalStrStart = (CHAR8 *)(Type17Record + 1);
+ UnicodeStrToAsciiStr(DevLocStr, OptionalStrStart);
+ UnicodeStrToAsciiStr(BankLocStr, OptionalStrStart + DevLocStrLen + 1);
+ UnicodeStrToAsciiStr(ManuStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1);
+ UnicodeStrToAsciiStr(SerialNumStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1);
+ UnicodeStrToAsciiStr(AssertTagStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1);
+ UnicodeStrToAsciiStr(PartNumStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1);
+ MemDevSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (Smbios, NULL, &MemDevSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type17Record);
+ FreePool(Type17Record);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Generate Memory Device Mapped Address info
+ //
+ ZeroMem(&DeviceStartAddress, sizeof(EFI_MEMORY_DEVICE_START_ADDRESS_DATA));
+ DeviceStartAddress.MemoryDeviceStartAddress = 0;
+ DeviceStartAddress.MemoryDeviceEndAddress = DeviceStartAddress.MemoryDeviceStartAddress + DimmMemorySize-1;
+ DeviceStartAddress.PhysicalMemoryDeviceLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ DeviceStartAddress.PhysicalMemoryDeviceLink.Instance = ArrayInstance;
+ DeviceStartAddress.PhysicalMemoryDeviceLink.SubInstance = (UINT16)(Dimm + 1);
+ DeviceStartAddress.PhysicalMemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
+ DeviceStartAddress.PhysicalMemoryArrayLink.Instance = ArrayInstance;
+ DeviceStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
+
+ //
+ // Single channel mode
+ //
+ DeviceStartAddress.MemoryDevicePartitionRowPosition = 0x01;
+ DeviceStartAddress.MemoryDeviceInterleavePosition = 0x00;
+ DeviceStartAddress.MemoryDeviceInterleaveDataDepth = 0x00;
+
+ //
+ // Generate Memory Device Mapped Address info (TYPE 20)
+ //
+ Type20Record = AllocatePool(sizeof (SMBIOS_TABLE_TYPE20));
+ ZeroMem(Type20Record, sizeof (SMBIOS_TABLE_TYPE20));
+ Type20Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS;
+ Type20Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE20);
+ Type20Record->Hdr.Handle = 0;
+
+ Type20Record->StartingAddress = (UINT32)RShiftU64 (DeviceStartAddress.MemoryDeviceStartAddress, 10);
+ Type20Record->EndingAddress = (UINT32)RShiftU64 (DeviceStartAddress.MemoryDeviceEndAddress, 10);
+ Type20Record->MemoryDeviceHandle = MemDevSmbiosHandle;
+ Type20Record->MemoryArrayMappedAddressHandle = MemArrayMappedAddrSmbiosHandle;
+ Type20Record->PartitionRowPosition = DeviceStartAddress.MemoryDevicePartitionRowPosition;
+ Type20Record->InterleavePosition = DeviceStartAddress.MemoryDeviceInterleavePosition;
+ Type20Record->InterleavedDataDepth = DeviceStartAddress.MemoryDeviceInterleaveDataDepth;
+ MemDevMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (Smbios, NULL, &MemDevMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type20Record);
+ FreePool(Type20Record);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.h b/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.h
new file mode 100644
index 0000000..eec5a64
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.h
@@ -0,0 +1,89 @@
+/**@file
+ Header file for MemorySubClass Driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _MEMORY_SUB_CLASS_H
+#define _MEMORY_SUB_CLASS_H
+
+//
+// The package level header files this module uses
+//
+#include <FrameworkDxe.h>
+//
+// The protocols, PPI and GUID definitions for this module
+//
+#include <IndustryStandard/SmBios.h>
+#include <Protocol/Smbios.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/SmbusHc.h>
+#include <Guid/DataHubRecords.h>
+#include <Guid/MemoryConfigData.h>
+#include <Protocol/HiiDatabase.h>
+#include <Guid/MdeModuleHii.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciLib.h>
+#include <Library/QNCAccessLib.h>
+
+#include "QNCAccess.h"
+
+
+
+//
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+//
+
+#define EFI_MEMORY_SUBCLASS_DRIVER_GUID \
+ { 0xef17cee7, 0x267d, 0x4bfd, { 0xa2, 0x57, 0x4a, 0x6a, 0xb3, 0xee, 0x85, 0x91 }}
+
+//
+// Prototypes
+//
+EFI_STATUS
+MemorySubClassEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.inf b/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.inf
new file mode 100644
index 0000000..c03a337
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.inf
@@ -0,0 +1,84 @@
+## @file
+# Component description file for MemorySubClass module.
+#
+# This is the driver that locates the MemoryConfigurationData Variable, if it
+# exists, and reports the data to the DataHub.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MemorySubClass
+ FILE_GUID = EF17CEE7-267D-4BFD-A257-4A6AB3EE8591
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MemorySubClassEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ MemorySubClass.c
+ MemorySubClass.h
+ MemorySubClassStrings.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ HiiLib
+ PrintLib
+ BaseMemoryLib
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseLib
+ HobLib
+ PciLib
+
+[Guids]
+ gEfiMemoryConfigDataGuid # ALWAYS_CONSUMED
+
+[Protocols]
+ gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSmbusHcProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Depex]
+ gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid AND gEfiSmbiosProtocolGuid AND gEfiSmbusHcProtocolGuid
diff --git a/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClassStrings.uni b/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClassStrings.uni
new file mode 100644
index 0000000..ca8a0b7
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClassStrings.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/PlatformInit/DxeFvSecurity.c b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/DxeFvSecurity.c
new file mode 100644
index 0000000..e910ea3
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/DxeFvSecurity.c
@@ -0,0 +1,242 @@
+/** @file
+ This driver produces security architectural protocol based on SecurityManagementLib.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "DxeFvSecurity.h"
+#include <Library/QuarkBootRomLib.h>
+
+//
+// Protocol notify related globals
+//
+VOID *gEfiFwVolBlockNotifySecurityReg;
+EFI_EVENT gEfiFwVolBlockSecurityEvent;
+
+//
+// Handle for the FvbSecurity protocol.
+//
+EFI_HANDLE mFvbSecurityProtocolHandle = NULL;
+
+STATIC
+VOID
+InstallFvbSecurityProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL *FvbSecurityProtocol;
+
+ //
+ // Make sure the FvbSecurity Protocol is not already installed
+ // in the system.
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gFirmwareVolumeBlockSecurityGuid);
+
+ //
+ // Setup protocol structure.
+ //
+ FvbSecurityProtocol = (FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL *)
+ AllocateZeroPool (sizeof (FIRMWARE_VOLUME_BLOCK_SECURITY_PROTOCOL));
+
+ ASSERT (FvbSecurityProtocol != NULL);
+ FvbSecurityProtocol->SecurityAuthenticateImage = DxeSecurityVerifyFv;
+
+ //
+ // Install the FvbSecurityProtocol onto a new handle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mFvbSecurityProtocolHandle,
+ &gFirmwareVolumeBlockSecurityGuid,
+ FvbSecurityProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ This notification function is invoked when an instance of the
+ EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the
+ EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where
+ the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.
+
+ @param Event The event that occured
+ @param Context For EFI compatiblity. Not used.
+
+**/
+VOID
+EFIAPI
+FirmwareVolmeBlockNotifySecurityCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_PHYSICAL_ADDRESS FvbBaseAddress;
+ EFI_PEI_HOB_POINTERS HobPtr;
+ EFI_BOOT_MODE BootMode;
+
+ BootMode = GetBootModeHob ();
+
+ //
+ // Examine all new handles
+ //
+ for (;;) {
+ //
+ // Get the next handle
+ //
+ BufferSize = sizeof (Handle);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ gEfiFwVolBlockNotifySecurityReg,
+ &BufferSize,
+ &Handle
+ );
+
+ //
+ // If not found, we're done
+ //
+ if (EFI_NOT_FOUND == Status) {
+ break;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get the FirmwareVolumeBlock protocol on that handle
+ //
+ Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
+ if (!(EFI_ERROR (Status)) && (Fvb != NULL)) {
+ Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
+ if (!EFI_ERROR (Status)) {
+ //
+ // (1) Only authenticate new Firmware Volumes (any FV that has a HOB was already authenticated in PEI)
+ // (2) Don't authenticate the NV Storage Firmware Volume as it's contents change (can't sign)
+ //
+
+ //
+ // Check if this FV already has a HOB
+ //
+ HobPtr.Raw = GetHobList ();
+ while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV, HobPtr.Raw)) != NULL) {
+ if ((HobPtr.FirmwareVolume->BaseAddress) == (UINT32)FvbBaseAddress) {
+ break;
+ }
+ HobPtr.Raw = GET_NEXT_HOB (HobPtr);
+ }
+
+ //
+ // If this FV has no HOB and it is not the NVRAM FV then authenticate it.
+ //
+ if ((HobPtr.Raw == NULL) && (FvbBaseAddress != PcdGet32 (PcdFlashNvStorageBase))) {
+
+ //
+ // No need to check volumes which are within firmware flash items.
+ // These are checked in security boot rom or PEI stage.
+ //
+ if (!(MfhLibIsAddressWithinFwFlashItem((UINT32) FvbBaseAddress))) {
+ Status = DxeSecurityVerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) ((UINTN) FvbBaseAddress));
+ }
+ }
+ }
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ return;
+}
+
+/**
+ Calls BootRom services to verify the Firmware Volume
+
+ @param CurrentFvAddress Pointer to the current Firmware Volume under consideration
+
+ @retval EFI_SUCCESS Firmware Volume is legal
+
+**/
+EFI_STATUS
+DxeSecurityVerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Authenticate the Firmware Volume image
+ //
+ DEBUG ((DEBUG_INFO, "DxeSecurityVerifyFv - CurrentFvAddress=0x%8x\n", (UINT32)CurrentFvAddress));
+ Status = SecurityAuthenticateImage(
+ (VOID *) CurrentFvAddress,
+ NULL,
+ TRUE,
+ NULL,
+ (QUARK_AUTH_ALLOC_POOL) AllocatePool,
+ (QUARK_AUTH_FREE_POOL) FreePool
+ );
+
+ return Status;
+}
+
+/**
+ Installs Firmware Volume Security.
+
+ @retval EFI_SUCCESS Installed Firmware Volume Security successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeInitializeFvSecurity (
+ VOID
+ )
+{
+ if (mFvbSecurityProtocolHandle == NULL) {
+ InstallFvbSecurityProtocol ();
+ }
+
+ //
+ // Create a notify event any time the gEfiFirmwareVolumeBlockProtocolGuid is installed
+ //
+ gEfiFwVolBlockSecurityEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ TPL_CALLBACK,
+ FirmwareVolmeBlockNotifySecurityCallback,
+ NULL,
+ &gEfiFwVolBlockNotifySecurityReg
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/PlatformInit/DxeFvSecurity.h b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/DxeFvSecurity.h
new file mode 100644
index 0000000..4271993
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/DxeFvSecurity.h
@@ -0,0 +1,73 @@
+/** @file
+ The internal header file includes the common header files, defines
+ internal structure and functions used by Dxe Fv security module.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _DXE_SECURITY_H_
+#define _DXE_SECURITY_H_
+
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+#include <Protocol/FirmwareVolumeBlockSecurity.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/MfhLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+ Authenticates the Firmware Volume
+
+ @param CurrentFvAddress Pointer to the current Firmware Volume under consideration
+
+ @retval EFI_SUCCESS Firmware Volume is legal
+
+**/
+EFI_STATUS
+DxeSecurityVerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress
+ );
+
+/**
+ Init DXE Firmware Volume security for this platform.
+
+ @retval EFI_SUCCESS Init success
+
+**/
+EFI_STATUS
+EFIAPI
+DxeInitializeFvSecurity (
+ VOID
+ );
+#endif
diff --git a/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformConfig.c b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformConfig.c
new file mode 100644
index 0000000..db76297
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformConfig.c
@@ -0,0 +1,762 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PlatformConfig.c
+
+Abstract:
+
+ Essential platform configuration.
+
+Revision History
+
+--*/
+
+#include "PlatformInitDxe.h"
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+
+//
+// The Library classes this module consumes
+//
+
+//
+// RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE
+// Workaround to make default SMRAM UnCachable
+//
+#define SMM_DEFAULT_SMBASE 0x30000 // Default SMBASE address
+#define SMM_DEFAULT_SMBASE_SIZE_BYTES 0x10000 // Size in bytes of default SMRAM
+
+BOOLEAN mMemCfgDone = FALSE;
+BOOLEAN mPciCfgDone = FALSE;
+BOARD_GPIO_CONTROLLER_CONFIG mBoardGpioControllerConfigTable[] = { PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION };
+UINTN mBoardGpioControllerConfigTableLen = (sizeof(mBoardGpioControllerConfigTable) / sizeof(BOARD_GPIO_CONTROLLER_CONFIG));
+UINT8 ChipsetDefaultMac [6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+VOID
+EFIAPI
+SetLanControllerMacAddr (
+ IN CONST UINT8 Bus,
+ IN CONST UINT8 Device,
+ IN CONST UINT8 Func,
+ IN CONST UINT8 *MacAddr
+ )
+/*++
+
+Routine Description:
+
+ Set Mac address on chipset ethernet device.
+
+Arguments:
+ Bus - PCI Bus number of chipset ethernet device.
+ Device - PCI Device number of chipset ethernet device.
+ Func - PCI Function number of chipset ethernet device.
+ MacAddr - MAC Address to set.
+
+Returns:
+ None.
+
+--*/
+{
+ UINT32 Data32;
+ UINT8 PciCmd;
+ UINT8 Value8;
+ UINT16 PciVid;
+ UINT16 PciDid;
+ UINT32 Bar0;
+ UINT32 Addr;
+ UINT32 MacVer;
+ volatile UINT8 *Wrote;
+
+ PciVid = IohMmPci16(0, Bus, Device, Func, PCI_REG_VID);
+ PciDid = IohMmPci16(0, Bus, Device, Func, PCI_REG_DID);
+ //
+ // Read PCICMD. Bus=0, Dev=0, Func=0, Reg=0x4
+ //
+ PciCmd = IohMmPci8(0, Bus, Device, Func, PCI_REG_PCICMD);
+
+ if((PciVid == V_IOH_MAC_VENDOR_ID) && (PciDid == V_IOH_MAC_DEVICE_ID)) {
+ //
+ // Enable MMIO Space(Bit1).
+ //
+ Value8 = PciCmd | B_IOH_MAC_COMMAND_MSE;
+ IohMmPci8(0, Bus, Device, Func, PCI_REG_PCICMD) = Value8;
+
+ //
+ // Read BAR0. Bus=0, Dev=0, Func=0, Reg=0x10
+ //
+ Bar0 = IohMmPci32(0, Bus, Device, Func, R_IOH_MAC_MEMBAR) & B_IOH_MAC_MEMBAR_ADDRESS_MASK;
+
+ Addr = Bar0 + R_IOH_MAC_GMAC_REG_8;
+ MacVer = *((volatile UINT32 *) (UINTN)(Addr));
+
+ DEBUG ((EFI_D_INFO, "Ioh MAC [B:%d, D:%d, F:%d] VER:%04x ADDR:",
+ (UINTN) Bus,
+ (UINTN) Device,
+ (UINTN) Func,
+ (UINTN) MacVer
+ ));
+
+ //
+ // Set MAC Address0 Low Register (GMAC_REG_17) ADDRLO bits.
+ //
+ Addr = Bar0 + R_IOH_MAC_GMAC_REG_17;
+ Data32 = *((UINT32 *) (UINTN)(&MacAddr[0]));
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+ Wrote = (volatile UINT8 *) (UINTN)(Addr);
+ DEBUG ((EFI_D_INFO, "%02x-%02x-%02x-%02x-",
+ (UINTN) Wrote[0],
+ (UINTN) Wrote[1],
+ (UINTN) Wrote[2],
+ (UINTN) Wrote[3]
+ ));
+
+ //
+ // Set MAC Address0 High Register (GMAC_REG_16) ADDRHI bits
+ // and Address Enable (AE) bit.
+ //
+ Addr = Bar0 + R_IOH_MAC_GMAC_REG_16;
+ Data32 =
+ ((UINT32) MacAddr[4]) |
+ (((UINT32)MacAddr[5]) << 8) |
+ B_IOH_MAC_AE;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+ Wrote = (volatile UINT8 *) (UINTN)(Addr);
+
+ DEBUG ((EFI_D_INFO, "%02x-%02x\n", (UINTN) Wrote[0], (UINTN) Wrote[1]));
+
+ //
+ // Return Cmd register to initial value.
+ //
+ IohMmPci8(0, Bus, Device, Func, PCI_REG_PCICMD) = PciCmd;
+
+ }
+}
+
+EFI_STATUS
+EFIAPI
+PlatformPcal9555Config (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ PlatformType - Set PCAL9555 IO Expander config for this platform.
+
+Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN WriteLength;
+ UINT8 Data[3];
+ EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr;
+ EFI_I2C_ADDR_MODE I2CAddrMode;
+
+ if (PlatformType != GalileoFabE) {
+ return EFI_SUCCESS; // No error if plaform has no Pcal9555 IO Expander.
+ }
+
+ I2CDeviceAddr.I2CDeviceAddress = PCAL9555_GALILEO_GEN2_7BIT_SLAVE_ADDR;
+ I2CAddrMode = EfiI2CSevenBitAddrMode;
+
+ WriteLength = 3;
+ Data[0] = PCAL9555_REG_CFG_PORT0; // Write to both cfg registers.
+ Data[1] = PCAL9555_GALILEO_GEN2_PORT0_CFG;
+ Data[2] = PCAL9555_GALILEO_GEN2_PORT1_CFG;
+
+ Status = mI2cBus->WriteMultipleByte (
+ mI2cBus,
+ I2CDeviceAddr,
+ I2CAddrMode,
+ &WriteLength,
+ &Data
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ WriteLength = 3;
+ Data[0] = PCAL9555_REG_OUT_PORT0; // Write to both output registers.
+ Data[1] = PCAL9555_GALILEO_GEN2_PORT0_DEFAULT_OUT;
+ Data[2] = PCAL9555_GALILEO_GEN2_PORT1_DEFAULT_OUT;
+
+ Status = mI2cBus->WriteMultipleByte (
+ mI2cBus,
+ I2CDeviceAddr,
+ I2CAddrMode,
+ &WriteLength,
+ &Data
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+GpioControllerConfig (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Perform Gpio controller config.
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ UINT32 IohGpioBase;
+ UINT32 Data32;
+ UINT8 Value8;
+ UINT8 PciCmd;
+ UINT16 PciVid;
+ UINT16 PciDid;
+ UINT32 Addr;
+ BOARD_GPIO_CONTROLLER_CONFIG *GpioConfig;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Func;
+ EFI_PLATFORM_TYPE_PROTOCOL *PlatformType;
+
+ PlatformType = &mPrivatePlatformData.PlatformType;
+
+ Bus = IOH_I2C_GPIO_BUS_NUMBER;
+ Device = IOH_I2C_GPIO_DEVICE_NUMBER;
+ Func = IOH_I2C_GPIO_FUNCTION_NUMBER;
+
+ PciVid = IohMmPci16(0, Bus, Device, Func, PCI_REG_VID);
+ PciDid = IohMmPci16(0, Bus, Device, Func, PCI_REG_DID);
+
+ if((PciVid == V_IOH_I2C_GPIO_VENDOR_ID) && (PciDid == V_IOH_I2C_GPIO_DEVICE_ID)) {
+ //
+ // Read PCICMD. Bus=0, Dev=0, Func=0, Reg=0x4
+ //
+ PciCmd = IohMmPci8(0, Bus, Device, Func, PCI_REG_PCICMD);
+
+ //
+ // Enable Bus Master(Bit2), MMIO Space(Bit1) & I/O Space(Bit0)
+ //
+ Value8 = PciCmd | 0x7;
+ IohMmPci8(0, Bus, Device, Func, PCI_REG_PCICMD) = Value8;
+
+ //
+ // Read MEM_BASE. Bus=0, Dev=0, Func=0, Reg=0x14
+ //
+ IohGpioBase = IohMmPci32(0, Bus, Device, Func, R_IOH_GPIO_MEMBAR);
+
+ ASSERT ((UINTN) PlatformType->Type < mBoardGpioControllerConfigTableLen);
+ GpioConfig = &mBoardGpioControllerConfigTable[(UINTN) PlatformType->Type];
+ DEBUG ((EFI_D_INFO, "Ioh Gpio Controller Init for PlatType=0x%02x\n", (UINTN) PlatformType->Type));
+
+ //
+ // IEN- Interrupt Enable Register
+ //
+ Addr = IohGpioBase + GPIO_INTEN;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ Data32 |= (GpioConfig->IntEn & 0x000FFFFF);
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ //
+ // ISTATUS- Interrupt Status Register
+ //
+ Addr = IohGpioBase + GPIO_INTSTATUS;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ //
+ // GPIO SWPORTA Direction Register - GPIO_SWPORTA_DR
+ //
+ Addr = IohGpioBase + GPIO_SWPORTA_DR;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ Data32 |= (GpioConfig->PortADR & 0x000FFFFF);
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ //
+ // GPIO SWPORTA Data Direction Register - GPIO_SWPORTA_DDR - default input
+ //
+ Addr = IohGpioBase + GPIO_SWPORTA_DDR;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ Data32 |= (GpioConfig->PortADir & 0x000FFFFF);
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ //
+ // Interrupt Mask Register - GPIO_INTMASK - default interrupts unmasked
+ //
+ Addr = IohGpioBase + GPIO_INTMASK;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ Data32 |= (GpioConfig->IntMask & 0x000FFFFF);
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ //
+ // Interrupt Level Type Register - GPIO_INTTYPE_LEVEL - default is level sensitive
+ //
+ Addr = IohGpioBase + GPIO_INTTYPE_LEVEL;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ Data32 |= (GpioConfig->IntType & 0x000FFFFF);
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ //
+ // Interrupt Polarity Type Register - GPIO_INT_POLARITY - default is active low
+ //
+ Addr = IohGpioBase + GPIO_INT_POLARITY;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ Data32 |= (GpioConfig->IntPolarity & 0x000FFFFF);
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ //
+ // Interrupt Debounce Type Register - GPIO_DEBOUNCE - default no debounce
+ //
+ Addr = IohGpioBase + GPIO_DEBOUNCE;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ Data32 |= (GpioConfig->Debounce & 0x000FFFFF);
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ //
+ // Interrupt Clock Synchronisation Register - GPIO_LS_SYNC - default no sync with pclk_intr(APB bus clk)
+ //
+ Addr = IohGpioBase + GPIO_LS_SYNC;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
+ Data32 |= (GpioConfig->LsSync & 0x000FFFFF);
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ }
+}
+
+VOID
+EFIAPI
+PlatformResetDevices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Performs any platform specific device resets
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ UINT32 IohGpioBase;
+ UINT32 Data32;
+ UINT8 Value8;
+ UINT8 PciCmd;
+ UINT16 PciVid;
+ UINT16 PciDid;
+ UINT32 Addr;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Func;
+ EFI_PLATFORM_TYPE_PROTOCOL *PlatformType;
+
+ PlatformType = &mPrivatePlatformData.PlatformType;
+
+ if(PlatformType->Type == (EFI_PLATFORM_TYPE) Galileo) {
+
+ DEBUG ((EFI_D_INFO, "Resetting Cypress Expander\n"));
+
+ Bus = IOH_I2C_GPIO_BUS_NUMBER;
+ Device = IOH_I2C_GPIO_DEVICE_NUMBER;
+ Func = IOH_I2C_GPIO_FUNCTION_NUMBER;
+
+ PciVid = IohMmPci16(0, Bus, Device, Func, PCI_REG_VID);
+ PciDid = IohMmPci16(0, Bus, Device, Func, PCI_REG_DID);
+
+ if((PciVid == V_IOH_I2C_GPIO_VENDOR_ID) && (PciDid == V_IOH_I2C_GPIO_DEVICE_ID)) {
+ //
+ // Read PCICMD. Bus=0, Dev=0, Func=0, Reg=0x4
+ //
+ PciCmd = IohMmPci8(0, Bus, Device, Func, PCI_REG_PCICMD);
+
+ //
+ // Enable Bus Master(Bit2), MMIO Space(Bit1) & I/O Space(Bit0)
+ //
+ Value8 = PciCmd | 0x7;
+ IohMmPci8(0, Bus, Device, Func, PCI_REG_PCICMD) = Value8;
+
+ //
+ // Read MEM_BASE. Bus=0, Dev=0, Func=0, Reg=0x14
+ //
+ IohGpioBase = IohMmPci32(0, Bus, Device, Func, R_IOH_GPIO_MEMBAR);
+ ASSERT (IohGpioBase != 0xFFFFFFFF);
+
+ //
+ // Reset Cypress Expander on Galileo Platform
+ //
+ Addr = IohGpioBase + GPIO_SWPORTA_DR;
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr));
+ Data32 |= BIT4; // Cypress Reset line controlled by GPIO<4>
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+
+ Data32 = *((volatile UINT32 *) (UINTN)(Addr));
+ Data32 &= ~BIT4; // Cypress Reset line controlled by GPIO<4>
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
+ }
+ }
+}
+
+VOID
+EFIAPI
+PlatformConfigOnPciEnumComplete (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Function runs in PI-DXE to perform platform specific config when PCI enum
+ is complete.
+
+Arguments:
+ Event - The event that occured.
+ Context - For EFI compatiblity. Not used.
+
+Returns:
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN SetMacAddr;
+ EFI_PLATFORM_TYPE_PROTOCOL *PlatformType;
+ VOID *PciEnumProt = NULL;
+
+ PlatformType = &mPrivatePlatformData.PlatformType;
+
+ Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, &PciEnumProt);
+ if (Status != EFI_SUCCESS){
+ DEBUG ((DEBUG_INFO, "gEfiPciEnumerationCompleteProtocolGuid triggered but not valid.\n"));
+ return;
+ }
+ if (mPciCfgDone) {
+ DEBUG ((DEBUG_INFO, "Platform DXE Pci config already done.\n"));
+ return;
+ }
+
+ GpioControllerConfig ();
+ PlatformResetDevices ();
+
+ //
+ // Set chipset MAC0 address if configured.
+ //
+ SetMacAddr =
+ (CompareMem (ChipsetDefaultMac, PlatformType->SysData.IohMac0Address, sizeof (ChipsetDefaultMac))) != 0;
+ if (SetMacAddr) {
+ if ((*(PlatformType->SysData.IohMac0Address) & BIT0) != 0) {
+ DEBUG ((EFI_D_ERROR, "HALT: Multicast Mac Address configured for Ioh MAC [B:%d, D:%d, F:%d]\n",
+ (UINTN) IOH_MAC0_BUS_NUMBER,
+ (UINTN) IOH_MAC0_DEVICE_NUMBER,
+ (UINTN) IOH_MAC0_FUNCTION_NUMBER
+ ));
+ ASSERT (FALSE);
+ } else {
+ SetLanControllerMacAddr (
+ IOH_MAC0_BUS_NUMBER,
+ IOH_MAC0_DEVICE_NUMBER,
+ IOH_MAC0_FUNCTION_NUMBER,
+ PlatformType->SysData.IohMac0Address
+ );
+ }
+ } else {
+ DEBUG ((EFI_D_WARN, "WARNING: Ioh MAC [B:%d, D:%d, F:%d] NO HW ADDR CONFIGURED!!!\n",
+ (UINTN) IOH_MAC0_BUS_NUMBER,
+ (UINTN) IOH_MAC0_DEVICE_NUMBER,
+ (UINTN) IOH_MAC0_FUNCTION_NUMBER
+ ));
+ }
+
+ //
+ // Set chipset MAC1 address if configured.
+ //
+ SetMacAddr =
+ (CompareMem (ChipsetDefaultMac, PlatformType->SysData.IohMac1Address, sizeof (ChipsetDefaultMac))) != 0;
+ if (SetMacAddr) {
+ if ((*(PlatformType->SysData.IohMac1Address) & BIT0) != 0) {
+ DEBUG ((EFI_D_ERROR, "HALT: Multicast Mac Address configured for Ioh MAC [B:%d, D:%d, F:%d]\n",
+ (UINTN) IOH_MAC1_BUS_NUMBER,
+ (UINTN) IOH_MAC1_DEVICE_NUMBER,
+ (UINTN) IOH_MAC1_FUNCTION_NUMBER
+ ));
+ ASSERT (FALSE);
+ } else {
+ SetLanControllerMacAddr (
+ IOH_MAC1_BUS_NUMBER,
+ IOH_MAC1_DEVICE_NUMBER,
+ IOH_MAC1_FUNCTION_NUMBER,
+ PlatformType->SysData.IohMac1Address
+ );
+ }
+ } else {
+ DEBUG ((EFI_D_WARN, "WARNING: Ioh MAC [B:%d, D:%d, F:%d] NO HW ADDR CONFIGURED!!!\n",
+ (UINTN) IOH_MAC1_BUS_NUMBER,
+ (UINTN) IOH_MAC1_DEVICE_NUMBER,
+ (UINTN) IOH_MAC1_FUNCTION_NUMBER
+ ));
+ }
+ mPciCfgDone = TRUE;
+}
+
+VOID
+EFIAPI
+PlatformConfigOnSmmConfigurationProtocol (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Function runs in PI-DXE to perform platform specific config when
+ SmmConfigurationProtocol is installed.
+
+Arguments:
+ Event - The event that occured.
+ Context - For EFI compatiblity. Not used.
+
+Returns:
+ None.
+--*/
+
+{
+ EFI_STATUS Status;
+ UINT32 NewValue;
+ UINT64 BaseAddress;
+ UINT64 SmramLength;
+ EFI_CPU_ARCH_PROTOCOL *CpuArchProtocol; // RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE
+ VOID *SmmCfgProt;
+
+ Status = gBS->LocateProtocol (&gEfiSmmConfigurationProtocolGuid, NULL, &SmmCfgProt);
+ if (Status != EFI_SUCCESS){
+ DEBUG ((DEBUG_INFO, "gEfiSmmConfigurationProtocolGuid triggered but not valid.\n"));
+ return;
+ }
+ if (mMemCfgDone) {
+ DEBUG ((DEBUG_INFO, "Platform DXE Mem config already done.\n"));
+ return;
+ }
+
+ //
+ // Disable eSram block (this will also clear/zero eSRAM)
+ // We only use eSRAM in the PEI phase. Disable now that we are in the DXE phase
+ //
+ NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK);
+ NewValue |= BLOCK_DISABLE_PG;
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK, NewValue);
+
+ //
+ // Update HMBOUND to top of DDR3 memory and LOCK
+ // We disabled eSRAM so now we move HMBOUND down to top of DDR3
+ //
+ QNCGetTSEGMemoryRange (&BaseAddress, &SmramLength);
+ NewValue = (UINT32)(BaseAddress + SmramLength);
+ DEBUG ((EFI_D_INFO,"Locking HMBOUND at: = 0x%8x\n",NewValue));
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG, (NewValue | HMBOUND_LOCK));
+
+ //
+ // Lock IMR5 now that HMBOUND is locked (legacy S3 region)
+ //
+ NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXL);
+ NewValue |= IMR_LOCK;
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXL, NewValue);
+
+ //
+ // Lock IMR6 now that HMBOUND is locked (ACPI Reclaim/ACPI/Runtime services/Reserved)
+ //
+ NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXL);
+ NewValue |= IMR_LOCK;
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXL, NewValue);
+
+ //
+ // Disable IMR2 memory protection (RMU Main Binary)
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR2,
+ (UINT32)(IMRL_RESET & ~IMR_EN),
+ (UINT32)IMRH_RESET,
+ (UINT32)IMRX_ALL_ACCESS,
+ (UINT32)IMRX_ALL_ACCESS
+ );
+
+ //
+ // Disable IMR3 memory protection (Default SMRAM)
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR3,
+ (UINT32)(IMRL_RESET & ~IMR_EN),
+ (UINT32)IMRH_RESET,
+ (UINT32)IMRX_ALL_ACCESS,
+ (UINT32)IMRX_ALL_ACCESS
+ );
+
+ //
+ // Disable IMR4 memory protection (eSRAM).
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR4,
+ (UINT32)(IMRL_RESET & ~IMR_EN),
+ (UINT32)IMRH_RESET,
+ (UINT32)IMRX_ALL_ACCESS,
+ (UINT32)IMRX_ALL_ACCESS
+ );
+
+ //
+ // RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE
+ // Workaround to make default SMRAM UnCachable
+ //
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &CpuArchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ CpuArchProtocol->SetMemoryAttributes (
+ CpuArchProtocol,
+ (EFI_PHYSICAL_ADDRESS) SMM_DEFAULT_SMBASE,
+ SMM_DEFAULT_SMBASE_SIZE_BYTES,
+ EFI_MEMORY_WB
+ );
+
+ mMemCfgDone = TRUE;
+}
+
+VOID
+EFIAPI
+PlatformConfigOnSpiReady (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Function runs in PI-DXE to perform platform specific config when SPI
+ interface is ready.
+
+Arguments:
+ Event - The event that occured.
+ Context - For EFI compatiblity. Not used.
+
+Returns:
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *SpiReadyProt = NULL;
+
+ Status = gBS->LocateProtocol (&gEfiSmmSpiReadyProtocolGuid, NULL, &SpiReadyProt);
+ if (Status != EFI_SUCCESS){
+ DEBUG ((DEBUG_INFO, "gEfiSmmSpiReadyProtocolGuid triggered but not valid.\n"));
+ return;
+ }
+
+ //
+ // Lock regions SPI flash.
+ //
+ PlatformFlashLockPolicy (FALSE);
+
+}
+
+EFI_STATUS
+EFIAPI
+CreateConfigEvents (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ None
+
+Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_EVENT EventSmmCfg;
+ EFI_EVENT EventPci;
+ EFI_EVENT EventSpiReady;
+ VOID *RegistrationSmmCfg;
+ VOID *RegistrationPci;
+ VOID *RegistrationSpiReady;
+
+ //
+ // Schedule callback for when SmmConfigurationProtocol installed.
+ //
+ EventSmmCfg = EfiCreateProtocolNotifyEvent (
+ &gEfiSmmConfigurationProtocolGuid,
+ TPL_CALLBACK,
+ PlatformConfigOnSmmConfigurationProtocol,
+ NULL,
+ &RegistrationSmmCfg
+ );
+ ASSERT (EventSmmCfg != NULL);
+
+ //
+ // Schedule callback to setup IOH GPIO controller registers when PCI enum
+ // complete (MEMBASE assigned).
+ //
+ EventPci = EfiCreateProtocolNotifyEvent (
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ TPL_CALLBACK,
+ PlatformConfigOnPciEnumComplete,
+ NULL,
+ &RegistrationPci
+ );
+ ASSERT (EventPci != NULL);
+
+ //
+ // Schedule callback to setup SPI Flash Policy when SPI interface ready.
+ //
+ EventSpiReady = EfiCreateProtocolNotifyEvent (
+ &gEfiSmmSpiReadyProtocolGuid,
+ TPL_CALLBACK,
+ PlatformConfigOnSpiReady,
+ NULL,
+ &RegistrationSpiReady
+ );
+ ASSERT (EventSpiReady != NULL);
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.c b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.c
new file mode 100644
index 0000000..55e966f
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.c
@@ -0,0 +1,307 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformInitDxe.c
+
+Abstract:
+
+ Platform init DXE driver for this platform.
+
+--*/
+
+//
+// Statements that include other files
+//
+#include "PlatformInitDxe.h"
+
+
+CHAR16 QncName[40];
+CHAR16 IioName[40];
+
+//
+// Instantiation of Driver's private data.
+//
+EFI_PLATFORM_DATA_DRIVER_PRIVATE mPrivatePlatformData;
+EFI_IIO_UDS_DRIVER_PRIVATE mIioUdsPrivateData;
+IIO_UDS *IioUdsData; // Pointer to UDS in Allocated Memory Pool
+
+//
+// Global variable to cache pointer to I2C protocol.
+//
+EFI_I2C_HC_PROTOCOL *mI2cBus = NULL;
+
+VOID
+GetQncName (
+ VOID
+ )
+{
+
+ switch (mPrivatePlatformData.PlatformType.QncSku) {
+ case QUARK_MC_DEVICE_ID:
+ StrCpy (QncName, L"Quark");
+ break;
+ case QUARK2_MC_DEVICE_ID:
+ StrCpy (QncName, L"Quark2");
+ break;
+ default:
+ StrCpy (QncName, L"Unknown");
+ }
+
+ //
+ // Revision
+ //
+ switch (mPrivatePlatformData.PlatformType.QncRevision) {
+ case QNC_MC_REV_ID_A0:
+ StrCat (QncName, L" - A0 stepping");
+ break;
+ default:
+ StrCat (QncName, L" - xx");
+ }
+
+ mPrivatePlatformData.PlatformType.QncStringPtr = (UINT64)QncName;
+ return;
+}
+
+
+VOID
+GetIioName (
+ VOID
+ )
+{
+
+ StrCpy (IioName, L"Unknown");
+
+ mPrivatePlatformData.PlatformType.IioStringPtr = (UINT64)IioName;
+ return ;
+}
+
+EFI_STATUS
+EFIAPI
+InstallProtocolsFromHobs (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Install protocols derived from platform hobs.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_PLATFORM_INFO *PlatformInfoHobData = NULL;
+ IIO_UDS *UdsHobPtr;
+ EFI_GUID UniversalDataGuid = IIO_UNIVERSAL_DATA_GUID;
+
+ //
+ // Initialize driver private data.
+ // Only one instance exists
+ //
+ ZeroMem (&mPrivatePlatformData, sizeof (mPrivatePlatformData));
+ mPrivatePlatformData.Signature = EFI_PLATFORM_TYPE_DRIVER_PRIVATE_SIGNATURE;
+
+ //
+ // Search for the Platform Info PEIM GUID HOB.
+ //
+ GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
+ PlatformInfoHobData = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (PlatformInfoHobData);
+
+ mPrivatePlatformData.PlatformType.Type = PlatformInfoHobData->Type;
+ mPrivatePlatformData.PlatformType.IioSku = PlatformInfoHobData->IioSku;
+ mPrivatePlatformData.PlatformType.IioRevision = PlatformInfoHobData->IioRevision;
+ mPrivatePlatformData.PlatformType.QncSku = PlatformInfoHobData->QncSku;
+ mPrivatePlatformData.PlatformType.QncRevision = PlatformInfoHobData->QncRevision;
+ mPrivatePlatformData.PlatformType.CpuType = PlatformInfoHobData->CpuType;
+ mPrivatePlatformData.PlatformType.CpuStepping = PlatformInfoHobData->CpuStepping;
+ mPrivatePlatformData.PlatformType.FirmwareVersion = PlatformInfoHobData->FirmwareVersion;
+ CopyGuid (
+ &mPrivatePlatformData.PlatformType.BiosPlatformDataFile,
+ &PlatformInfoHobData->BiosPlatformDataFile
+ );
+
+ CopyMem (
+ &mPrivatePlatformData.PlatformType.PciData,
+ &PlatformInfoHobData->PciData,
+ sizeof (mPrivatePlatformData.PlatformType.PciData)
+ );
+ CopyMem (
+ &mPrivatePlatformData.PlatformType.CpuData,
+ &PlatformInfoHobData->CpuData,
+ sizeof (mPrivatePlatformData.PlatformType.CpuData)
+ );
+ CopyMem (
+ &mPrivatePlatformData.PlatformType.MemData,
+ &PlatformInfoHobData->MemData,
+ sizeof (mPrivatePlatformData.PlatformType.MemData)
+ );
+ CopyMem (
+ &mPrivatePlatformData.PlatformType.SysData,
+ &PlatformInfoHobData->SysData,
+ sizeof (mPrivatePlatformData.PlatformType.SysData)
+ );
+
+ mPrivatePlatformData.PlatformType.TypeStringPtr =
+ PlatformTypeString ((UINT16) mPrivatePlatformData.PlatformType.Type);
+
+ GetQncName();
+ GetIioName();
+
+ //
+ // Install the PlatformType policy.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mPrivatePlatformData.Handle,
+ &gEfiPlatformTypeProtocolGuid,
+ &mPrivatePlatformData.PlatformType,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_ERROR, "%s platform is detected!\n", mPrivatePlatformData.PlatformType.TypeStringPtr));
+
+ //
+ // Time to get the IIO_UDS HOB data stored in the PEI driver
+ //
+ GuidHob = GetFirstGuidHob (&UniversalDataGuid);
+ UdsHobPtr = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (UdsHobPtr);
+
+ //
+ // Allocate Memory Pool for Universal Data Storage so that protocol can expose it
+ //
+ Status = gBS->AllocatePool ( EfiBootServicesData, sizeof (IIO_UDS), (VOID **) &IioUdsData );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the Pool Memory with the data from the Hand-Off-Block
+ //
+ CopyMem(IioUdsData, UdsHobPtr, sizeof(IIO_UDS));
+
+ //
+ // Build the IIO_UDS driver instance for protocol publishing
+ //
+ ZeroMem (&mIioUdsPrivateData, sizeof (mIioUdsPrivateData));
+
+ mIioUdsPrivateData.Signature = EFI_IIO_UDS_DRIVER_PRIVATE_SIGNATURE;
+ mIioUdsPrivateData.IioUds.IioUdsPtr = IioUdsData;
+
+ //
+ // Install the IioUds Protocol.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mIioUdsPrivateData.Handle,
+ &gEfiIioUdsProtocolGuid,
+ &mIioUdsPrivateData.IioUds,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PlatformInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Entry point for the driver.
+
+Arguments:
+
+ ImageHandle - Image Handle.
+ SystemTable - EFI System Table.
+
+Returns:
+
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Install data protocols whose contents are derived from Hobs.
+ //
+ InstallProtocolsFromHobs ();
+
+ //
+ // GalileoGen2 Platform support.
+ //
+ if (mPrivatePlatformData.PlatformType.Type == GalileoFabE) {
+ //
+ // Locate I2C host controller driver.
+ //
+ Status = gBS->LocateProtocol (&gEfiI2CHcProtocolGuid, NULL, (VOID **) &mI2cBus);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set Pcal9555 IO Expander config.
+ //
+ Status = PlatformPcal9555Config ((EFI_PLATFORM_TYPE) mPrivatePlatformData.PlatformType.Type);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Do Early PCIe init if GalileoFabE Platform.
+ //
+ Status = PlatformPciExpressEarlyInit ((EFI_PLATFORM_TYPE) mPrivatePlatformData.PlatformType.Type);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Initialize Firmware Volume security.
+ // This must be done before any firmware volume accesses.
+ //
+ Status = DxeInitializeFvSecurity();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create events for configuration callbacks.
+ //
+ CreateConfigEvents ();
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.h b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.h
new file mode 100644
index 0000000..47646e6
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.h
@@ -0,0 +1,114 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+ PlatformInitDxe.h
+
+Abstract:
+ Platform init DXE driver header file.
+
+--*/
+
+#ifndef _PLATFORM_TYPES_H_
+#define _PLATFORM_TYPES_H_
+
+#include <PiDxe.h>
+#include <Protocol/PlatformType.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformPcieHelperLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Protocol/Variable.h>
+#include <Protocol/CpuIo.h>
+#include <Protocol/Cpu.h>
+#include <Protocol/PlatformType.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Protocol/Spi.h>
+#include <Protocol/PlatformSmmSpiReady.h>
+#include <Protocol/IioUds.h>
+#include <Protocol/SmmConfiguration.h>
+#include <Protocol/I2CHc.h>
+#include <Guid/HobList.h>
+#include <CpuRegs.h>
+#include <IntelQNCRegs.h>
+#include <Platform.h>
+#include <Pcal9555.h>
+#include <PlatformBoards.h>
+#include <IohAccess.h>
+#include "DxeFvSecurity.h"
+
+#define BLOCK_SIZE_32KB 0x8000
+#define BLOCK_SIZE_64KB 0x10000
+#define EFI_PLATFORM_TYPE_DRIVER_PRIVATE_SIGNATURE SIGNATURE_32 ('T', 'Y', 'P', 'P')
+#define EFI_IIO_UDS_DRIVER_PRIVATE_SIGNATURE SIGNATURE_32 ('S', 'D', 'U', 'I')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle; // Handle for protocol this driver installs on
+ EFI_PLATFORM_TYPE_PROTOCOL PlatformType; // Policy protocol this driver installs
+} EFI_PLATFORM_DATA_DRIVER_PRIVATE;
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle; // Handle for protocol this driver installs on
+ EFI_IIO_UDS_PROTOCOL IioUds; // Policy protocol this driver installs
+} EFI_IIO_UDS_DRIVER_PRIVATE;
+
+//
+// Instantiation of Driver's private data.
+//
+extern EFI_PLATFORM_DATA_DRIVER_PRIVATE mPrivatePlatformData;
+extern EFI_IIO_UDS_DRIVER_PRIVATE mIioUdsPrivateData;
+extern IIO_UDS *IioUdsData;
+extern EFI_I2C_HC_PROTOCOL *mI2cBus;
+
+//
+// Function prototypes for routines private to this driver.
+//
+EFI_STATUS
+EFIAPI
+CreateConfigEvents (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+PlatformPcal9555Config (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.inf b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.inf
new file mode 100644
index 0000000..7fb3132
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.inf
@@ -0,0 +1,100 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+# Module Name:
+#
+# PlatformInitDxe.inf
+#
+# Abstract:.
+#
+# Component description file for Quark Platform Init DXE module.
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformInitDxe
+ FILE_GUID = 2E6A521C-F697-402d-9774-98B2B7E140F3
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformInit
+
+[Sources]
+ PlatformInitDxe.h
+ PlatformInitDxe.c
+ PlatformConfig.c
+ DxeFvSecurity.c
+ DxeFvSecurity.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ HobLib
+ DebugLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ PlatformHelperLib
+ PlatformPcieHelperLib
+ MfhLib
+ SecurityAuthenticationLib
+ DxeServicesLib
+ IntelQNCLib
+ QNCAccessLib
+ BaseMemoryLib
+
+[Protocols]
+ gEfiPlatformTypeProtocolGuid ## Produces
+ gEfiCpuIoProtocolGuid
+ gEfiIioUdsProtocolGuid
+ gFirmwareVolumeBlockSecurityGuid
+ gEfiFirmwareVolumeBlockProtocolGuid
+ gEfiCpuArchProtocolGuid
+ gEfiPciEnumerationCompleteProtocolGuid
+ gEfiSmmConfigurationProtocolGuid
+ gEfiSmmSpiReadyProtocolGuid
+ gEfiI2CHcProtocolGuid
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageBase
+
+[Guids]
+ gEfiPlatformInfoGuid
+
+[Depex]
+ TRUE
+
diff --git a/QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.c b/QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.c
new file mode 100755
index 0000000..9790c66
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.c
@@ -0,0 +1,152 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SaveMemoryConfig.c
+
+Abstract:
+ This is the driver that locates the MemoryConfigurationData HOB, if it
+ exists, and saves the data to nvRAM.
+
+Revision History
+
+--*/
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+#include <Guid/MemoryConfigData.h>
+#include <Guid/DebugMask.h>
+
+EFI_STATUS
+EFIAPI
+SaveMemoryConfigEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+ Routine Description:
+ This is the standard EFI driver point that detects whether there is a
+ MemoryConfigurationData HOB and, if so, saves its data to nvRAM.
+
+ Arguments:
+ ImageHandle - Handle for the image of this driver
+ SystemTable - Pointer to the EFI System Table
+
+ Returns:
+ EFI_SUCCESS - if the data is successfully saved or there was no data
+ EFI_NOT_FOUND - if the HOB list could not be located.
+ EFI_UNLOAD_IMAGE - It is not success
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *HobList;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ VOID *HobData;
+ VOID *VariableData;
+ UINTN DataSize;
+ UINTN BufferSize;
+
+ DataSize = 0;
+ VariableData = NULL;
+ GuidHob = NULL;
+ HobList = NULL;
+ HobData = NULL;
+ Status = EFI_UNSUPPORTED;
+
+ //
+ // Get the HOB list. If it is not present, then ASSERT.
+ //
+ HobList = GetHobList ();
+ ASSERT (HobList != NULL);
+
+ //
+ // Search for the Memory Configuration GUID HOB. If it is not present, then
+ // there's nothing we can do. It may not exist on the update path.
+ //
+ GuidHob = GetNextGuidHob (&gEfiMemoryConfigDataGuid, HobList);
+ if (GuidHob != NULL) {
+ HobData = GET_GUID_HOB_DATA (GuidHob);
+ DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+ //
+ // Use the HOB to save Memory Configuration Data
+ //
+ BufferSize = DataSize;
+ VariableData = AllocatePool (BufferSize);
+ ASSERT (VariableData != NULL);
+ Status = gRT->GetVariable (
+ EFI_MEMORY_CONFIG_DATA_NAME,
+ &gEfiMemoryConfigDataGuid,
+ NULL,
+ &BufferSize,
+ VariableData
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ (gBS->FreePool)(VariableData);
+ VariableData = AllocatePool (BufferSize);
+ ASSERT (VariableData != NULL);
+ Status = gRT->GetVariable (
+ EFI_MEMORY_CONFIG_DATA_NAME,
+ &gEfiMemoryConfigDataGuid,
+ NULL,
+ &BufferSize,
+ VariableData
+ );
+ }
+
+ if ( (EFI_ERROR(Status)) || BufferSize != DataSize || 0 != CompareMem (HobData, VariableData, DataSize)) {
+ if (Status != EFI_SUCCESS){
+ Status = gRT->SetVariable (
+ EFI_MEMORY_CONFIG_DATA_NAME,
+ &gEfiMemoryConfigDataGuid,
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+ DataSize,
+ HobData
+ );
+ }
+ ASSERT((Status == EFI_SUCCESS) || (Status == EFI_OUT_OF_RESOURCES));
+
+ DEBUG((EFI_D_INFO, "Restored Size is 0x%x\n", DataSize));
+ }
+ (gBS->FreePool)(VariableData);
+ }
+ //
+ // This driver does not produce any protocol services, so always unload it.
+ //
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.inf b/QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.inf
new file mode 100755
index 0000000..b083350
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.inf
@@ -0,0 +1,73 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Module Name:
+#
+# SaveMemoryConfig.inf
+#
+# Abstract:
+#
+# Component description file for SaveMemoryConfig module
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SaveMemoryConfig
+ FILE_GUID = 0F99E33C-CA0C-4aa2-887D-B57EC9050278
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SaveMemoryConfigEntryPoint
+
+[sources]
+ SaveMemoryConfig.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ HobLib
+
+[Guids]
+ gEfiGenericVariableGuid
+ gEfiMemoryConfigDataGuid
+
+[Depex]
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid
diff --git a/QuarkPlatformPkg/Platform/Dxe/Setup/CommonHeader.h b/QuarkPlatformPkg/Platform/Dxe/Setup/CommonHeader.h
new file mode 100644
index 0000000..71d470b
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/Setup/CommonHeader.h
@@ -0,0 +1,83 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+
+#include <FrameworkDxe.h>
+#include <QuarkPlatformDxe.h>
+#include <IntelQNCDxe.h>
+#include <IndustryStandard/Pci22.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/DataHubRecords.h>
+#include <Protocol/Smbios.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/PlatformPolicy.h>
+#include <Protocol/MpService.h>
+
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiConfigAccess.h>
+
+#include <Protocol/IdeControllerInit.h>
+#include <Protocol/PciIo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HiiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/CpuConfigLib.h>
+#include <Library/S3IoLib.h>
+#include <Library/S3PciLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/SocketLga775Lib.h>
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Dxe/Setup/DxePlatform.inf b/QuarkPlatformPkg/Platform/Dxe/Setup/DxePlatform.inf
new file mode 100644
index 0000000..18b8547
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/Setup/DxePlatform.inf
@@ -0,0 +1,109 @@
+## @file
+# Component description file for DxePlatform module.
+#
+# This driver initializes platform configuration setting and installs several platform policy potocols.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxePlatform
+ FILE_GUID = DAA55048-BC3F-4dd9-999B-F58ABF2BBFCC
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DxePlatformDriverEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ KeyboardLayout.c
+ QNCRegTable.c
+ processor.c
+ SetupPlatform.c
+ SetupPlatform.h
+ Strings.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+
+[LibraryClasses]
+ IoLib
+ IntelQNCLib
+ PcdLib
+ PrintLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ S3BootScriptLib
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseLib
+ S3IoLib
+ S3PciLib
+ HiiLib
+ HobLib
+ PciLib
+ UefiLib
+
+[Guids]
+
+[Protocols]
+ gEfiPlatformPolicyProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiHiiDatabaseProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigAccessProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigRoutingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent0IR
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent1IR
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent2IR
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent3IR
+
+[Pcd]
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuFrequencyLists
+
+[Depex]
+ # AND EFI_SDRAM_MEMORY_SETUP_PROTOCOL_GUID AND
+ gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid AND gEfiHiiDatabaseProtocolGuid AND gPcdProtocolGuid
diff --git a/QuarkPlatformPkg/Platform/Dxe/Setup/KeyboardLayout.c b/QuarkPlatformPkg/Platform/Dxe/Setup/KeyboardLayout.c
new file mode 100644
index 0000000..24e4b65
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/Setup/KeyboardLayout.c
@@ -0,0 +1,295 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ KeyboardLayout.c
+
+Abstract:
+
+ Example code to register customized keyboard layout to HII database.
+
+Revision History
+
+--*/
+
+#include "CommonHeader.h"
+
+//
+// Define "`" as Non-spacing key to switch "a","u","i","o","e"
+//
+#define ENABLE_NS_KEY 1
+
+#ifdef ENABLE_NS_KEY
+#define KEYBOARD_KEY_COUNT (104 + 5)
+#else
+#define KEYBOARD_KEY_COUNT 104
+#endif
+
+#pragma pack (1)
+typedef struct {
+ //
+ // This 4-bytes total array length is required by PreparePackageList()
+ //
+ UINT32 Length;
+
+ //
+ // Keyboard Layout package definition
+ //
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ UINT16 LayoutCount;
+
+ //
+ // EFI_HII_KEYBOARD_LAYOUT
+ //
+ UINT16 LayoutLength;
+ EFI_GUID Guid;
+ UINT32 LayoutDescriptorStringOffset;
+ UINT8 DescriptorCount;
+ EFI_KEY_DESCRIPTOR KeyDescriptor[KEYBOARD_KEY_COUNT];
+ UINT16 DescriptionCount; // EFI_DESCRIPTION_STRING_BUNDLE
+ CHAR16 Language[5]; // RFC4646 Language Code: "en-US"
+ CHAR16 Space;
+ CHAR16 DescriptionString[17]; // Description: "English Keyboard"
+} KEYBOARD_LAYOUT_PACK_BIN;
+#pragma pack()
+
+#define KEYBOARD_LAYOUT_PACKAGE_GUID \
+ { \
+ 0xd66f7b7a, 0x5e06, 0x49f3, { 0xa1, 0xcf, 0x12, 0x8d, 0x4, 0x86, 0xc2, 0x7c } \
+ }
+
+#define KEYBOARD_LAYOUT_KEY_GUID \
+ { \
+ 0xd9db96f4, 0xff47, 0x4eb6, { 0x8a, 0x4, 0x79, 0x5b, 0x56, 0x87, 0xb, 0x4e } \
+ }
+
+EFI_GUID mKeyboardLayoutPackageGuid = KEYBOARD_LAYOUT_PACKAGE_GUID;
+EFI_GUID mKeyboardLayoutKeyGuid = KEYBOARD_LAYOUT_KEY_GUID;
+
+KEYBOARD_LAYOUT_PACK_BIN mKeyboardLayoutBin = {
+ sizeof (KEYBOARD_LAYOUT_PACK_BIN), // Binary size
+
+ //
+ // EFI_HII_PACKAGE_HEADER
+ //
+ {
+ sizeof (KEYBOARD_LAYOUT_PACK_BIN) - sizeof (UINT32),
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT
+ },
+ 1, // LayoutCount
+ sizeof (KEYBOARD_LAYOUT_PACK_BIN) - sizeof (UINT32) - sizeof (EFI_HII_PACKAGE_HEADER) - sizeof (UINT16), // LayoutLength
+ KEYBOARD_LAYOUT_KEY_GUID, // KeyGuid
+ sizeof (UINT16) + sizeof (EFI_GUID) + sizeof (UINT32) + sizeof (UINT8) + (KEYBOARD_KEY_COUNT * sizeof (EFI_KEY_DESCRIPTOR)), // LayoutDescriptorStringOffset
+ KEYBOARD_KEY_COUNT, // DescriptorCount
+ {
+ //
+ // EFI_KEY_DESCRIPTOR
+ //
+ {EfiKeyC1, 'a', 'A', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyB5, 'b', 'B', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyB3, 'c', 'C', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyC3, 'd', 'D', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD3, 'e', 'E', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyC4, 'f', 'F', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyC5, 'g', 'G', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyC6, 'h', 'H', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD8, 'i', 'I', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyC7, 'j', 'J', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyC8, 'k', 'K', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyC9, 'l', 'L', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyB7, 'm', 'M', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyB6, 'n', 'N', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD9, 'o', 'O', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD10, 'p', 'P', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD1, 'q', 'Q', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD4, 'r', 'R', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyC2, 's', 'S', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD5, 't', 'T', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD7, 'u', 'U', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyB4, 'v', 'V', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD2, 'w', 'W', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyB2, 'x', 'X', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD6, 'y', 'Y', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyB1, 'z', 'Z', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyE1, '1', '!', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE2, '2', '@', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE3, '3', '#', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE4, '4', '$', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE5, '5', '%', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE6, '6', '^', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE7, '7', '&', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE8, '8', '*', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE9, '9', '(', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE10, '0', ')', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyEnter, 0x0d, 0x0d, 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyEsc, 0x1b, 0x1b, 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyBackSpace, 0x08, 0x08, 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyTab, 0x09, 0x09, 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeySpaceBar, ' ', ' ', 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyE11, '-', '_', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyE12, '=', '+', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyD11, '[', '{', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyD12, ']', '}', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyD13, '\\', '|', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyC10, ';', ':', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyC11, '\'', '"', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+
+#ifdef ENABLE_NS_KEY
+ //
+ // Non-Spacing key example
+ //
+ {EfiKeyE0, 0, 0, 0, 0, EFI_NS_KEY_MODIFIER, 0},
+ {EfiKeyC1, 0x00E2, 0x00C2, 0, 0, EFI_NS_KEY_DEPENDENCY_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD3, 0x00EA, 0x00CA, 0, 0, EFI_NS_KEY_DEPENDENCY_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD8, 0x00EC, 0x00CC, 0, 0, EFI_NS_KEY_DEPENDENCY_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD9, 0x00F4, 0x00D4, 0, 0, EFI_NS_KEY_DEPENDENCY_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+ {EfiKeyD7, 0x00FB, 0x00CB, 0, 0, EFI_NS_KEY_DEPENDENCY_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},
+#else
+ {EfiKeyE0, '`', '~', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+#endif
+
+ {EfiKeyB8, ',', '<', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyB9, '.', '>', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyB10, '/', '?', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT},
+ {EfiKeyCapsLock, 0x00, 0x00, 0, 0, EFI_CAPS_LOCK_MODIFIER, 0},
+ {EfiKeyF1, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_ONE_MODIFIER, 0},
+ {EfiKeyF2, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TWO_MODIFIER, 0},
+ {EfiKeyF3, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_THREE_MODIFIER, 0},
+ {EfiKeyF4, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_FOUR_MODIFIER, 0},
+ {EfiKeyF5, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_FIVE_MODIFIER, 0},
+ {EfiKeyF6, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_SIX_MODIFIER, 0},
+ {EfiKeyF7, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_SEVEN_MODIFIER, 0},
+ {EfiKeyF8, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_EIGHT_MODIFIER, 0},
+ {EfiKeyF9, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_NINE_MODIFIER, 0},
+ {EfiKeyF10, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TEN_MODIFIER, 0},
+ {EfiKeyF11, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_ELEVEN_MODIFIER, 0},
+ {EfiKeyF12, 0x00, 0x00, 0, 0, EFI_FUNCTION_KEY_TWELVE_MODIFIER, 0},
+ {EfiKeyPrint, 0x00, 0x00, 0, 0, EFI_PRINT_MODIFIER, 0},
+ {EfiKeySLck, 0x00, 0x00, 0, 0, EFI_SCROLL_LOCK_MODIFIER, 0},
+ {EfiKeyPause, 0x00, 0x00, 0, 0, EFI_PAUSE_MODIFIER, 0},
+ {EfiKeyIns, 0x00, 0x00, 0, 0, EFI_INSERT_MODIFIER, 0},
+ {EfiKeyHome, 0x00, 0x00, 0, 0, EFI_HOME_MODIFIER, 0},
+ {EfiKeyPgUp, 0x00, 0x00, 0, 0, EFI_PAGE_UP_MODIFIER, 0},
+ {EfiKeyDel, 0x00, 0x00, 0, 0, EFI_DELETE_MODIFIER, 0},
+ {EfiKeyEnd, 0x00, 0x00, 0, 0, EFI_END_MODIFIER, 0},
+ {EfiKeyPgDn, 0x00, 0x00, 0, 0, EFI_PAGE_DOWN_MODIFIER, 0},
+ {EfiKeyRightArrow, 0x00, 0x00, 0, 0, EFI_RIGHT_ARROW_MODIFIER, 0},
+ {EfiKeyLeftArrow, 0x00, 0x00, 0, 0, EFI_LEFT_ARROW_MODIFIER, 0},
+ {EfiKeyDownArrow, 0x00, 0x00, 0, 0, EFI_DOWN_ARROW_MODIFIER, 0},
+ {EfiKeyUpArrow, 0x00, 0x00, 0, 0, EFI_UP_ARROW_MODIFIER, 0},
+ {EfiKeyNLck, 0x00, 0x00, 0, 0, EFI_NUM_LOCK_MODIFIER, 0},
+ {EfiKeySlash, '/', '/', 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyAsterisk, '*', '*', 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyMinus, '-', '-', 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyPlus, '+', '+', 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyEnter, 0x0d, 0x0d, 0, 0, EFI_NULL_MODIFIER, 0},
+ {EfiKeyOne, '1', '1', 0, 0, EFI_END_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyTwo, '2', '2', 0, 0, EFI_DOWN_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyThree, '3', '3', 0, 0, EFI_PAGE_DOWN_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyFour, '4', '4', 0, 0, EFI_LEFT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyFive, '5', '5', 0, 0, EFI_NULL_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeySix, '6', '6', 0, 0, EFI_RIGHT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeySeven, '7', '7', 0, 0, EFI_HOME_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyEight, '8', '8', 0, 0, EFI_UP_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyNine, '9', '9', 0, 0, EFI_PAGE_UP_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyZero, '0', '0', 0, 0, EFI_INSERT_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyPeriod, '.', '.', 0, 0, EFI_DELETE_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},
+ {EfiKeyA4, 0x00, 0x00, 0, 0, EFI_MENU_MODIFIER, 0},
+ {EfiKeyLCtrl, 0, 0, 0, 0, EFI_LEFT_CONTROL_MODIFIER, 0},
+ {EfiKeyLShift, 0, 0, 0, 0, EFI_LEFT_SHIFT_MODIFIER, 0},
+ {EfiKeyLAlt, 0, 0, 0, 0, EFI_LEFT_ALT_MODIFIER, 0},
+ {EfiKeyA0, 0, 0, 0, 0, EFI_LEFT_LOGO_MODIFIER, 0},
+ {EfiKeyRCtrl, 0, 0, 0, 0, EFI_RIGHT_CONTROL_MODIFIER, 0},
+ {EfiKeyRShift, 0, 0, 0, 0, EFI_RIGHT_SHIFT_MODIFIER, 0},
+ {EfiKeyA2, 0, 0, 0, 0, EFI_RIGHT_ALT_MODIFIER, 0},
+ {EfiKeyA3, 0, 0, 0, 0, EFI_RIGHT_LOGO_MODIFIER, 0},
+ },
+ 1, // DescriptionCount
+ {'e', 'n', '-', 'U', 'S'}, // RFC4646 language code
+ ' ', // Space
+ {'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '\0'}, // DescriptionString[17]
+};
+
+extern EFI_HANDLE mImageHandle;
+
+EFI_STATUS
+InitKeyboardLayout (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Install keyboard layout package and set current keyboard layout.
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_HANDLE HiiHandle;
+
+ //
+ // Locate Hii database protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID**)&HiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Keyboard Layout package to HII database
+ //
+ HiiHandle = HiiAddPackages (
+ &mKeyboardLayoutPackageGuid,
+ mImageHandle,
+ &mKeyboardLayoutBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Set current keyboard layout
+ //
+ Status = HiiDatabase->SetKeyboardLayout (HiiDatabase, &mKeyboardLayoutKeyGuid);
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/Setup/QNCRegTable.c b/QuarkPlatformPkg/Platform/Dxe/Setup/QNCRegTable.c
new file mode 100644
index 0000000..d7de990
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/Setup/QNCRegTable.c
@@ -0,0 +1,113 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCRegTable.c
+
+Abstract:
+
+ Register initialization table for Ich.
+
+Revision History
+
+--*/
+
+
+#include "CommonHeader.h"
+
+VOID
+PlatformInitQNCRegs (
+ VOID
+ )
+{
+ //
+ // All devices on bus 0.
+ // Device 0:
+ // FNC 0: Host Bridge
+ // Device 20:
+ // FNC 0: IOSF2AHB Bridge
+ // Device 21:
+ // FNC 0: IOSF2AHB Bridge
+ // Device 23:
+ // FNC 0: PCIe Port 0
+ // Device 24:
+ // FNC 0: PCIe Port 1
+
+ // Device 31:
+ // FNC 0: PCI-LPC Bridge
+ //
+ S3PciWrite32 (PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, R_QNC_LPC_FWH_BIOS_DEC),
+ B_QNC_LPC_FWH_BIOS_DEC_F0 | B_QNC_LPC_FWH_BIOS_DEC_F8 |
+ B_QNC_LPC_FWH_BIOS_DEC_E0 | B_QNC_LPC_FWH_BIOS_DEC_E8 |
+ B_QNC_LPC_FWH_BIOS_DEC_D0 | B_QNC_LPC_FWH_BIOS_DEC_D8 |
+ B_QNC_LPC_FWH_BIOS_DEC_C0 | B_QNC_LPC_FWH_BIOS_DEC_C8
+ );
+
+ //
+ // Program SCI Interrupt for IRQ9
+ //
+ S3PciWrite8 (PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, R_QNC_LPC_ACTL),
+ V_QNC_LPC_ACTL_SCIS_IRQ9
+ );
+
+ //
+ // Program Quark Interrupt Route Registers
+ //
+ S3MmioWrite16 (FixedPcdGet64(PcdRcbaMmioBaseAddress) + R_QNC_RCRB_AGENT0IR,
+ FixedPcdGet16(PcdQuarkAgent0IR)
+ );
+ S3MmioWrite16 (FixedPcdGet64(PcdRcbaMmioBaseAddress) + R_QNC_RCRB_AGENT1IR,
+ FixedPcdGet16(PcdQuarkAgent1IR)
+ );
+ S3MmioWrite16 (FixedPcdGet64(PcdRcbaMmioBaseAddress) + R_QNC_RCRB_AGENT2IR,
+ FixedPcdGet16(PcdQuarkAgent2IR)
+ );
+ S3MmioWrite16 (FixedPcdGet64(PcdRcbaMmioBaseAddress) + R_QNC_RCRB_AGENT3IR,
+ FixedPcdGet16(PcdQuarkAgent3IR)
+ );
+
+ //
+ // Program SVID and SID for QNC PCI devices. In order to boost performance, we
+ // combine two 16 bit PCI_WRITE into one 32 bit PCI_WRITE. The programmed LPC SVID
+ // will reflect on all internal devices's SVID registers
+ //
+ S3PciWrite32 (PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, R_EFI_PCI_SVID),
+ (UINT32)(V_INTEL_VENDOR_ID + (QUARK_V_LPC_DEVICE_ID_0 << 16))
+ );
+
+ //
+ // Write once on Element Self Description Regster before OS boot
+ //
+ QNCMmio32And (FixedPcdGet64(PcdRcbaMmioBaseAddress), 0x04, 0xFF00FFFF);
+
+ return;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/Setup/SetupPlatform.c b/QuarkPlatformPkg/Platform/Dxe/Setup/SetupPlatform.c
new file mode 100644
index 0000000..b1275e4
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/Setup/SetupPlatform.c
@@ -0,0 +1,130 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SetupPlatform.c
+
+Abstract:
+
+ Platform Initialization Driver.
+
+Revision History
+
+--*/
+
+#include "CommonHeader.h"
+
+#include "SetupPlatform.h"
+#include <Library/HobLib.h>
+
+EFI_HANDLE mImageHandle = NULL;
+
+EFI_HII_DATABASE_PROTOCOL *mHiiDataBase = NULL;
+EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL;
+
+static UINT8 mSmbusRsvdAddresses[PLATFORM_NUM_SMBUS_RSVD_ADDRESSES] = {
+ SMBUS_ADDR_CH_A_1,
+ SMBUS_ADDR_CK505,
+ SMBUS_ADDR_THERMAL_SENSOR1,
+ SMBUS_ADDR_THERMAL_SENSOR2
+};
+
+EFI_PLATFORM_POLICY_PROTOCOL mPlatformPolicyData = {
+ PLATFORM_NUM_SMBUS_RSVD_ADDRESSES,
+ mSmbusRsvdAddresses
+};
+
+EFI_STATUS
+DxePlatformDriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+ Routine Description:
+ This is the standard EFI driver point for the D845GRgPlatform Driver. This
+ driver is responsible for setting up any platform specific policy or
+ initialization information.
+
+ Arguments:
+ ImageHandle - Handle for the image of this driver
+ SystemTable - Pointer to the EFI System Table
+
+ Returns:
+ EFI_SUCCESS - Policy decisions set
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ S3BootScriptSaveInformationAsciiString (
+ "SetupDxeEntryBegin"
+ );
+
+ mImageHandle = ImageHandle;
+
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID**)&mHiiDataBase);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID**)&mHiiConfigRouting);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize keyboard layout
+ //
+ Status = InitKeyboardLayout ();
+
+ //
+ // Initialize ICH registers
+ //
+ PlatformInitQNCRegs();
+
+ ProducePlatformCpuData ();
+
+ //
+ // Install protocol to to allow access to this Policy.
+ //
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiPlatformPolicyProtocolGuid, &mPlatformPolicyData,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ S3BootScriptSaveInformationAsciiString (
+ "SetupDxeEntryEnd"
+ );
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Platform/Dxe/Setup/SetupPlatform.h b/QuarkPlatformPkg/Platform/Dxe/Setup/SetupPlatform.h
new file mode 100644
index 0000000..285f5e0
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/Setup/SetupPlatform.h
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SetupPlatform.h
+
+Abstract:
+
+ Header file for Platform Initialization Driver.
+
+Revision History
+
+++*/
+
+#ifndef _SETUP_PLATFORM_H
+#define _SETUP_PLATFORM_H
+
+//
+// Data
+//
+#define PLATFORM_NUM_SMBUS_RSVD_ADDRESSES 4
+#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((SYSTEM_CONFIGURATION *) 0)->Field)))
+#define QUESTION_ID(Field) (VAR_OFFSET (Field) + 1)
+
+#define SMBUS_ADDR_CH_A_1 0xA0
+#define SMBUS_ADDR_CK505 0xD2
+#define SMBUS_ADDR_THERMAL_SENSOR1 0x4C
+#define SMBUS_ADDR_THERMAL_SENSOR2 0x4D
+
+///
+/// HII specific Vendor Device Path Node definition.
+///
+#pragma pack(1)
+
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ UINT16 UniqueId;
+} HII_VENDOR_DEVICE_PATH_NODE;
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ HII_VENDOR_DEVICE_PATH_NODE Node;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+//
+// Prototypes
+//
+VOID
+ProducePlatformCpuData (
+ VOID
+ );
+
+VOID
+PlatformInitQNCRegs (
+ VOID
+ );
+
+EFI_STATUS
+InitKeyboardLayout (
+ VOID
+ );
+
+//
+// Global externs
+//
+extern UINT8 UefiSetupDxeStrings[];
+
+extern EFI_HII_DATABASE_PROTOCOL *mHiiDataBase;
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
+
+typedef struct {
+ EFI_EXP_BASE10_DATA *CoreFrequencyList;
+ EFI_EXP_BASE10_DATA *FsbFrequencyList;
+} PLATFORM_CPU_FREQUENCY_LIST;
+#endif
diff --git a/QuarkPlatformPkg/Platform/Dxe/Setup/Strings.uni b/QuarkPlatformPkg/Platform/Dxe/Setup/Strings.uni
new file mode 100644
index 0000000..a728729
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/Setup/Strings.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/Setup/processor.c b/QuarkPlatformPkg/Platform/Dxe/Setup/processor.c
new file mode 100644
index 0000000..996a9eb
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/Setup/processor.c
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Processor.c
+
+Abstract:
+
+ None.
+
+Revision History
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SetupPlatform.h"
+
+
+#define NUMBER_OF_PACKAGES 1
+
+static EFI_EXP_BASE10_DATA mCoreFrequencyList[] = {
+ { 0, 0 }, // 0 Means "Auto", also, the first is the default.
+ { (UINT16) -1, 0 } // End marker
+};
+
+static EFI_EXP_BASE10_DATA mFsbFrequencyList[] = {
+ { 0, 0 }, // 0 Means "Auto", also, the first is the default.
+ { (UINT16) -1, 0 } // End marker
+};
+
+static CHAR16 *SocketNames[NUMBER_OF_PACKAGES];
+static CHAR16 *AssetTags[NUMBER_OF_PACKAGES];
+
+static CHAR16 EmptyString[] = L" ";
+static CHAR16 SocketString[] = L"LGA775";
+
+
+PLATFORM_CPU_FREQUENCY_LIST PlatformCpuFrequencyList = {
+ mCoreFrequencyList,
+ mFsbFrequencyList
+};
+
+VOID
+ProducePlatformCpuData (
+ VOID
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < NUMBER_OF_PACKAGES; Index++) {
+
+ //
+ // The String Package of a module is registered together with all IFR packages.
+ // So we just arbitrarily pick a package GUID that is always installed to get the string.
+ //
+ AssetTags[Index] = EmptyString;
+ SocketNames[Index] = SocketString;
+ }
+
+ PcdSet64 (PcdPlatformCpuSocketNames, (UINT64) (UINTN) SocketNames);
+ PcdSet64 (PcdPlatformCpuAssetTags, (UINT64) (UINTN) AssetTags);
+ PcdSet64 (PcdPlatformCpuFrequencyLists, (UINT64) (UINTN) &PlatformCpuFrequencyList);
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/CommonHeader.h b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/CommonHeader.h
new file mode 100644
index 0000000..9a60879
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/CommonHeader.h
@@ -0,0 +1,60 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+
+#include <FrameworkDxe.h>
+#include <QuarkPlatformDxe.h>
+//#include <LakeportDxe.h>
+#include <IndustryStandard/SmBios.h>
+#include <Protocol/Smbios.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/DataHubRecords.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+
+extern EFI_HII_HANDLE gHiiHandle;
+#endif
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturer.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturer.uni
new file mode 100755
index 0000000..781c1a2
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturer.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturerData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturerData.c
new file mode 100755
index 0000000..2f8f431
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturerData.c
@@ -0,0 +1,69 @@
+/** @file
+ Type 2: Base Board Information.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "CommonHeader.h"
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_BASE_BOARD_MANUFACTURER_DATA, MiscBaseBoardManufacturer)
+= {
+ STRING_TOKEN(STR_MISC_BASE_BOARD_MANUFACTURER),
+ STRING_TOKEN(STR_MISC_BASE_BOARD_PRODUCT_NAME),
+ STRING_TOKEN(STR_MISC_BASE_BOARD_VERSION),
+ STRING_TOKEN(STR_MISC_BASE_BOARD_SERIAL_NUMBER),
+ STRING_TOKEN(STR_MISC_BASE_BOARD_ASSET_TAG),
+ STRING_TOKEN(STR_MISC_BASE_BOARD_CHASSIS_LOCATION),
+ { // BaseBoardFeatureFlags
+ 1, // Motherboard
+ 0, // RequiresDaughterCard
+ 0, // Removable
+ 1, // Replaceable,
+ 0, // HotSwappable
+ 0, // Reserved
+ },
+ EfiBaseBoardTypeUnknown, // BaseBoardType
+ { // BaseBoardChassisLink
+ EFI_MISC_SUBCLASS_GUID, // ProducerName
+ 1, // Instance
+ 1, // SubInstance
+ },
+ 0, // BaseBoardNumberLinks
+ { // LinkN
+ EFI_MISC_SUBCLASS_GUID, // ProducerName
+ 1, // Instance
+ 1, // SubInstance
+ },
+};
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturerFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturerFunction.c
new file mode 100755
index 0000000..2afc072
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBaseBoardManufacturerFunction.c
@@ -0,0 +1,202 @@
+/** @file
+ Base Board Information boot time changes.
+ Misc. subclass type 4.
+ SMBIOS type 2.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "CommonHeader.h"
+#include "SmbiosMisc.h"
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscBaseBoardManufacturer (Type 2).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscBaseBoardManufacturer)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN ManuStrLen;
+ UINTN ProductStrLen;
+ UINTN VerStrLen;
+ UINTN AssertTagStrLen;
+ UINTN SerialNumStrLen;
+ UINTN ChassisStrLen;
+ EFI_STATUS Status;
+ EFI_STRING Manufacturer;
+ EFI_STRING Product;
+ EFI_STRING Version;
+ EFI_STRING SerialNumber;
+ EFI_STRING AssertTag;
+ EFI_STRING Chassis;
+ STRING_REF TokenToGet;
+ STRING_REF TokenToUpdate;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE2 *SmbiosRecord;
+ EFI_MISC_BASE_BOARD_MANUFACTURER *ForType2InputData;
+ EFI_PLATFORM_TYPE_PROTOCOL *PlatformType;
+
+ ForType2InputData = (EFI_MISC_BASE_BOARD_MANUFACTURER *)RecordData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_MANUFACTURER);
+ Manufacturer = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ManuStrLen = StrLen(Manufacturer);
+ if (ManuStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiPlatformTypeProtocolGuid, NULL, (VOID **) &PlatformType);
+ ASSERT_EFI_ERROR (Status);
+
+ if (StrLen (PlatformType->TypeStringPtr) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME);
+ HiiSetString (mHiiHandle, TokenToUpdate, PlatformType->TypeStringPtr, NULL);
+ }
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME);
+ Product = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ProductStrLen = StrLen(PlatformType->TypeStringPtr);
+ if (ProductStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+ StrCpy(PlatformType->TypeStringPtr, Product);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_VERSION);
+ Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VerStrLen = StrLen(Version);
+ if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_SERIAL_NUMBER);
+ SerialNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SerialNumStrLen = StrLen(SerialNumber);
+ if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_ASSET_TAG);
+ AssertTag = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ AssertTagStrLen = StrLen(AssertTag);
+ if (AssertTagStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_CHASSIS_LOCATION);
+ Chassis = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ChassisStrLen = StrLen(Chassis);
+ if (ChassisStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE3) + ManuStrLen + 1 + ProductStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1 + ChassisStrLen +1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE3) + ManuStrLen + 1 + ProductStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1 + ChassisStrLen +1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE2);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ //
+ // Manu will be the 1st optional string following the formatted structure.
+ //
+ SmbiosRecord->Manufacturer = 1;
+ //
+ // ProductName will be the 2st optional string following the formatted structure.
+ //
+ SmbiosRecord->ProductName = 2;
+ //
+ // Version will be the 3rd optional string following the formatted structure.
+ //
+ SmbiosRecord->Version = 3;
+ //
+ // SerialNumber will be the 4th optional string following the formatted structure.
+ //
+ SmbiosRecord->SerialNumber = 4;
+ //
+ // AssertTag will be the 5th optional string following the formatted structure.
+ //
+ SmbiosRecord->AssetTag = 5;
+
+ //
+ // LocationInChassis will be the 6th optional string following the formatted structure.
+ //
+ SmbiosRecord->LocationInChassis = 6;
+ SmbiosRecord->FeatureFlag = (*(BASE_BOARD_FEATURE_FLAGS*)&(ForType2InputData->BaseBoardFeatureFlags));
+ SmbiosRecord->ChassisHandle = 0;
+ SmbiosRecord->BoardType = (UINT8)ForType2InputData->BaseBoardType;
+ SmbiosRecord->NumberOfContainedObjectHandles = 0;
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ //
+ // Since we fill NumberOfContainedObjectHandles = 0 for simple, just after this filed to fill string
+ //
+ //OptionalStrStart -= 2;
+ UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart);
+ UnicodeStrToAsciiStr(Product, OptionalStrStart + ManuStrLen + 1);
+ UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1 + ProductStrLen + 1);
+ UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + ProductStrLen + 1 + VerStrLen + 1);
+ UnicodeStrToAsciiStr(AssertTag, OptionalStrStart + ManuStrLen + 1 + ProductStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1);
+ UnicodeStrToAsciiStr(Chassis, OptionalStrStart + ManuStrLen + 1 + ProductStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendor.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendor.uni
new file mode 100644
index 0000000..e38b656
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendor.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendorData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendorData.c
new file mode 100644
index 0000000..c67a282
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendorData.c
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscBiosVendorData.c
+
+Abstract:
+
+ BIOS vendor information static data.
+ Misc. subclass type 2.
+ SMBIOS type 0.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_BIOS_VENDOR, MiscBiosVendor) = {
+ STRING_TOKEN (STR_MISC_BIOS_VENDOR), // BiosVendor
+ STRING_TOKEN (STR_MISC_BIOS_VERSION), // BiosVersion
+ STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE), // BiosReleaseDate
+ 0xE0000, // BiosStartingAddress
+ { // BiosPhysicalDeviceSize
+ 2, // Value
+ 20, // Exponent
+ },
+ { // BiosCharacteristics1
+ 0, // Reserved1 :2
+ 0, // Unknown :1
+ 0, // BiosCharacteristicsNotSupported :1
+ 0, // IsaIsSupported :1
+ 0, // McaIsSupported :1
+
+ 0, // EisaIsSupported :1
+ 1, // PciIsSupported :1
+ 0, // PcmciaIsSupported :1
+ 0, // PlugAndPlayIsSupported :1
+ 0, // ApmIsSupported :1
+
+ 1, // BiosIsUpgradable :1
+ 1, // BiosShadowingAllowed :1
+ 0, // VlVesaIsSupported :1
+ 0, // EscdSupportIsAvailable :1
+ 1, // BootFromCdIsSupported :1
+
+ 1, // SelectableBootIsSupported :1
+ 0, // RomBiosIsSocketed :1
+ 0, // BootFromPcmciaIsSupported :1
+ 1, // EDDSpecificationIsSupported :1
+ 0, // JapaneseNecFloppyIsSupported :1
+
+ 0, // JapaneseToshibaFloppyIsSupported :1
+ 0, // Floppy525_360IsSupported :1
+ 0, // Floppy525_12IsSupported :1
+ 0, // Floppy35_720IsSupported :1
+ 0, // Floppy35_288IsSupported :1
+
+ 1, // PrintScreenIsSupported :1
+ 1, // Keyboard8042IsSupported :1
+ 1, // SerialIsSupported :1
+ 1, // PrinterIsSupported :1
+ 1, // CgaMonoIsSupported :1
+
+ 0, // NecPc98 :1
+ 1, // AcpiIsSupported :1
+ 1, // UsbLegacyIsSupported :1
+ 0, // AgpIsSupported :1
+ 0, // I20BootIsSupported :1
+
+ 0, // Ls120BootIsSupported :1
+ 0, // AtapiZipDriveBootIsSupported :1
+ 0, // Boot1394IsSupported :1
+ 0, // SmartBatteryIsSupported :1
+ 1, // BiosBootSpecIsSupported :1
+
+ 1, // FunctionKeyNetworkBootIsSupported :1
+ 0 // Reserved :22
+ },
+ { // BiosCharacteristics2
+ 0, // BiosReserved :16
+ 0, // SystemReserved :16
+ 0 // Reserved :32
+ },
+ 0x1, // System BIOS Major Release
+ 0x0, // System BIOS Minor Release
+ 0xFF, // Embedded controller firmware major Release
+ 0xFF, // Embedded controller firmware minor Release
+};
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendorFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendorFunction.c
new file mode 100755
index 0000000..423b1d9
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBiosVendorFunction.c
@@ -0,0 +1,256 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscBiosVendorFunction.c
+
+Abstract:
+
+ BIOS vendor information boot time changes.
+ Misc. subclass type 2.
+ SMBIOS type 0.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+/**
+ This function returns the value & exponent to Base2 for a given
+ Hex value. This is used to calculate the BiosPhysicalDeviceSize.
+
+ @param Value The hex value which is to be converted into value-exponent form
+ @param Exponent The exponent out of the conversion
+
+ @retval EFI_SUCCESS All parameters were valid and *Value & *Exponent have been set.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+EFI_STATUS
+GetValueExponentBase2(
+ IN OUT UINTN *Value,
+ OUT UINTN *Exponent
+ )
+{
+ if ((Value == NULL) || (Exponent == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while ((*Value % 2) == 0) {
+ *Value=*Value/2;
+ (*Exponent)++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'
+ as the unit.
+
+ @param Base2Data Pointer to Base2_Data
+
+ @retval EFI_SUCCESS Transform successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+UINT16
+Base2ToByteWith64KUnit (
+ IN EFI_EXP_BASE2_DATA *Base2Data
+ )
+{
+ UINT16 Value;
+ UINT16 Exponent;
+
+ Value = Base2Data->Value;
+ Exponent = Base2Data->Exponent;
+ Exponent -= 16;
+ Value <<= Exponent;
+
+ return Value;
+}
+
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscBiosVendor (Type 0).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscBiosVendor)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN VendorStrLen;
+ UINTN VerStrLen;
+ UINTN DateStrLen;
+ UINTN BiosPhysicalSizeHexValue;
+ UINTN BiosPhysicalSizeExponent;
+ CHAR16 Version[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 Vendor[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 ReleaseDate[SMBIOS_STRING_MAX_LENGTH];
+ EFI_STRING VersionPtr;
+ EFI_STRING VendorPtr;
+ EFI_STRING ReleaseDatePtr;
+ EFI_STATUS Status;
+ STRING_REF TokenToGet;
+ STRING_REF TokenToUpdate;
+ SMBIOS_TABLE_TYPE0 *SmbiosRecord;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_MISC_BIOS_VENDOR *ForType0InputData;
+ EFI_PLATFORM_TYPE_PROTOCOL *PlatformType;
+
+ BiosPhysicalSizeHexValue = 0x0;
+ BiosPhysicalSizeExponent = 0x0;
+ ForType0InputData = (EFI_MISC_BIOS_VENDOR *)RecordData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Now update the BiosPhysicalSize
+ //
+ BiosPhysicalSizeHexValue = PcdGet32 (PcdFlashAreaSize);
+ Status= GetValueExponentBase2 (
+ &BiosPhysicalSizeHexValue,
+ &BiosPhysicalSizeExponent
+ );
+ if(Status == EFI_SUCCESS){
+ ForType0InputData->BiosPhysicalDeviceSize.Value = (UINT16)BiosPhysicalSizeHexValue;
+ ForType0InputData->BiosPhysicalDeviceSize.Exponent = (UINT16)BiosPhysicalSizeExponent;
+ }
+ //
+ // Update strings from PCD
+ //
+ AsciiStrToUnicodeStr (PcdGetPtr (PcdSMBIOSBiosVendor), Vendor);
+ if (StrLen (Vendor) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VENDOR);
+ HiiSetString (mHiiHandle, TokenToUpdate, Vendor, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VENDOR);
+ VendorPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VendorStrLen = StrLen(VendorPtr);
+ if (VendorStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiPlatformTypeProtocolGuid, NULL, (VOID **) &PlatformType);
+ ASSERT_EFI_ERROR (Status);
+ UnicodeSPrint (Version, sizeof (Version), L"0x%08x", PlatformType->FirmwareVersion);
+ if (StrLen (Version) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+ VersionPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VerStrLen = StrLen(VersionPtr);
+ if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr (PcdSMBIOSBiosReleaseDate), ReleaseDate);
+ if (StrLen (ReleaseDate) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);
+ HiiSetString (mHiiHandle, TokenToUpdate, ReleaseDate, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);
+ ReleaseDatePtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ DateStrLen = StrLen(ReleaseDatePtr);
+ if (DateStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 + VerStrLen + 1 + DateStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 + VerStrLen + 1 + DateStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_BIOS_INFORMATION;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE0);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ //
+ // Vendor will be the 1st optional string following the formatted structure.
+ //
+ SmbiosRecord->Vendor = 1;
+ //
+ // Version will be the 2nd optional string following the formatted structure.
+ //
+ SmbiosRecord->BiosVersion = 2;
+ SmbiosRecord->BiosSegment = PcdGet16 (PcdSMBIOSBiosStartAddress);
+ //
+ // ReleaseDate will be the 3rd optional string following the formatted structure.
+ //
+ SmbiosRecord->BiosReleaseDate = 3;
+ SmbiosRecord->BiosSize = (UINT8)(Base2ToByteWith64KUnit(&ForType0InputData->BiosPhysicalDeviceSize) - 1);
+ *(UINT64 *)&SmbiosRecord->BiosCharacteristics = PcdGet64 (PcdSMBIOSBiosChar);
+ //
+ // CharacterExtensionBytes also store in ForType0InputData->BiosCharacteristics1 later two bytes to save size.
+ //
+ SmbiosRecord->BIOSCharacteristicsExtensionBytes[0] = PcdGet8 (PcdSMBIOSBiosCharEx1);
+ SmbiosRecord->BIOSCharacteristicsExtensionBytes[1] = PcdGet8 (PcdSMBIOSBiosCharEx2);
+
+ SmbiosRecord->SystemBiosMajorRelease = ForType0InputData->BiosMajorRelease;
+ SmbiosRecord->SystemBiosMinorRelease = ForType0InputData->BiosMinorRelease;
+ SmbiosRecord->EmbeddedControllerFirmwareMajorRelease = ForType0InputData->BiosEmbeddedFirmwareMajorRelease;
+ SmbiosRecord->EmbeddedControllerFirmwareMinorRelease = ForType0InputData->BiosEmbeddedFirmwareMinorRelease;
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(VendorPtr, OptionalStrStart);
+ UnicodeStrToAsciiStr(VersionPtr, OptionalStrStart + VendorStrLen + 1);
+ UnicodeStrToAsciiStr(ReleaseDatePtr, OptionalStrStart + VendorStrLen + 1 + VerStrLen + 1);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBootInformationData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBootInformationData.c
new file mode 100644
index 0000000..a3a49fa
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBootInformationData.c
@@ -0,0 +1,55 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscBootInformationData.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to the DataHub.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data. SMBIOS TYPE 32
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_BOOT_INFORMATION_STATUS, MiscBootInfoStatus) = {
+ EfiBootInformationStatusNoError, // BootInformationStatus
+ 0 // BootInformationData
+};
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBootInformationFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBootInformationFunction.c
new file mode 100755
index 0000000..9ede763
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscBootInformationFunction.c
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscBootInformationFunction.c
+
+Abstract:
+
+ boot information boot time changes.
+ SMBIOS type 32.
+
+--*/
+
+
+#include "CommonHeader.h"
+#include "SmbiosMisc.h"
+
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscBootInformation (Type 32).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+
+MISC_SMBIOS_TABLE_FUNCTION(MiscBootInfoStatus)
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE32 *SmbiosRecord;
+ EFI_MISC_BOOT_INFORMATION_STATUS* ForType32InputData;
+
+ ForType32InputData = (EFI_MISC_BOOT_INFORMATION_STATUS *)RecordData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE32) + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE32) + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE32);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ SmbiosRecord->BootStatus = (UINT8)ForType32InputData->BootInformationStatus;
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturer.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturer.uni
new file mode 100644
index 0000000..a998d0c
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturer.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturerData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturerData.c
new file mode 100644
index 0000000..36eea6b
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturerData.c
@@ -0,0 +1,67 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscChassisManufacturerData.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to the DataHub.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Chassis Manufacturer data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_CHASSIS_MANUFACTURER, MiscChassisManufacturer) = {
+ STRING_TOKEN(STR_MISC_CHASSIS_MANUFACTURER), // ChassisManufactrurer
+ STRING_TOKEN(STR_MISC_CHASSIS_VERSION), // ChassisVersion
+ STRING_TOKEN(STR_MISC_CHASSIS_SERIAL_NUMBER), // ChassisSerialNumber
+ STRING_TOKEN(STR_MISC_CHASSIS_ASSET_TAG), // ChassisAssetTag
+ { // ChassisTypeStatus
+ EfiMiscChassisTypeDeskTop, // ChassisType
+ 0, // ChassisLockPresent
+ 0 // Reserved
+ },
+ EfiChassisStateSafe, // ChassisBootupState
+ EfiChassisStateSafe, // ChassisPowerSupplyState
+ EfiChassisStateOther, // ChassisThermalState
+ EfiChassisSecurityStatusOther, // ChassisSecurityState
+ 0 // ChassisOemDefined
+};
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturerFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturerFunction.c
new file mode 100755
index 0000000..ffaabc6
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscChassisManufacturerFunction.c
@@ -0,0 +1,199 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscChassisManufacturerFunction.c
+
+Abstract:
+
+ Chassis manufacturer information boot time changes.
+ SMBIOS type 3.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscChassisManufacturer (Type 3).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscChassisManufacturer)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN ManuStrLen;
+ UINTN VerStrLen;
+ UINTN AssertTagStrLen;
+ UINTN SerialNumStrLen;
+ EFI_STATUS Status;
+ CHAR16 Manufacturer[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 Version[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 SerialNumber[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 AssertTag[SMBIOS_STRING_MAX_LENGTH];
+ EFI_STRING ManufacturerPtr;
+ EFI_STRING VersionPtr;
+ EFI_STRING SerialNumberPtr;
+ EFI_STRING AssertTagPtr;
+ STRING_REF TokenToGet;
+ STRING_REF TokenToUpdate;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE3 *SmbiosRecord;
+ EFI_MISC_CHASSIS_MANUFACTURER *ForType3InputData;
+
+ ForType3InputData = (EFI_MISC_CHASSIS_MANUFACTURER *)RecordData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Update strings from PCD
+ //
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSChassisManufacturer), Manufacturer);
+ if (StrLen (Manufacturer) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER);
+ HiiSetString (mHiiHandle, TokenToUpdate, Manufacturer, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER);
+ ManufacturerPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ManuStrLen = StrLen(ManufacturerPtr);
+ if (ManuStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSChassisVersion), Version);
+ if (StrLen (Version) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_CHASSIS_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_VERSION);
+ VersionPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VerStrLen = StrLen(VersionPtr);
+ if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSChassisSerialNumber), SerialNumber);
+ if (StrLen (SerialNumber) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER);
+ HiiSetString (mHiiHandle, TokenToUpdate, SerialNumber, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER);
+ SerialNumberPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SerialNumStrLen = StrLen(SerialNumberPtr);
+ if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSChassisAssetTag), AssertTag);
+ if (StrLen (AssertTag) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG);
+ HiiSetString (mHiiHandle, TokenToUpdate, AssertTag, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG);
+ AssertTagPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ AssertTagStrLen = StrLen(AssertTagPtr);
+ if (AssertTagStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE3) + ManuStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE3) + ManuStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE3);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ //
+ // Manu will be the 1st optional string following the formatted structure.
+ //
+ SmbiosRecord->Manufacturer = 1;
+ SmbiosRecord->Type = PcdGet8 (PcdSMBIOSChassisType);
+ //
+ // Version will be the 2nd optional string following the formatted structure.
+ //
+ SmbiosRecord->Version = 2;
+ //
+ // SerialNumber will be the 3rd optional string following the formatted structure.
+ //
+ SmbiosRecord->SerialNumber = 3;
+ //
+ // AssertTag will be the 4th optional string following the formatted structure.
+ //
+ SmbiosRecord->AssetTag = 4;
+ SmbiosRecord->BootupState = PcdGet8 (PcdSMBIOSChassisBootupState);
+ SmbiosRecord->PowerSupplyState = PcdGet8 (PcdSMBIOSChassisPowerSupplyState);
+ SmbiosRecord->ThermalState = (UINT8)ForType3InputData->ChassisThermalState;
+ SmbiosRecord->SecurityStatus = PcdGet8 (PcdSMBIOSChassisSecurityState);
+ *(UINT32 *)&SmbiosRecord->OemDefined = PcdGet32 (PcdSMBIOSChassisOemDefined);
+ SmbiosRecord->Height = PcdGet8 (PcdSMBIOSChassisHeight);
+ SmbiosRecord->NumberofPowerCords = PcdGet8 (PcdSMBIOSChassisNumberPowerCords);
+ SmbiosRecord->ContainedElementCount = PcdGet8 (PcdSMBIOSChassisElementCount);
+ SmbiosRecord->ContainedElementRecordLength = PcdGet8 (PcdSMBIOSChassisElementRecordLength);
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(ManufacturerPtr, OptionalStrStart);
+ UnicodeStrToAsciiStr(VersionPtr, OptionalStrStart + ManuStrLen + 1);
+ UnicodeStrToAsciiStr(SerialNumberPtr, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1);
+ UnicodeStrToAsciiStr(AssertTagPtr, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscDevicePath.h b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscDevicePath.h
new file mode 100644
index 0000000..b37de0e
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscDevicePath.h
@@ -0,0 +1,73 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscDevicePath.h
+
+Abstract:
+
+ Misc class required EFI Device Path definitions (Ports, slots &
+ onboard devices)
+
+--*/
+
+#ifndef _MISC_DEVICE_PATH_H
+#define _MISC_DEVICE_PATH_H
+
+#pragma pack(1)
+
+//USB
+/* For reference:
+#define USB1_1_STR "ACPI(PNP0A03,0)/PCI(1D,0)."
+#define USB1_2_STR "ACPI(PNP0A03,0)/PCI(1D,1)."
+#define USB1_3_STR "ACPI(PNP0A03,0)/PCI(1D,2)."
+#define USB2_1_STR "ACPI(PNP0A03,0)/PCI(1D,7)."
+*/
+
+#define DP_ACPI { ACPI_DEVICE_PATH,\
+ ACPI_DP, (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),\
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8), EISA_PNP_ID(0x0A03), 0 }
+#define DP_PCI( device,function) { HARDWARE_DEVICE_PATH,\
+ HW_PCI_DP, (UINT8) (sizeof (PCI_DEVICE_PATH)),\
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8), function, device }
+#define DP_END { END_DEVICE_PATH_TYPE, \
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, END_DEVICE_PATH_LENGTH, 0 }
+
+#define DP_LPC(eisaid,function ){ ACPI_DEVICE_PATH, \
+ACPI_DP,(UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),\
+(UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8),EISA_PNP_ID(eisaid), function }
+
+
+#pragma pack()
+
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscNumberOfInstallableLanguagesData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscNumberOfInstallableLanguagesData.c
new file mode 100644
index 0000000..1559680
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscNumberOfInstallableLanguagesData.c
@@ -0,0 +1,59 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscNumberOfInstallableLanguagesData.c
+
+Abstract:
+
+ This driver parses the mSmbiosMiscDataTable structure and reports
+ any generated data to SMBIOS.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES, NumberOfInstallableLanguages) = {
+ 2, // NumberOfInstallableLanguages
+ { // LanguageFlags
+ 0, // AbbreviatedLanguageFormat
+ 0 // Reserved
+ },
+ 1, // CurrentLanguageNumber
+};
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscNumberOfInstallableLanguagesFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscNumberOfInstallableLanguagesFunction.c
new file mode 100644
index 0000000..8f48e68
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscNumberOfInstallableLanguagesFunction.c
@@ -0,0 +1,273 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscNumberOfInstallableLanguagesFunction.c
+
+Abstract:
+
+ This driver parses the mSmbiosMiscDataTable structure and reports
+ any generated data.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+/*++
+ Check whether the language is supported for given HII handle
+
+ @param HiiHandle The HII package list handle.
+ @param Offset The offest of current lanague in the supported languages.
+ @param CurrentLang The language code.
+
+ @retval TRUE Supported.
+ @retval FALSE Not Supported.
+
+--*/
+BOOLEAN
+EFIAPI
+CurrentLanguageMatch (
+ IN EFI_HII_HANDLE HiiHandle,
+ OUT UINT16 *Offset,
+ OUT CHAR8 *CurrentLang
+ )
+{
+ CHAR8 *DefaultLang;
+ CHAR8 *BestLanguage;
+ CHAR8 *Languages;
+ CHAR8 *MatchLang;
+ CHAR8 *EndMatchLang;
+ UINTN CompareLength;
+ BOOLEAN LangMatch;
+
+ Languages = HiiGetSupportedLanguages (HiiHandle);
+ if (Languages == NULL) {
+ return FALSE;
+ }
+
+ LangMatch = FALSE;
+ CurrentLang = GetEfiGlobalVariable (L"PlatformLang");
+ DefaultLang = (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang);
+ BestLanguage = GetBestLanguage (
+ Languages,
+ FALSE,
+ (CurrentLang != NULL) ? CurrentLang : "",
+ DefaultLang,
+ NULL
+ );
+ if (BestLanguage != NULL) {
+ //
+ // Find the best matching RFC 4646 language, compute the offset.
+ //
+ LangMatch = TRUE;
+ CompareLength = AsciiStrLen (BestLanguage);
+ for (MatchLang = Languages, (*Offset) = 0; MatchLang != '\0'; (*Offset)++) {
+ //
+ // Seek to the end of current match language.
+ //
+ for (EndMatchLang = MatchLang; *EndMatchLang != '\0' && *EndMatchLang != ';'; EndMatchLang++);
+
+ if ((EndMatchLang == MatchLang + CompareLength) && AsciiStrnCmp(MatchLang, BestLanguage, CompareLength) == 0) {
+ //
+ // Find the current best Language in the supported languages
+ //
+ break;
+ }
+ //
+ // best language match be in the supported language.
+ //
+ ASSERT (*EndMatchLang == ';');
+ MatchLang = EndMatchLang + 1;
+ }
+ FreePool (BestLanguage);
+ }
+
+ FreePool (Languages);
+ if (CurrentLang != NULL) {
+ FreePool (CurrentLang);
+ }
+ return LangMatch;
+}
+
+
+/**
+ Get next language from language code list (with separator ';').
+
+ @param LangCode Input: point to first language in the list. On
+ Otput: point to next language in the list, or
+ NULL if no more language in the list.
+ @param Lang The first language in the list.
+
+**/
+VOID
+EFIAPI
+GetNextLanguage (
+ IN OUT CHAR8 **LangCode,
+ OUT CHAR8 *Lang
+ )
+{
+ UINTN Index;
+ CHAR8 *StringPtr;
+
+ ASSERT (LangCode != NULL);
+ ASSERT (*LangCode != NULL);
+ ASSERT (Lang != NULL);
+
+ Index = 0;
+ StringPtr = *LangCode;
+ while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
+ Index++;
+ }
+
+ CopyMem (Lang, StringPtr, Index);
+ Lang[Index] = 0;
+
+ if (StringPtr[Index] == ';') {
+ Index++;
+ }
+ *LangCode = StringPtr + Index;
+}
+
+/**
+ This function returns the number of supported languages on HiiHandle.
+
+ @param HiiHandle The HII package list handle.
+
+ @retval The number of supported languages.
+
+**/
+UINT16
+EFIAPI
+GetSupportedLanguageNumber (
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ CHAR8 *Lang;
+ CHAR8 *Languages;
+ CHAR8 *LanguageString;
+ UINT16 LangNumber;
+
+ Languages = HiiGetSupportedLanguages (HiiHandle);
+ if (Languages == NULL) {
+ return 0;
+ }
+
+ LangNumber = 0;
+ Lang = AllocatePool (AsciiStrSize (Languages));
+ if (Lang != NULL) {
+ LanguageString = Languages;
+ while (*LanguageString != 0) {
+ GetNextLanguage (&LanguageString, Lang);
+ LangNumber++;
+ }
+ FreePool (Lang);
+ }
+ FreePool (Languages);
+ return LangNumber;
+}
+
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscNumberOfInstallableLanguages (Type 13).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(NumberOfInstallableLanguages)
+{
+ UINTN LangStrLen;
+ CHAR8 CurrentLang[SMBIOS_STRING_MAX_LENGTH + 1];
+ CHAR8 *OptionalStrStart;
+ UINT16 Offset;
+ BOOLEAN LangMatch;
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE13 *SmbiosRecord;
+ EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES *ForType13InputData;
+
+ ForType13InputData = (EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES *)RecordData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ForType13InputData->NumberOfInstallableLanguages = GetSupportedLanguageNumber (mHiiHandle);
+
+ //
+ // Try to check if current langcode matches with the langcodes in installed languages
+ //
+ LangMatch = FALSE;
+ ZeroMem(CurrentLang, SMBIOS_STRING_MAX_LENGTH + 1);
+ LangMatch = CurrentLanguageMatch (mHiiHandle, &Offset, CurrentLang);
+ LangStrLen = AsciiStrLen(CurrentLang);
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE13);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+
+ SmbiosRecord->InstallableLanguages = (UINT8)ForType13InputData->NumberOfInstallableLanguages;
+ SmbiosRecord->Flags = (UINT8)ForType13InputData->LanguageFlags.AbbreviatedLanguageFormat;
+ SmbiosRecord->CurrentLanguages = 1;
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ AsciiStrCpy(OptionalStrStart, CurrentLang);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemString.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemString.uni
new file mode 100644
index 0000000..00594ba
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemString.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemStringData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemStringData.c
new file mode 100644
index 0000000..143cf1e
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemStringData.c
@@ -0,0 +1,44 @@
+/** @file
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to smbios.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) OEM String data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_OEM_STRING, MiscOemString)
+= { STRING_TOKEN(STR_MISC_OEM_EN_US) };
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemStringFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemStringFunction.c
new file mode 100644
index 0000000..30b99eb
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOemStringFunction.c
@@ -0,0 +1,112 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ MiscOemStringFunction.c
+
+Abstract:
+
+ boot information boot time changes.
+ SMBIOS type 11.
+
+--*/
+
+
+#include "CommonHeader.h"
+#include "SmbiosMisc.h"
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscOemString (Type 11).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscOemString)
+{
+ UINTN OemStrLen;
+ CHAR8 *OptionalStrStart;
+ EFI_STATUS Status;
+ EFI_STRING OemStr;
+ STRING_REF TokenToGet;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE11 *SmbiosRecord;
+ EFI_MISC_OEM_STRING *ForType11InputData;
+
+ ForType11InputData = (EFI_MISC_OEM_STRING *)RecordData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TokenToGet = STRING_TOKEN (STR_MISC_OEM_EN_US);
+ OemStr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ OemStrLen = StrLen(OemStr);
+ if (OemStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE11) + OemStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE11) + OemStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_OEM_STRINGS;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE11);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ SmbiosRecord->StringCount = 1;
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(OemStr, OptionalStrStart);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDevice.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDevice.uni
new file mode 100644
index 0000000..988c93d
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDevice.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDeviceData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDeviceData.c
new file mode 100644
index 0000000..83b3bfb
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDeviceData.c
@@ -0,0 +1,80 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscOnboardDeviceData.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to smbios.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_ONBOARD_DEVICE, MiscOnboardDeviceVideo) = {
+ STRING_TOKEN(STR_MISC_ONBOARD_DEVICE_VIDEO), // OnBoardDeviceDescription
+ { // OnBoardDeviceStatus
+ EfiOnBoardDeviceTypeVideo, // DeviceType
+ 1, // DeviceEnabled
+ 0 // Reserved
+ },
+ 0 // OnBoardDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_ONBOARD_DEVICE, MiscOnboardDeviceNetwork) = {
+ STRING_TOKEN(STR_MISC_ONBOARD_DEVICE_NETWORK), // OnBoardDeviceDescription
+ { // OnBoardDeviceStatus
+ EfiOnBoardDeviceTypeEthernet, // DeviceType
+ 1, // DeviceEnabled
+ 0 // Reserved
+ },
+ 0 // OnBoardDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_ONBOARD_DEVICE, MiscOnboardDeviceAudio) = {
+ STRING_TOKEN(STR_MISC_ONBOARD_DEVICE_AUDIO), // OnBoardDeviceDescription
+ { // OnBoardDeviceStatus
+ EfiOnBoardDeviceTypeSound, // DeviceType
+ 1, // DeviceEnabled
+ 0 // Reserved
+ },
+ DP_END // OnBoardDevicePath
+};
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDeviceFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDeviceFunction.c
new file mode 100644
index 0000000..babe231
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscOnboardDeviceFunction.c
@@ -0,0 +1,136 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscOnboardDeviceFunction.c
+
+Abstract:
+
+ Onboard device information boot time changes.
+ SMBIOS type 10.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscOnboardDevice (Type 10).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscOnboardDevice)
+{
+ CHAR8 *OptionalStrStart;
+ UINT8 StatusAndType;
+ UINTN DescriptionStrLen;
+ EFI_STRING DeviceDescription;
+ STRING_REF TokenToGet;
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE10 *SmbiosRecord;
+ EFI_MISC_ONBOARD_DEVICE *ForType10InputData;
+
+ ForType10InputData = (EFI_MISC_ONBOARD_DEVICE *)RecordData;
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TokenToGet = 0;
+ switch (ForType10InputData->OnBoardDeviceDescription) {
+ case STR_MISC_ONBOARD_DEVICE_VIDEO:
+ TokenToGet = STRING_TOKEN (STR_MISC_ONBOARD_DEVICE_VIDEO);
+ break;
+ case STR_MISC_ONBOARD_DEVICE_AUDIO:
+ TokenToGet = STRING_TOKEN (STR_MISC_ONBOARD_DEVICE_AUDIO);
+ break;
+ }
+
+ DeviceDescription = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ DescriptionStrLen = StrLen(DeviceDescription);
+ if (DescriptionStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE10) + DescriptionStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE10) + DescriptionStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_ONBOARD_DEVICE_INFORMATION;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE10);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+
+ //
+ // Status & Type: Bit 7 Devicen Status, Bits 6:0 Type of Device
+ //
+ StatusAndType = (UINT8) ForType10InputData->OnBoardDeviceStatus.DeviceType;
+ if (ForType10InputData->OnBoardDeviceStatus.DeviceEnabled != 0) {
+ StatusAndType |= 0x80;
+ } else {
+ StatusAndType &= 0x7F;
+ }
+
+ SmbiosRecord->Device[0].DeviceType = StatusAndType;
+ SmbiosRecord->Device[0].DescriptionString = 1;
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(DeviceDescription, OptionalStrStart);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignator.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignator.uni
new file mode 100644
index 0000000..d5bdc70
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignator.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignatorData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignatorData.c
new file mode 100644
index 0000000..94621f6
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignatorData.c
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscPortInternalConnectorDesignatorData.c
+
+Abstract:
+
+ This driver parses the mSmbiosMiscDataTable structure and reports
+ any generated data to the DataHub.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector1) = {
+ STRING_TOKEN (STR_MISC_PORT1_INTERNAL_DESIGN), // PortInternalConnectorDesignator
+ STRING_TOKEN (STR_MISC_PORT1_EXTERNAL_DESIGN), // PortExternalConnectorDesignator
+ EfiPortConnectorTypeNone, // PortInternalConnectorType
+ EfiPortConnectorTypePS2, // PortExternalConnectorType
+ EfiPortTypeKeyboard, // PortType
+ //mPs2KbyboardDevicePath // PortPath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector2) = {
+ STRING_TOKEN (STR_MISC_PORT2_INTERNAL_DESIGN), // PortInternalConnectorDesignator
+ STRING_TOKEN (STR_MISC_PORT2_EXTERNAL_DESIGN), // PortExternalConnectorDesignator
+ EfiPortConnectorTypeNone, // PortInternalConnectorType
+ EfiPortConnectorTypePS2, // PortExternalConnectorType
+ EfiPortTypeMouse, // PortType
+ //mPs2MouseDevicePath // PortPath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector3) = {
+ STRING_TOKEN (STR_MISC_PORT3_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT3_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeOther,
+ EfiPortConnectorTypeNone,
+ EfiPortTypeSerial16550ACompatible,
+ //mCom1DevicePath
+ 0
+};
+
+
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector4) = {
+ STRING_TOKEN (STR_MISC_PORT4_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT4_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeNone,
+ EfiPortConnectorTypeRJ45,
+ EfiPortTypeSerial16550ACompatible,
+ //mCom2DevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector5) = {
+ STRING_TOKEN (STR_MISC_PORT5_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT5_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeOther,
+ EfiPortConnectorTypeNone,
+ EfiPortTypeSerial16550ACompatible,
+ //mCom3DevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector6) = {
+ STRING_TOKEN (STR_MISC_PORT6_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT6_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeNone,
+ EfiPortConnectorTypeRJ45,
+ EfiPortTypeSerial16550ACompatible,
+ //mCom3DevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector7) = {
+ STRING_TOKEN (STR_MISC_PORT7_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT7_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeNone,
+ EfiPortConnectorTypeDB25Male,
+ EfiPortTypeParallelPortEcpEpp,
+ //mLpt1DevicePath
+ 0
+};
+
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector8) = {
+ STRING_TOKEN (STR_MISC_PORT8_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT8_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeNone,
+ EfiPortConnectorTypeUsb,
+ EfiPortTypeUsb,
+ //mUsb0DevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector9) = {
+ STRING_TOKEN (STR_MISC_PORT9_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT9_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeNone,
+ EfiPortConnectorTypeUsb,
+ EfiPortTypeUsb,
+ //mUsb1DevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector10) = {
+ STRING_TOKEN (STR_MISC_PORT10_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT10_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeNone,
+ EfiPortConnectorTypeUsb,
+ EfiPortTypeUsb,
+ //mUsb2DevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector11) = {
+ STRING_TOKEN (STR_MISC_PORT11_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT11_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeNone,
+ EfiPortConnectorTypeUsb,
+ EfiPortTypeUsb,
+ //mUsb3DevicePath
+ 0
+};
+
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector12) = {
+ STRING_TOKEN (STR_MISC_PORT12_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT12_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeNone,
+ EfiPortConnectorTypeRJ45,
+ EfiPortTypeNetworkPort,
+ //mGbNicDevicePath
+ 0
+};
+
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector13) = {
+ STRING_TOKEN (STR_MISC_PORT13_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT13_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeOnboardFloppy,
+ EfiPortConnectorTypeNone,
+ EfiPortTypeOther,
+ //mFloopyADevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector14) = {
+ STRING_TOKEN (STR_MISC_PORT14_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT14_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeOnboardIde,
+ EfiPortConnectorTypeNone,
+ EfiPortTypeOther,
+ //mIdeDevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector15) = {
+ STRING_TOKEN (STR_MISC_PORT15_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT15_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeOnboardIde,
+ EfiPortConnectorTypeNone,
+ EfiPortTypeOther,
+ //mSataDevicePath
+ 0
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector16) = {
+ STRING_TOKEN (STR_MISC_PORT16_INTERNAL_DESIGN),
+ STRING_TOKEN (STR_MISC_PORT16_EXTERNAL_DESIGN),
+ EfiPortConnectorTypeOnboardIde,
+ EfiPortConnectorTypeNone,
+ EfiPortTypeOther,
+ //mSataDevicePath
+ 0
+};
+
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignatorFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignatorFunction.c
new file mode 100755
index 0000000..bd4941c
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscPortInternalConnectorDesignatorFunction.c
@@ -0,0 +1,323 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscPortInternalConnectorDesignatorFunction.c
+
+Abstract:
+
+ Port internal connector designator information boot time changes.
+ SMBIOS type 8.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+//STATIC PS2_CONN_DEVICE_PATH mPs2KeyboardDevicePath = { DP_ACPI, DP_PCI( 0x1F,0x00 ),DP_LPC( 0x0303,0 ), DP_END };
+//STATIC PS2_CONN_DEVICE_PATH mPs2MouseDevicePath = { DP_ACPI, DP_PCI( 0x1F,0x00 ),DP_LPC( 0x0303,1 ), DP_END };
+//STATIC SERIAL_CONN_DEVICE_PATH mCom1DevicePath = { DP_ACPI, DP_PCI( 0x1F,0x00 ),DP_LPC( 0x0501,0 ), DP_END };
+//STATIC SERIAL_CONN_DEVICE_PATH mCom2DevicePath = { DP_ACPI, DP_PCI( 0x1F,0x00 ),DP_LPC( 0x0501,1 ), DP_END };
+//STATIC PARALLEL_CONN_DEVICE_PATH mLpt1DevicePath = { DP_ACPI, DP_PCI( 0x1F,0x00 ),DP_LPC( 0x0401,0 ), DP_END };
+//STATIC FLOOPY_CONN_DEVICE_PATH mFloopyADevicePath = { DP_ACPI, DP_PCI( 0x1F,0x00 ),DP_LPC( 0x0604,0 ), DP_END };
+//STATIC FLOOPY_CONN_DEVICE_PATH mFloopyBDevicePath = { DP_ACPI, DP_PCI( 0x1F,0x00 ),DP_LPC( 0x0604,1 ), DP_END };
+//STATIC USB_PORT_DEVICE_PATH mUsb0DevicePath = { DP_ACPI, DP_PCI( 0x1d,0x00 ), DP_END };
+//STATIC USB_PORT_DEVICE_PATH mUsb1DevicePath = { DP_ACPI, DP_PCI( 0x1d,0x01 ), DP_END };
+//STATIC USB_PORT_DEVICE_PATH mUsb2DevicePath = { DP_ACPI, DP_PCI( 0x1d,0x02 ), DP_END };
+//STATIC USB_PORT_DEVICE_PATH mUsb3DevicePath = { DP_ACPI, DP_PCI( 0x1d,0x03 ), DP_END };
+//STATIC IDE_DEVICE_PATH mIdeDevicePath = { DP_ACPI, DP_PCI( 0x1F,0x01 ), DP_END };
+//STATIC IDE_DEVICE_PATH mSata1DevicePath = { DP_ACPI, DP_PCI( 0x1F,0x02 ), DP_END };
+//STATIC GB_NIC_DEVICE_PATH mGbNicDevicePath = { DP_ACPI, DP_PCI( 0x03,0x00 ),DP_PCI( 0x1F,0x00 ),DP_PCI( 0x07,0x00 ), DP_END };
+EFI_DEVICE_PATH_PROTOCOL mEndDevicePath = DP_END;
+
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector1);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector2);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector3);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector4);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector5);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector6);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector7);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector8);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector9);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector10);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector11);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector12);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector13);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector14);
+
+
+EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR *mMiscConnectorArray[SMBIOS_PORT_CONNECTOR_MAX_NUM] =
+{
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector1),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector2),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector3),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector4),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector5),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector6),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector7),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector8),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector9),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector10),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector11),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector12),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector13),
+ MISC_SMBIOS_DATA_TABLE_POINTER(MiscPortConnector14),
+};
+
+BOOLEAN PcdMiscPortIsInit = FALSE;
+SMBIOS_PORT_CONNECTOR_DESIGNATOR_COFNIG SMBIOSPortConnector = {0};
+
+
+/**
+ Get Misc Port Configuration information from PCD
+ @param SMBIOSPortConnector Pointer to SMBIOSPortConnector table.
+
+**/
+
+VOID
+GetMiscPortConfigFromPcd ()
+{
+ //
+ // Type 8
+ //
+ SMBIOSPortConnector.SMBIOSConnectorNumber = PcdGet8 (PcdSMBIOSConnectorNumber);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort1InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[0].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort1ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[0].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[0].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort1InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[0].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort1ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[0].PortType = PcdGet8 (PcdSMBIOSPort1Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort2InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[1].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort2ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[1].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[1].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort2InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[1].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort2ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[1].PortType = PcdGet8 (PcdSMBIOSPort2Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort3InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[2].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort3ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[2].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[2].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort3InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[2].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort3ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[2].PortType = PcdGet8 (PcdSMBIOSPort3Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort4InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[3].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort4ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[3].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[3].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort4InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[3].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort4ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[3].PortType = PcdGet8 (PcdSMBIOSPort4Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort5InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[4].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort5ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[4].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[4].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort5InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[4].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort5ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[4].PortType = PcdGet8 (PcdSMBIOSPort5Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort6InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[5].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort6ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[5].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[5].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort6InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[5].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort6ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[5].PortType = PcdGet8 (PcdSMBIOSPort6Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort7InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[6].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort7ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[6].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[6].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort7InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[6].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort7ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[6].PortType = PcdGet8 (PcdSMBIOSPort7Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort8InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[7].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort8ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[7].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[7].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort8InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[7].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort8ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[7].PortType = PcdGet8 (PcdSMBIOSPort8Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort9InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[8].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort9ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[8].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[8].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort9InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[8].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort9ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[8].PortType = PcdGet8 (PcdSMBIOSPort9Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort10InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[9].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort10ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[9].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[9].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort10InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[9].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort10ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[9].PortType = PcdGet8 (PcdSMBIOSPort10Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort11InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[10].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort11ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[10].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[10].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort11InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[10].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort11ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[10].PortType = PcdGet8 (PcdSMBIOSPort11Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort12InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[11].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort12ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[11].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[11].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort12InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[11].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort12ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[11].PortType = PcdGet8 (PcdSMBIOSPort12Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort13InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[12].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort13ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[12].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[12].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort13InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[12].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort13ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[12].PortType = PcdGet8 (PcdSMBIOSPort13Type);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort14InternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[13].PortInternalConnectorDesignator);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSPort14ExternalConnectorDesignator), SMBIOSPortConnector.SMBIOSPortConnector[13].PortExternalConnectorDesignator);
+ SMBIOSPortConnector.SMBIOSPortConnector[13].PortInternalConnectorType = PcdGet8 (PcdSMBIOSPort14InternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[13].PortExternalConnectorType = PcdGet8 (PcdSMBIOSPort14ExternalConnectorType);
+ SMBIOSPortConnector.SMBIOSPortConnector[13].PortType = PcdGet8 (PcdSMBIOSPort14Type);
+}
+/**
+ This function makes boot time changes to the contents of the
+ MiscPortConnectorInformation (Type 8).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscPortInternalConnectorDesignator)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN InternalRefStrLen;
+ UINTN ExternalRefStrLen;
+ EFI_STRING InternalRef;
+ EFI_STRING ExternalRef;
+ STRING_REF TokenForInternal;
+ STRING_REF TokenForExternal;
+ STRING_REF TokenToUpdate;
+ UINT8 InternalType;
+ UINT8 ExternalType;
+ UINT8 PortType;
+ EFI_STATUS Status;
+ SMBIOS_TABLE_TYPE8 *SmbiosRecord;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR *ForType8InputData;
+ UINT8 Index;
+
+ ForType8InputData = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR *)RecordData;
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TokenForInternal = 0;
+ TokenForExternal = 0;
+ InternalType = 0;
+ ExternalType = 0;
+ PortType = 0;
+
+ if (!PcdMiscPortIsInit) {
+ GetMiscPortConfigFromPcd ();
+ PcdMiscPortIsInit = TRUE;
+ }
+
+ for (Index = 0; Index < SMBIOS_PORT_CONNECTOR_MAX_NUM; Index++) {
+ if (ForType8InputData->PortInternalConnectorDesignator == (mMiscConnectorArray[Index])->PortInternalConnectorDesignator) {
+ //DEBUG ((EFI_D_ERROR, "Found Port Connector Data %d : ", Index));
+ break;
+ }
+ }
+ if (Index >= SMBIOSPortConnector.SMBIOSConnectorNumber) {
+ return EFI_SUCCESS;
+ }
+
+ if (Index >= SMBIOS_PORT_CONNECTOR_MAX_NUM) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InternalRef = SMBIOSPortConnector.SMBIOSPortConnector[Index].PortInternalConnectorDesignator;
+ if (StrLen (InternalRef) > 0) {
+ TokenToUpdate = STRING_TOKEN ((mMiscConnectorArray[Index])->PortInternalConnectorDesignator);
+ HiiSetString (mHiiHandle, TokenToUpdate, InternalRef, NULL);
+ }
+ ExternalRef = SMBIOSPortConnector.SMBIOSPortConnector[Index].PortExternalConnectorDesignator;
+ if (StrLen (ExternalRef) > 0) {
+ TokenToUpdate = STRING_TOKEN ((mMiscConnectorArray[Index])->PortExternalConnectorDesignator);
+ HiiSetString (mHiiHandle, TokenToUpdate, ExternalRef, NULL);
+ }
+ TokenForInternal = STRING_TOKEN ((mMiscConnectorArray[Index])->PortInternalConnectorDesignator);
+ TokenForExternal = STRING_TOKEN ((mMiscConnectorArray[Index])->PortExternalConnectorDesignator);
+ InternalType = SMBIOSPortConnector.SMBIOSPortConnector[Index].PortInternalConnectorType;
+ ExternalType = SMBIOSPortConnector.SMBIOSPortConnector[Index].PortExternalConnectorType;
+ PortType = SMBIOSPortConnector.SMBIOSPortConnector[Index].PortType;
+
+ InternalRef = HiiGetPackageString(&gEfiCallerIdGuid, TokenForInternal, NULL);
+ InternalRefStrLen = StrLen(InternalRef);
+ if (InternalRefStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ExternalRef = HiiGetPackageString(&gEfiCallerIdGuid, TokenForExternal, NULL);
+ ExternalRefStrLen = StrLen(ExternalRef);
+ if (ExternalRefStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE8) + InternalRefStrLen + 1 + ExternalRefStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE8) + InternalRefStrLen + 1 + ExternalRefStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE8);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ SmbiosRecord->InternalReferenceDesignator = 1;
+ SmbiosRecord->InternalConnectorType = InternalType;
+ SmbiosRecord->ExternalReferenceDesignator = 2;
+ SmbiosRecord->ExternalConnectorType = ExternalType;
+ SmbiosRecord->PortType = PortType;
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(InternalRef, OptionalStrStart);
+ UnicodeStrToAsciiStr(ExternalRef, OptionalStrStart + InternalRefStrLen + 1);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturer.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturer.uni
new file mode 100644
index 0000000..0848768
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturer.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturerData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturerData.c
new file mode 100644
index 0000000..69c1d33
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturerData.c
@@ -0,0 +1,63 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscSystemManufacturerData.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data using smbios protocol.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) System Manufacturer data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_MANUFACTURER, MiscSystemManufacturer) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_MANUFACTURER), // SystemManufactrurer
+ STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), // SystemProductName
+ STRING_TOKEN(STR_MISC_SYSTEM_VERSION), // SystemVersion
+ STRING_TOKEN(STR_MISC_SYSTEM_SERIAL_NUMBER), // SystemSerialNumber
+ { // SystemUuid
+ 0x13ffef23, 0x8654, 0x46da, 0xa4, 0x7, 0x39, 0xc9, 0x12, 0x2, 0xd3, 0x56
+ },
+ EfiSystemWakeupTypePowerSwitch, // SystemWakeupType
+ STRING_TOKEN(STR_MISC_SYSTEM_SKU_NUMBER), // SystemSKUNumber
+ STRING_TOKEN(STR_MISC_SYSTEM_FAMILY), // SystemFamily
+};
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturerFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturerFunction.c
new file mode 100644
index 0000000..e5d2003
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemManufacturerFunction.c
@@ -0,0 +1,229 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscSystemManufacturerFunction.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to smbios.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscSystemManufacturer (Type 1).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscSystemManufacturer)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN ManuStrLen;
+ UINTN VerStrLen;
+ UINTN PdNameStrLen;
+ UINTN SerialNumStrLen;
+ UINTN SKUNumStrLen;
+ UINTN FamilyStrLen;
+ EFI_STATUS Status;
+ CHAR16 Manufacturer[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 ProductName[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 Version[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 SerialNumber[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 SKUNumber[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 Family[SMBIOS_STRING_MAX_LENGTH];
+ EFI_STRING ManufacturerPtr;
+ EFI_STRING ProductNamePtr;
+ EFI_STRING VersionPtr;
+ EFI_STRING SerialNumberPtr;
+ EFI_STRING SKUNumberPtr;
+ EFI_STRING FamilyPtr;
+ STRING_REF TokenToGet;
+ STRING_REF TokenToUpdate;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE1 *SmbiosRecord;
+ EFI_MISC_SYSTEM_MANUFACTURER *ForType1InputData;
+
+ ForType1InputData = (EFI_MISC_SYSTEM_MANUFACTURER *)RecordData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Update strings from PCD
+ //
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemManufacturer), Manufacturer);
+ if (StrLen (Manufacturer) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER);
+ HiiSetString (mHiiHandle, TokenToUpdate, Manufacturer, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER);
+ ManufacturerPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ManuStrLen = StrLen(ManufacturerPtr);
+ if (ManuStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemProductName), ProductName);
+ if (StrLen (ProductName) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME);
+ HiiSetString (mHiiHandle, TokenToUpdate, ProductName, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME);
+ ProductNamePtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ PdNameStrLen = StrLen(ProductNamePtr);
+ if (PdNameStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemVersion), Version);
+ if (StrLen (Version) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_VERSION);
+ VersionPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VerStrLen = StrLen(VersionPtr);
+ if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSerialNumber), SerialNumber);
+ if (StrLen (SerialNumber) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_SERIAL_NUMBER);
+ HiiSetString (mHiiHandle, TokenToUpdate, SerialNumber, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SERIAL_NUMBER);
+ SerialNumberPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SerialNumStrLen = StrLen(SerialNumberPtr);
+ if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSKUNumber), SKUNumber);
+ if (StrLen (SKUNumber) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_SKU_NUMBER);
+ HiiSetString (mHiiHandle, TokenToUpdate, SKUNumber, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SKU_NUMBER);
+ SKUNumberPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SKUNumStrLen = StrLen(SKUNumberPtr);
+ if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemFamily), Family);
+ if (StrLen (Family) > 0) {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_FAMILY);
+ HiiSetString (mHiiHandle, TokenToUpdate, Family, NULL);
+ }
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_FAMILY);
+ FamilyPtr = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ FamilyStrLen = StrLen(FamilyPtr);
+ if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE1) + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SKUNumStrLen + 1 + FamilyStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE1) + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SKUNumStrLen + 1 + FamilyStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_INFORMATION;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE1);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+ //
+ // Manu will be the 1st optional string following the formatted structure.
+ //
+ SmbiosRecord->Manufacturer = 1;
+ //
+ // ProductName will be the 2nd optional string following the formatted structure.
+ //
+ SmbiosRecord->ProductName = 2;
+ //
+ // Version will be the 3rd optional string following the formatted structure.
+ //
+ SmbiosRecord->Version = 3;
+ //
+ // Serial number will be the 4th optional string following the formatted structure.
+ //
+ SmbiosRecord->SerialNumber = 4;
+ //
+ // SKU number will be the 5th optional string following the formatted structure.
+ //
+ SmbiosRecord->SKUNumber = 5;
+ //
+ // Family will be the 6th optional string following the formatted structure.
+ //
+ SmbiosRecord->Family = 6;
+ CopyMem ((UINT8 *) (&SmbiosRecord->Uuid), (UINT8 *)PcdGetPtr(PcdSMBIOSSystemUuid),16);
+ SmbiosRecord->WakeUpType = (UINT8)ForType1InputData->SystemWakeupType;
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(ManufacturerPtr, OptionalStrStart);
+ UnicodeStrToAsciiStr(ProductNamePtr, OptionalStrStart + ManuStrLen + 1);
+ UnicodeStrToAsciiStr(VersionPtr, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1);
+ UnicodeStrToAsciiStr(SerialNumberPtr, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1);
+ UnicodeStrToAsciiStr(SKUNumberPtr, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen+ 1);
+ UnicodeStrToAsciiStr(FamilyPtr, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SKUNumStrLen+ 1);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionString.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionString.uni
new file mode 100644
index 0000000..4a59dfb
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionString.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionStringData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionStringData.c
new file mode 100644
index 0000000..7945cc7
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionStringData.c
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscSystemOptionStringData.c
+
+Abstract:
+
+ This driver parses the mSmbiosMiscDataTable structure and reports
+ any generated data to smbios.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_OPTION_STRING, SystemOptionString) = {
+ STRING_TOKEN (STR_MISC_SYSTEM_OPTION_STRING)
+};
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionStringFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionStringFunction.c
new file mode 100755
index 0000000..9b7a379
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemOptionStringFunction.c
@@ -0,0 +1,115 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscSystemOptionStringFunction.c
+
+Abstract:
+
+ BIOS system option string boot time changes.
+ SMBIOS type 12.
+
+--*/
+
+
+#include "CommonHeader.h"
+#include "SmbiosMisc.h"
+
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscSystemOptionString (Type 12).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(SystemOptionString)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN OptStrLen;
+ EFI_STRING OptionString;
+ EFI_STATUS Status;
+ STRING_REF TokenToGet;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE12 *SmbiosRecord;
+ EFI_MISC_SYSTEM_OPTION_STRING *ForType12InputData;
+
+ ForType12InputData = (EFI_MISC_SYSTEM_OPTION_STRING *)RecordData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_OPTION_STRING);
+ OptionString = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ OptStrLen = StrLen(OptionString);
+ if (OptStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE12) + OptStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE12) + OptStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE12);
+ //
+ // Make handle chosen by smbios protocol.add automatically.
+ //
+ SmbiosRecord->Hdr.Handle = 0;
+
+ SmbiosRecord->StringCount = 1;
+ OptionalStrStart = (CHAR8*) (SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(OptionString, OptionalStrStart);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignation.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignation.uni
new file mode 100644
index 0000000..e8a75bb
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignation.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignationData.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignationData.c
new file mode 100644
index 0000000..c27feb2
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignationData.c
@@ -0,0 +1,388 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscSystemSlotDesignationData.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to the DataHub.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot1) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT1), // SlotDesignation
+ EfiSlotTypePci, // SlotType
+ EfiSlotDataBusWidth32Bit, // SlotDataBusWidth
+ EfiSlotUsageAvailable, // SlotUsage
+ EfiSlotLengthLong , // SlotLength
+ 1, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 0, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot2) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT2), // SlotDesignation
+ EfiSlotTypePciExpress, // SlotType
+ EfiSlotDataBusWidth32Bit, // SlotDataBusWidth
+ EfiSlotUsageAvailable, // SlotUsage
+ EfiSlotLengthLong , // SlotLength
+ 1, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot3) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT3), // SlotDesignation
+ EfiSlotTypePciExpress, // SlotType
+ EfiSlotDataBusWidth32Bit, // SlotDataBusWidth
+ EfiSlotUsageAvailable, // SlotUsage
+ EfiSlotLengthLong , // SlotLength
+ 2, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot4) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT4), // SlotDesignation
+ EfiSlotTypePciExpress, // SlotType
+ EfiSlotDataBusWidth32Bit, // SlotDataBusWidth
+ EfiSlotUsageAvailable, // SlotUsage
+ EfiSlotLengthLong , // SlotLength
+ 2, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot5) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT5), // SlotDesignation
+ EfiSlotTypePciExpress, // SlotType
+ EfiSlotDataBusWidth32Bit, // SlotDataBusWidth
+ EfiSlotUsageAvailable, // SlotUsage
+ EfiSlotLengthLong , // SlotLength
+ 3, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot6) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT6), // SlotDesignation
+ EfiSlotTypePciExpress, // SlotType
+ EfiSlotDataBusWidth32Bit, // SlotDataBusWidth
+ EfiSlotUsageAvailable, // SlotUsage
+ EfiSlotLengthLong , // SlotLength
+ 3, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot7) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT7), // SlotDesignation
+ EfiSlotTypePciExpress, // SlotType
+ EfiSlotDataBusWidth32Bit, // SlotDataBusWidth
+ EfiSlotUsageAvailable, // SlotUsage
+ EfiSlotLengthLong , // SlotLength
+ 3, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot8) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT8), // SlotDesignation
+ EfiSlotTypePciExpress, // SlotType
+ EfiSlotDataBusWidth32Bit, // SlotDataBusWidth
+ EfiSlotUsageAvailable, // SlotUsage
+ EfiSlotLengthLong , // SlotLength
+ 3, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot9) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT9), // SlotDesignation
+ EfiSlotTypeUnknown, // SlotType
+ EfiSlotDataBusWidthUnknown, // SlotDataBusWidth
+ EfiSlotUsageUnknown, // SlotUsage
+ EfiSlotLengthUnknown , // SlotLength
+ 0, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot10) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT10), // SlotDesignation
+ EfiSlotTypeUnknown, // SlotType
+ EfiSlotDataBusWidthUnknown, // SlotDataBusWidth
+ EfiSlotUsageUnknown, // SlotUsage
+ EfiSlotLengthUnknown , // SlotLength
+ 0, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot11) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT11), // SlotDesignation
+ EfiSlotTypeUnknown, // SlotType
+ EfiSlotDataBusWidthUnknown, // SlotDataBusWidth
+ EfiSlotUsageUnknown, // SlotUsage
+ EfiSlotLengthUnknown , // SlotLength
+ 0, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot12) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT12), // SlotDesignation
+ EfiSlotTypeUnknown, // SlotType
+ EfiSlotDataBusWidthUnknown, // SlotDataBusWidth
+ EfiSlotUsageUnknown, // SlotUsage
+ EfiSlotLengthUnknown , // SlotLength
+ 0, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot13) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT13), // SlotDesignation
+ EfiSlotTypeUnknown, // SlotType
+ EfiSlotDataBusWidthUnknown, // SlotDataBusWidth
+ EfiSlotUsageUnknown, // SlotUsage
+ EfiSlotLengthUnknown , // SlotLength
+ 0, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot14) = {
+ STRING_TOKEN(STR_MISC_SYSTEM_SLOT14), // SlotDesignation
+ EfiSlotTypeUnknown, // SlotType
+ EfiSlotDataBusWidthUnknown, // SlotDataBusWidth
+ EfiSlotUsageUnknown, // SlotUsage
+ EfiSlotLengthUnknown , // SlotLength
+ 0, // SlotId
+ { // SlotCharacteristics
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 1, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ 1, // PmeSignalSupported :1;
+ 1, // HotPlugDevicesSupported :1;
+ 1, // SmbusSignalSupported :1;
+ 0 // Reserved :21;
+ },
+ 0 // SlotDevicePath
+};
+
+
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignationFunction.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignationFunction.c
new file mode 100644
index 0000000..5a8e5cd
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotDesignationFunction.c
@@ -0,0 +1,314 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MiscSystemSlotDesignatorFunction.c
+
+Abstract:
+
+ BIOS system slot designator information boot time changes.
+ SMBIOS type 9.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+//
+//
+//
+
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot1);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot2);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot3);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot4);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot5);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot6);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot7);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot8);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot9);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot10);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot11);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot12);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot13);
+MISC_SMBIOS_DATA_TABLE_EXTERNS (EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot14);
+
+EFI_MISC_SYSTEM_SLOT_DESIGNATION *mMiscSlotArray[SMBIOS_SYSTEM_SLOT_MAX_NUM] =
+{
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot1),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot2),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot3),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot4),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot5),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot6),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot7),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot8),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot9),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot10),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot11),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot12),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot13),
+ MISC_SMBIOS_DATA_TABLE_POINTER (MiscSystemSlot14),
+};
+
+BOOLEAN PcdMiscSlotIsInit = FALSE;
+SMBIOS_SLOT_COFNIG SMBIOSlotConfig = {0};
+
+/**
+ Get Misc Slot Configuration information from PCD
+ @param SMBIOSPortConnector Pointer to SMBIOSPortConnector table.
+
+**/
+
+VOID
+GetMiscSLotConfigFromPcd ()
+{
+ //
+ // Type 9
+ //
+ SMBIOSlotConfig.SMBIOSSystemSlotNumber = PcdGet8 (PcdSMBIOSSystemSlotNumber);
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot1Designation), SMBIOSlotConfig.SMBIOSSystemSlot[0].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[0].SlotType = PcdGet8(PcdSMBIOSSystemSlot1Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[0].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot1DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[0].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot1Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[0].SlotLength = PcdGet8(PcdSMBIOSSystemSlot1Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[0].SlotId = PcdGet16(PcdSMBIOSSystemSlot1Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[0].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot1Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot2Designation), SMBIOSlotConfig.SMBIOSSystemSlot[1].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[1].SlotType = PcdGet8(PcdSMBIOSSystemSlot2Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[1].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot2DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[1].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot2Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[1].SlotLength = PcdGet8(PcdSMBIOSSystemSlot2Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[1].SlotId = PcdGet16(PcdSMBIOSSystemSlot2Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[1].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot2Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot3Designation), SMBIOSlotConfig.SMBIOSSystemSlot[2].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[2].SlotType = PcdGet8(PcdSMBIOSSystemSlot3Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[2].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot3DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[2].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot3Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[2].SlotLength = PcdGet8(PcdSMBIOSSystemSlot3Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[2].SlotId = PcdGet16(PcdSMBIOSSystemSlot3Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[2].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot3Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot4Designation), SMBIOSlotConfig.SMBIOSSystemSlot[3].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[3].SlotType = PcdGet8(PcdSMBIOSSystemSlot4Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[3].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot4DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[3].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot4Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[3].SlotLength = PcdGet8(PcdSMBIOSSystemSlot4Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[3].SlotId = PcdGet16(PcdSMBIOSSystemSlot4Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[3].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot4Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot5Designation), SMBIOSlotConfig.SMBIOSSystemSlot[4].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[4].SlotType = PcdGet8(PcdSMBIOSSystemSlot5Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[4].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot5DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[4].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot5Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[4].SlotLength = PcdGet8(PcdSMBIOSSystemSlot5Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[4].SlotId = PcdGet16(PcdSMBIOSSystemSlot5Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[4].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot5Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot6Designation), SMBIOSlotConfig.SMBIOSSystemSlot[5].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[5].SlotType = PcdGet8(PcdSMBIOSSystemSlot6Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[5].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot6DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[5].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot6Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[5].SlotLength = PcdGet8(PcdSMBIOSSystemSlot6Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[5].SlotId = PcdGet16(PcdSMBIOSSystemSlot6Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[5].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot6Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot7Designation), SMBIOSlotConfig.SMBIOSSystemSlot[6].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[6].SlotType = PcdGet8(PcdSMBIOSSystemSlot7Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[6].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot7DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[6].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot7Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[6].SlotLength = PcdGet8(PcdSMBIOSSystemSlot7Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[6].SlotId = PcdGet16(PcdSMBIOSSystemSlot7Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[6].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot7Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot8Designation), SMBIOSlotConfig.SMBIOSSystemSlot[7].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[7].SlotType = PcdGet8(PcdSMBIOSSystemSlot8Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[7].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot8DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[7].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot8Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[7].SlotLength = PcdGet8(PcdSMBIOSSystemSlot8Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[7].SlotId = PcdGet16(PcdSMBIOSSystemSlot8Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[7].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot8Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot9Designation), SMBIOSlotConfig.SMBIOSSystemSlot[8].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[8].SlotType = PcdGet8(PcdSMBIOSSystemSlot9Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[8].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot9DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[8].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot9Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[8].SlotLength = PcdGet8(PcdSMBIOSSystemSlot9Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[8].SlotId = PcdGet16(PcdSMBIOSSystemSlot9Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[8].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot9Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot10Designation), SMBIOSlotConfig.SMBIOSSystemSlot[9].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[9].SlotType = PcdGet8(PcdSMBIOSSystemSlot10Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[9].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot10DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[9].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot10Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[9].SlotLength = PcdGet8(PcdSMBIOSSystemSlot10Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[9].SlotId = PcdGet16(PcdSMBIOSSystemSlot10Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[9].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot10Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot11Designation), SMBIOSlotConfig.SMBIOSSystemSlot[10].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[10].SlotType = PcdGet8(PcdSMBIOSSystemSlot11Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[10].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot11DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[10].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot11Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[10].SlotLength = PcdGet8(PcdSMBIOSSystemSlot11Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[10].SlotId = PcdGet16(PcdSMBIOSSystemSlot11Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[10].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot11Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot12Designation), SMBIOSlotConfig.SMBIOSSystemSlot[11].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[11].SlotType = PcdGet8(PcdSMBIOSSystemSlot12Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[11].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot12DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[11].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot12Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[11].SlotLength = PcdGet8(PcdSMBIOSSystemSlot12Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[11].SlotId = PcdGet16(PcdSMBIOSSystemSlot12Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[11].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot12Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot13Designation), SMBIOSlotConfig.SMBIOSSystemSlot[12].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[12].SlotType = PcdGet8(PcdSMBIOSSystemSlot13Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[12].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot13DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[12].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot13Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[12].SlotLength = PcdGet8(PcdSMBIOSSystemSlot13Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[12].SlotId = PcdGet16(PcdSMBIOSSystemSlot13Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[12].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot13Characteristics);
+
+ AsciiStrToUnicodeStr (PcdGetPtr(PcdSMBIOSSystemSlot14Designation), SMBIOSlotConfig.SMBIOSSystemSlot[13].SlotDesignation);
+ SMBIOSlotConfig.SMBIOSSystemSlot[13].SlotType = PcdGet8(PcdSMBIOSSystemSlot14Type);
+ SMBIOSlotConfig.SMBIOSSystemSlot[13].SlotDataBusWidth = PcdGet8(PcdSMBIOSSystemSlot14DataBusWidth);
+ SMBIOSlotConfig.SMBIOSSystemSlot[13].SlotUsage = PcdGet8(PcdSMBIOSSystemSlot14Usage);
+ SMBIOSlotConfig.SMBIOSSystemSlot[13].SlotLength = PcdGet8(PcdSMBIOSSystemSlot14Length);
+ SMBIOSlotConfig.SMBIOSSystemSlot[13].SlotId = PcdGet16(PcdSMBIOSSystemSlot14Id);
+ SMBIOSlotConfig.SMBIOSSystemSlot[13].SlotCharacteristics = PcdGet32(PcdSMBIOSSystemSlot14Characteristics);
+}
+/**
+ This function makes boot time changes to the contents of the
+ MiscSystemSlotDesignator structure (Type 9).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscSystemSlotDesignator)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN SlotDesignationStrLen;
+ EFI_STATUS Status;
+ EFI_STRING SlotDesignation;
+ STRING_REF TokenToUpdate;
+ STRING_REF TokenToGet;
+ SMBIOS_TABLE_TYPE9 *SmbiosRecord;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_MISC_SYSTEM_SLOT_DESIGNATION* ForType9InputData;
+ UINT8 Index;
+
+ ForType9InputData = (EFI_MISC_SYSTEM_SLOT_DESIGNATION *)RecordData;
+
+ TokenToGet = 0;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!PcdMiscSlotIsInit) {
+ GetMiscSLotConfigFromPcd ();
+ PcdMiscSlotIsInit = TRUE;
+ }
+
+ for (Index = 0; Index < SMBIOS_SYSTEM_SLOT_MAX_NUM; Index++) {
+ if (ForType9InputData->SlotDesignation == (mMiscSlotArray[Index])->SlotDesignation) {
+ //DEBUG ((EFI_D_ERROR, "Found slot Data %d : ", Index));
+ break;
+ }
+ }
+ if (Index >= SMBIOSlotConfig.SMBIOSSystemSlotNumber) {
+ return EFI_SUCCESS;
+ }
+
+ if (Index >= SMBIOS_SYSTEM_SLOT_MAX_NUM) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SlotDesignation = SMBIOSlotConfig.SMBIOSSystemSlot[Index].SlotDesignation;
+ TokenToGet = STRING_TOKEN ((mMiscSlotArray[Index])->SlotDesignation);
+
+ if (StrLen (SlotDesignation) > 0) {
+ TokenToUpdate = STRING_TOKEN ((mMiscSlotArray[Index])->SlotDesignation);
+ HiiSetString (mHiiHandle, TokenToUpdate, SlotDesignation, NULL);
+ }
+
+ SlotDesignation = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SlotDesignationStrLen = StrLen(SlotDesignation);
+ if (SlotDesignationStrLen > SMBIOS_STRING_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE9) + SlotDesignationStrLen + 1 + 1);
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE9) +SlotDesignationStrLen + 1 + 1);
+
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_SLOTS;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE9);
+ SmbiosRecord->Hdr.Handle = 0;
+ SmbiosRecord->SlotDesignation = 1;
+ SmbiosRecord->SlotType = SMBIOSlotConfig.SMBIOSSystemSlot[Index].SlotType;
+ SmbiosRecord->SlotDataBusWidth = SMBIOSlotConfig.SMBIOSSystemSlot[Index].SlotDataBusWidth;
+ SmbiosRecord->CurrentUsage = SMBIOSlotConfig.SMBIOSSystemSlot[Index].SlotUsage;
+ SmbiosRecord->SlotLength = SMBIOSlotConfig.SMBIOSSystemSlot[Index].SlotLength;
+ SmbiosRecord->SlotID = SMBIOSlotConfig.SMBIOSSystemSlot[Index].SlotId;
+ *(UINT16 *)&SmbiosRecord->SlotCharacteristics1 = (UINT16)(SMBIOSlotConfig.SMBIOSSystemSlot[Index].SlotCharacteristics);
+
+ //
+ // Slot Characteristics
+ //
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(SlotDesignation, OptionalStrStart);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios-> Add(
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
+ );
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotOnboardDevices.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotOnboardDevices.uni
new file mode 100644
index 0000000..f1ddda9
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/MiscSystemSlotOnboardDevices.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMisc.h b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMisc.h
new file mode 100644
index 0000000..4763cc4
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMisc.h
@@ -0,0 +1,169 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmbiosMisc.h
+
+Abstract:
+
+ Header file for the SmbiosMisc Driver.
+
+--*/
+
+#ifndef _SMBIOS_MISC_H
+#define _SMBIOS_MISC_H
+
+#include "MiscDevicePath.h"
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/PlatformType.h>
+#include <Library/PrintLib.h>
+
+///
+/// Reference SMBIOS 2.6, chapter 3.1.3.
+/// Each text string is limited to 64 significant characters due to system MIF limitations.
+///
+#define SMBIOS_STRING_MAX_LENGTH 64
+#define SMBIOS_PORT_CONNECTOR_MAX_NUM 14
+
+typedef struct {
+ CHAR16 PortInternalConnectorDesignator[SMBIOS_STRING_MAX_LENGTH];
+ CHAR16 PortExternalConnectorDesignator[SMBIOS_STRING_MAX_LENGTH];
+ UINT8 PortInternalConnectorType;
+ UINT8 PortExternalConnectorType;
+ UINT8 PortType;
+} SMBIOS_PORT_CONNECTOR_DESIGNATOR;
+
+typedef struct {
+ UINT8 SMBIOSConnectorNumber;
+ SMBIOS_PORT_CONNECTOR_DESIGNATOR SMBIOSPortConnector[SMBIOS_PORT_CONNECTOR_MAX_NUM];
+} SMBIOS_PORT_CONNECTOR_DESIGNATOR_COFNIG;
+
+#define SMBIOS_SYSTEM_SLOT_MAX_NUM 14
+
+typedef struct {
+ CHAR16 SlotDesignation[SMBIOS_STRING_MAX_LENGTH];
+ UINT8 SlotType;
+ UINT8 SlotDataBusWidth;
+ UINT8 SlotUsage;
+ UINT8 SlotLength;
+ UINT16 SlotId;
+ UINT32 SlotCharacteristics;
+} SMBIOS_SLOT_DESIGNATION;
+
+typedef struct {
+ UINT8 SMBIOSSystemSlotNumber;
+ SMBIOS_SLOT_DESIGNATION SMBIOSSystemSlot[SMBIOS_SYSTEM_SLOT_MAX_NUM];
+} SMBIOS_SLOT_COFNIG;
+
+//
+// Data table entry update function.
+//
+typedef EFI_STATUS (EFIAPI EFI_MISC_SMBIOS_DATA_FUNCTION) (
+ IN VOID *RecordData,
+ IN EFI_SMBIOS_PROTOCOL *Smbios
+ );
+
+
+//
+// Data table entry definition.
+//
+typedef struct {
+ //
+ // intermediat input data for SMBIOS record
+ //
+ VOID *RecordData;
+ EFI_MISC_SMBIOS_DATA_FUNCTION *Function;
+} EFI_MISC_SMBIOS_DATA_TABLE;
+
+//
+// Data Table extern definitions.
+//
+#define MISC_SMBIOS_DATA_TABLE_POINTER(NAME1) \
+ & NAME1 ## Data
+
+//
+// Data Table extern definitions.
+//
+#define MISC_SMBIOS_DATA_TABLE_EXTERNS(NAME1, NAME2) \
+extern NAME1 NAME2 ## Data
+
+//
+// Data and function Table extern definitions.
+//
+#define MISC_SMBIOS_TABLE_EXTERNS(NAME1, NAME2, NAME3) \
+extern NAME1 NAME2 ## Data; \
+extern EFI_MISC_SMBIOS_DATA_FUNCTION NAME3 ## Function
+
+
+//
+// Data Table entries
+//
+
+#define MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(NAME1, NAME2) \
+{ \
+ & NAME1 ## Data, \
+ & NAME2 ## Function \
+}
+
+
+//
+// Global definition macros.
+//
+#define MISC_SMBIOS_TABLE_DATA(NAME1, NAME2) \
+ NAME1 NAME2 ## Data
+
+#define MISC_SMBIOS_TABLE_FUNCTION(NAME2) \
+ EFI_STATUS EFIAPI NAME2 ## Function( \
+ IN VOID *RecordData, \
+ IN EFI_SMBIOS_PROTOCOL *Smbios \
+ )
+
+
+// Data Table Array
+//
+extern EFI_MISC_SMBIOS_DATA_TABLE mSmbiosMiscDataTable[];
+
+//
+// Data Table Array Entries
+//
+extern UINTN mSmbiosMiscDataTableEntries;
+extern EFI_HII_HANDLE mHiiHandle;
+//
+// Prototypes
+//
+EFI_STATUS
+PiSmbiosMiscEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDataTable.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDataTable.c
new file mode 100755
index 0000000..b86fab7
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDataTable.c
@@ -0,0 +1,140 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmbiosMiscDataTable.c
+
+Abstract:
+
+ This driver parses the mSmbiosMiscDataTable structure and reports
+ any generated data using SMBIOS protocol.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+//
+// External definitions referenced by Data Table entries.
+//
+
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_BIOS_VENDOR, MiscBiosVendor, MiscBiosVendor);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_MANUFACTURER, MiscSystemManufacturer, MiscSystemManufacturer);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_MANUFACTURER, MiscBaseBoardManufacturer, MiscBaseBoardManufacturer);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_CHASSIS_MANUFACTURER, MiscChassisManufacturer, MiscChassisManufacturer);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_BOOT_INFORMATION_STATUS, MiscBootInfoStatus, MiscBootInfoStatus);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES, NumberOfInstallableLanguages, NumberOfInstallableLanguages);
+MISC_SMBIOS_TABLE_EXTERNS (EFI_MISC_SYSTEM_OPTION_STRING, SystemOptionString, SystemOptionString);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_ONBOARD_DEVICE, MiscOnboardDeviceVideo, MiscOnboardDevice);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_OEM_STRING,MiscOemString, MiscOemString);
+
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector1, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector2, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector3, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector4, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector5, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector6, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector7, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector8, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector9, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector10, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector11, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector12, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector13, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortConnector14, MiscPortInternalConnectorDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot1, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot2, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot3, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot4, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot5, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot6, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot7, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot8, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot9, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot10, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot11, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot12, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot13, MiscSystemSlotDesignator);
+MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlot14, MiscSystemSlotDesignator);
+
+
+//
+// Data Table
+//
+EFI_MISC_SMBIOS_DATA_TABLE mSmbiosMiscDataTable[] = {
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBiosVendor, MiscBiosVendor),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemManufacturer, MiscSystemManufacturer),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBaseBoardManufacturer, MiscBaseBoardManufacturer),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscChassisManufacturer, MiscChassisManufacturer),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector1, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector2, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector3, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector4, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector5, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector6, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector7, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector8, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector9, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector10, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector11, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector12, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector13, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortConnector14, MiscPortInternalConnectorDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot1, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot2, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot3, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot4, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot5, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot6, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot7, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot8, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot9, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot10, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot11, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot12, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot13, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlot14, MiscSystemSlotDesignator),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscOnboardDeviceVideo, MiscOnboardDevice),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscOemString, MiscOemString),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(SystemOptionString, SystemOptionString),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(NumberOfInstallableLanguages, NumberOfInstallableLanguages),
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBootInfoStatus, MiscBootInfoStatus)
+};
+
+//
+// Number of Data Table entries.
+//
+UINTN mSmbiosMiscDataTableEntries =
+ (sizeof mSmbiosMiscDataTable) / sizeof(EFI_MISC_SMBIOS_DATA_TABLE);
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDxe.inf b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDxe.inf
new file mode 100644
index 0000000..bb0dafa
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDxe.inf
@@ -0,0 +1,332 @@
+## @file
+# Component description file for Smbios Misc module.
+#
+# This driver parses the mSmbiosMiscDataTable structure
+# and reports any generated data using SMBIOS protocol.
+# SmBios To Misc.Subclass Map Table.
+# SMBIOS Type |SMBIOS Name |Misc Subclass Record |Misc Subclass Name
+# 0 | BIOS Information | 0x2 | BiosVendor
+# 3 | System/Chassis Enclosure | 0x5 | ChassisManufacturer
+# 8 | Port Connector Information | 0x6 | PortInternalConnectorDesignator
+# 9 | System Slot Information | 0x7 | SystemSlotDesignator
+# 10 | On Board Device Information | 0x8 | OnboardDevice
+# 12 | System Configuration Options| 0xA | SystemOptionString
+# 13 | BIOS Language Information | 0xB | NumberOfInstallableLanguages
+# 32 | Boot Information | 0x1A | BootInformationStatus
+# The uni files tagged with "ToolCode="DUMMY"" are included by SmbiosMiscStrings.uni file which is input
+# file for StrGather tool.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmbiosMisc
+ FILE_GUID = EF0C99B6-B1D3-4025-9405-BF6A560FE0E0
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SmbiosMiscEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ MiscOemStringFunction.c
+ MiscOemStringData.c
+ SmbiosMiscEntryPoint.c
+ SmbiosMiscDataTable.c
+ MiscSystemManufacturerData.c
+ MiscSystemManufacturerFunction.c
+ MiscBaseBoardManufacturerData.c
+ MiscBaseBoardManufacturerFunction.c
+ MiscOnboardDeviceFunction.c
+ MiscOnboardDeviceData.c
+ MiscSystemSlotDesignationFunction.c
+ MiscSystemSlotDesignationData.c
+ MiscNumberOfInstallableLanguagesFunction.c
+ MiscNumberOfInstallableLanguagesData.c
+ MiscChassisManufacturerFunction.c
+ MiscChassisManufacturerData.c
+ MiscBootInformationFunction.c
+ MiscBootInformationData.c
+ MiscBiosVendorFunction.c
+ MiscBiosVendorData.c
+ MiscSystemOptionStringFunction.c
+ MiscSystemOptionStringData.c
+ MiscPortInternalConnectorDesignatorFunction.c
+ MiscPortInternalConnectorDesignatorData.c
+ SmbiosMisc.h
+ MiscDevicePath.h
+ SmbiosMiscStrings.uni
+ CommonHeader.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ HiiLib
+ MemoryAllocationLib
+ DevicePathLib
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiPlatformTypeProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosVendor
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosReleaseDate
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosStartAddress
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosChar
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosCharEx1
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosCharEx2
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemManufacturer
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemProductName
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemVersion
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSerialNumber
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemUuid
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSKUNumber
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemFamily
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBoardManufacturer
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBoardProductName
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBoardVersion
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBoardSerialNumber
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisManufacturer
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisVersion
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisSerialNumber
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisAssetTag
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisBootupState
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisPowerSupplyState
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisSecurityState
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisOemDefined
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisHeight
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisNumberPowerCords
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisElementCount
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisElementRecordLength
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSConnectorNumber
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14InternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14ExternalConnectorDesignator
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort15InternalConnectorDesignator
+
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort15InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort15ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort15Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort16InternalConnectorDesignator
+
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort16InternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort16ExternalConnectorType
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort16Type
+
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlotNumber
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Characteristics
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Designation
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14DataBusWidth
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Usage
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Length
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Id
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Characteristics
+
+[Depex]
+ gEfiSmbiosProtocolGuid
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscEntryPoint.c b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
new file mode 100755
index 0000000..0157e87
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
@@ -0,0 +1,113 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmbiosMiscEntryPoint.c
+
+Abstract:
+
+ This driver parses the mSmbiosMiscDataTable structure and reports
+ any generated data using SMBIOS protocol.
+
+--*/
+
+
+#include "CommonHeader.h"
+
+#include "SmbiosMisc.h"
+
+
+extern UINT8 SmbiosMiscStrings[];
+EFI_HANDLE mImageHandle;
+
+EFI_HII_HANDLE mHiiHandle;
+
+
+
+/**
+ Standard EFI driver point. This driver parses the mSmbiosMiscDataTable
+ structure and reports any generated data using SMBIOS protocol.
+
+ @param ImageHandle Handle for the image of this driver
+ @param SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The data was successfully stored.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbiosMiscEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINTN Index;
+ EFI_STATUS EfiStatus;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+
+
+ mImageHandle = ImageHandle;
+
+ EfiStatus = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
+
+ if (EFI_ERROR(EfiStatus)) {
+ DEBUG((EFI_D_ERROR, "Could not locate SMBIOS protocol. %r\n", EfiStatus));
+ return EfiStatus;
+ }
+
+ mHiiHandle = HiiAddPackages (
+ &gEfiCallerIdGuid,
+ mImageHandle,
+ SmbiosMiscStrings,
+ NULL
+ );
+ ASSERT (mHiiHandle != NULL);
+
+ for (Index = 0; Index < mSmbiosMiscDataTableEntries; ++Index) {
+ //
+ // If the entry have a function pointer, just log the data.
+ //
+ if (mSmbiosMiscDataTable[Index].Function != NULL) {
+ EfiStatus = (*mSmbiosMiscDataTable[Index].Function)(
+ mSmbiosMiscDataTable[Index].RecordData,
+ Smbios
+ );
+
+ if (EFI_ERROR(EfiStatus)) {
+ DEBUG((EFI_D_ERROR, "Misc smbios store error. Index=%d, ReturnStatus=%r\n", Index, EfiStatus));
+ return EfiStatus;
+ }
+ }
+ }
+
+ return EfiStatus;
+}
diff --git a/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscStrings.uni b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscStrings.uni
new file mode 100644
index 0000000..4a70a63
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscStrings.uni
Binary files differ
diff --git a/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/AccessViolationHandler.c b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/AccessViolationHandler.c
new file mode 100644
index 0000000..cdc8279
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/AccessViolationHandler.c
@@ -0,0 +1,242 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ AccessViolationHandler.c
+
+Abstract:
+
+ SPI BIOS Flash access violation handler routines.
+
+--*/
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/BaseLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Protocol/SmmBase2.h>
+#include <Protocol/SmmVariable.h>
+#include <Guid/GlobalVariable.h>
+#include <QNCAccessLib.h>
+#include <Library/IntelQNCLib.h>
+#include "AccessViolationHandler.h"
+
+//
+// Variables private to this source module.
+//
+STATIC EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;
+STATIC EFI_HANDLE mSmiHandle;
+//
+// Routines private to this source module.
+//
+
+STATIC
+EFI_STATUS
+IncrementAccessViolationCount (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 AccessCount;
+ UINT32 Attr;
+ UINT32 DataSize;
+
+ if (mSmmVariable == NULL) {
+ return EFI_SUCCESS;
+ }
+ DataSize = sizeof (AccessCount);
+ Status = mSmmVariable->SmmGetVariable (
+ SPI_ACCESS_VIOLATION_COUNT_VAR_NAME,
+ &gEfiGlobalVariableGuid,
+ &Attr,
+ &DataSize,
+ (VOID *) &AccessCount
+ );
+
+ if (EFI_ERROR (Status)) {
+ AccessCount = 0;
+ Attr = SPI_ACCESS_VIOLATION_COUNT_VAR_ATTR;
+ DataSize = sizeof (AccessCount);
+ } else {
+ AccessCount++;
+ }
+
+ Status = mSmmVariable->SmmSetVariable (
+ SPI_ACCESS_VIOLATION_COUNT_VAR_NAME,
+ &gEfiGlobalVariableGuid,
+ Attr,
+ DataSize,
+ (VOID *) &AccessCount
+ );
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+VariableNotificationFunction (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, &mSmmVariable);
+ return EFI_SUCCESS;
+}
+
+//
+// Routines exported by this source module.
+//
+
+
+/**
+ SMI Handler to trap SPI Flash access violations.
+
+ @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister()
+ @param Context Points to an optional handler context which was specified when the
+ handler was registered..
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS Calculate the total size for all FV images stored in Capsule image.
+
+**/
+EFI_STATUS
+EFIAPI
+AccessViolationHandlerCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BcValue;
+
+ Status = EFI_WARN_INTERRUPT_SOURCE_PENDING;
+ BcValue = LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL);
+
+ //
+ // B_QNC_LPC_BIOS_CNTL_BLE and B_QNC_LPC_BIOS_CNTL_BIOSWE
+ // must be set to indicates condiitions met.
+ //
+ if ((BcValue & B_QNC_LPC_BIOS_CNTL_BLE) != 0) {
+ if ((BcValue & B_QNC_LPC_BIOS_CNTL_BIOSWE) != 0) {
+
+ IncrementAccessViolationCount ();
+
+ //
+ // Clear B_QNC_LPC_BIOS_CNTL_BIOSWE to trap
+ // next edge.
+ //
+ LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL) =
+ BcValue & (~B_QNC_LPC_BIOS_CNTL_BIOSWE);
+ Status = EFI_SUCCESS;
+ }
+ }
+ return Status;
+}
+
+/**
+ Installs SMI handler to trap Flash Access Violations.
+
+ @retval EFI_SUCCESS Function success.
+
+**/
+EFI_STATUS
+EFIAPI
+AccessViolationHandlerInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ VOID *RegistrationVar;
+ UINT32 Attr;
+ UINT32 DataSize;
+ UINT32 AccessCount;
+
+ //
+ // Register protocol notify for SMM variable services.
+ //
+
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, &mSmmVariable);
+ if (EFI_ERROR(Status)) {
+ mSmmVariable = NULL;
+ RegistrationVar = NULL;
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmVariableProtocolGuid,
+ VariableNotificationFunction,
+ &RegistrationVar
+ );
+ }
+
+ //
+ // Smm register SMI Access violation handler.
+ //
+
+ Status = gSmst->SmiHandlerRegister (AccessViolationHandlerCallback, NULL, &mSmiHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Check if there was a SPI Fash write on previous boot
+ //
+ Attr = SPI_ACCESS_VIOLATION_COUNT_VAR_ATTR;
+ DataSize = sizeof(UINT32);
+ Status = mSmmVariable->SmmGetVariable (
+ SPI_ACCESS_VIOLATION_COUNT_VAR_NAME,
+ &gEfiGlobalVariableGuid,
+ &Attr,
+ &DataSize,
+ (VOID *) &AccessCount
+ );
+ //
+ // Report error and clear count for previous boot, Initialize if not set
+ //
+ if ((EFI_ERROR(Status) || AccessCount != 0)) {
+ if(!EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "Access Violation Count: %x\n", AccessCount));
+ }
+ AccessCount = 0;
+ Status = mSmmVariable->SmmSetVariable (
+ SPI_ACCESS_VIOLATION_COUNT_VAR_NAME,
+ &gEfiGlobalVariableGuid,
+ Attr,
+ DataSize,
+ (VOID *) &AccessCount
+ );
+ }
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/AccessViolationHandler.h b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/AccessViolationHandler.h
new file mode 100644
index 0000000..dc91d6d
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/AccessViolationHandler.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ AccessViolationHandler.h
+
+Abstract:
+
+--*/
+
+#ifndef _ACCESS_VIOLATION_HANDLER_H_
+
+
+#define SPI_ACCESS_VIOLATION_COUNT_VAR_NAME L"PlatformFlashAccessViolationCount"
+#define SPI_ACCESS_VIOLATION_COUNT_VAR_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | \
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+ EFI_VARIABLE_NON_VOLATILE \
+ )
+
+EFI_STATUS
+EFIAPI
+AccessViolationHandlerInit (
+ VOID
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.c b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.c
new file mode 100755
index 0000000..ea22a68
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.c
@@ -0,0 +1,837 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SMIFlashDxe.c
+
+Abstract:
+
+ SMI driver to update BIOS capsule.
+
+--*/
+
+#include "SMIFlashDxe.h"
+
+EFI_STATUS ChallengeCapsule();
+EFI_STATUS CapsuleParse();
+EFI_STATUS EraseBlock();
+EFI_STATUS WriteBlock();
+
+#define MAX_BLOCK_NUMBER FixedPcdGet32(PcdMaxSizeNonPopulateCapsule) / FLASH_BLOCK_SIZE
+
+UINTN SmiFlashUpdateStateArray[SMI_FLASH_UPDATE_MAX_STATES] = {
+ (UINTN)&ChallengeCapsule,
+ (UINTN)&CapsuleParse,
+ (UINTN)&EraseBlock,
+ (UINTN)&WriteBlock,
+ (UINTN)-1,
+};
+
+SPI_IMAGE_PRESENT mSpiImageList[] = {
+ // DefaultBaseAddress MaxSize FixedAddress Updatable AnyBlockUpdate Present
+ {EDKII_BOOTROM_OVERRIDE_DEFAULT_BASE_ADDRESS, EDKII_BOOTROM_OVERRIDE_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_KEY_MODULE_DEFAULT_BASE_ADDRESS, EDKII_KEY_MODULE_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_SVN_DEFAULT_BASE_ADDRESS, EDKII_SVN_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_RECOVERY_IMAGE1_DEFAULT_BASE_ADDRESS, EDKII_RECOVERY_IMAGE1_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_OEM_AREA_DEFAULT_BASE_ADDRESS, EDKII_OEM_AREA_MAX_SIZE, TRUE, TRUE, TRUE, FALSE}
+ ,{EDKII_NVRAM_DEFAULT_BASE_ADDRESS, EDKII_NVRAM_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_PLATFORM_DATA_DEFAULT_BASE_ADDRESS, EDKII_PLATFORM_DATA_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_MFH_DEFAULT_BASE_ADDRESS, EDKII_MFH_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_RMU_DEFAULT_BASE_ADDRESS, EDKII_RMU_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_BOOT_STAGE1_IMAGE1_DEFAULT_BASE_ADDRESS, EDKII_BOOT_STAGE1_IMAGE1_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_BOOT_STAGE1_IMAGE2_DEFAULT_BASE_ADDRESS, EDKII_BOOT_STAGE1_IMAGE2_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_BOOT_STAGE2_COMPACT_DEFAULT_BASE_ADDRESS, EDKII_BOOT_STAGE2_COMPACT_MAX_SIZE, TRUE, TRUE, FALSE, FALSE}
+ ,{EDKII_OS_DEFAULT_BASE_ADDRESS, EDKII_OS_MAX_SIZE, TRUE, TRUE, TRUE, FALSE}
+};
+
+UINT8 mSpiImageListSize;
+
+//
+// Module Globals
+//
+EFI_SPI_PROTOCOL *mEfiSpiProtocol = NULL;
+EFI_SMM_CPU_PROTOCOL *mSmmCpu = NULL;
+SPI_INIT_INFO *mSpiCtrlerInfo = NULL;
+
+UPDATE_STATUS_PACKET mUpdateStatusPacket = {
+ 0x0,
+ (UINTN) -1,
+ EFI_NOT_READY
+};
+
+NEXT_STATE mNextState;
+UINTN mStateId;
+SMI_FLASH_STATE_MANAGER mActiveState;
+STATE_MACHINE_PRIVATE_DATA mStateMachinePrivateData[MAX_BLOCK_NUMBER];
+UINTN mCurrBlock = 0;
+BOOLEAN mLastBlockDone = FALSE;
+UINT8 *mCapsuleSmmBuffer = NULL;
+UINT32 mBufferOffset=0;
+UINT32 mSpiFlashBaseAddress = 0;
+
+/**
+ Calculate the total size for all images in Capsule.
+
+ @param CapsuleHeader Pointer to the capsule image.
+ @param CapsuleImageSize Pointer to the Capsule image size. On output, it stores the got Capsule image size.
+
+ @retval EFI_INVALID_PARAMETER The input parameter is NULL. Or Capsule image is not supported format.
+ @retval EFI_SUCCESS Calculate the total size for all images stored in Capsule image.
+
+**/
+EFI_STATUS
+FindTotalCapsuleImageSize (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ OUT UINT32 *CapsuleImageSize
+ )
+{
+ EFI_STATUS Status;
+ UPDATE_HINT *HintTable;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Check buffers are valid
+ //
+ if (CapsuleHeader == NULL || CapsuleImageSize == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto _Exit;
+ }
+
+ HintTable = (UPDATE_HINT*) ((UINT8*) CapsuleHeader + CapsuleHeader->HeaderSize);
+
+ //
+ // Add the size of each image in the capsule
+ //
+ *CapsuleImageSize = (sizeof(UPDATE_HINT) * MAX_IMAGES_PER_CAPSULE); // Hint table size
+ while(HintTable->Size != 0x00){
+ *CapsuleImageSize += HintTable->Size;
+ HintTable++;
+ }
+
+_Exit:
+ return Status;
+}
+
+/**
+ Check if we need to preserve any items in the Platform Data area
+
+ @param CapsulePlatformData Pointer to the capsule image Platform Data.
+
+ @retval EFI_SUCCESS Platform Data policy implemented successfully.
+
+**/
+EFI_STATUS
+CheckPlatformDataPolicy (
+ IN PDAT_AREA *CapsulePlatformData,
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_STATUS Status;
+ PDAT_ITEM *PDataFlashItem;
+ PDAT_ITEM *PDataCapsuleItem;
+ PDAT_LIB_FINDCONTEXT PDatCapsuleFindContext;
+ PDAT_LIB_FINDCONTEXT PDatFlashFindContext;
+ UINT32 CalcCrc;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Check if we should preserve the PlatformData MAC addresses
+ //
+ if (!(CapsuleHeader->Flags & PD_UPDATE_MAC)) {
+ //
+ // Find MAC1 in PlatformData in both SPI flash and capsule
+ // Copy MAC1 from the SPI flash PlatformData to the capsule PlatformData
+ //
+ PDataCapsuleItem = PDatLibFindFirstWithFilter ((PDAT_AREA *)CapsulePlatformData, PDAT_FIND_NETWORK_ITEMS, &PDatCapsuleFindContext, NULL);
+ PDataFlashItem = PDatLibFindFirstWithFilter (NULL, PDAT_FIND_NETWORK_ITEMS, &PDatFlashFindContext, NULL);
+ if ((PDataFlashItem != NULL) && (PDataCapsuleItem != NULL)) {
+ CopyMem (PDataCapsuleItem->Data, PDataFlashItem->Data, PDataFlashItem->Header.Length);
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Find MAC2 in PlatformData in both SPI flash and capsule
+ // Copy MAC2 from the SPI flash PlatformData to the capsule PlatformData
+ //
+ PDataCapsuleItem = PDatLibFindNextWithFilter(PDAT_FIND_NETWORK_ITEMS, &PDatCapsuleFindContext, NULL);
+ PDataFlashItem = PDatLibFindNextWithFilter(PDAT_FIND_NETWORK_ITEMS, &PDatFlashFindContext, NULL);
+ if ((PDataFlashItem != NULL) && (PDataCapsuleItem != NULL)) {
+ CopyMem (PDataCapsuleItem->Data, PDataFlashItem->Data, PDataFlashItem->Header.Length);
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Update the PlatformData CRC in the capsule
+ //
+ Status = PlatformCalculateCrc32 (
+ (UINT8 *) &CapsulePlatformData->Body[0],
+ (UINTN) CapsulePlatformData->Header.Length,
+ &CalcCrc
+ );
+ CapsulePlatformData->Header.Crc = CalcCrc;
+ }
+
+ return Status;
+}
+
+/**
+ Initialize State machine to store each block information.
+
+ @param StateElement Pointer to State machine element. On output, it will record each FV block.
+ @param CapsuleHeader Pointer to the capsule image.
+ @param HintTable Pointer to HintTable that stores each FV information.
+
+ @return the total number of the recorded FV block.
+
+**/
+UINT32
+InitialiseStateMachineData (
+ IN OUT STATE_MACHINE_PRIVATE_DATA **StateElement,
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,
+ IN UPDATE_HINT *HintTable
+ )
+{
+ UINT32 ImageSourceAddr;
+ UINT32 ImageDestinationAddr;
+ UINT32 NumberOfBlocks;
+
+ ASSERT(mEfiSpiProtocol != NULL);
+
+ ImageSourceAddr = (UINT32)((UINT8*) CapsuleHeader + HintTable->SourceOffset);
+ ImageDestinationAddr = HintTable->TargetAddr;
+ ASSERT ((ImageDestinationAddr & (FLASH_BLOCK_SIZE-1)) == 0); // Check that the destination SPI address is block aligned
+ NumberOfBlocks = 0;
+
+ while (ImageDestinationAddr <= ((HintTable->TargetAddr + HintTable->Size)-FLASH_BLOCK_SIZE) && (ImageDestinationAddr != 0)) {
+ ASSERT (ImageDestinationAddr >= mSpiFlashBaseAddress);
+
+ if (ImageDestinationAddr == EDKII_PLATFORM_DATA_DEFAULT_BASE_ADDRESS) {
+ CheckPlatformDataPolicy((PDAT_AREA *)ImageSourceAddr, CapsuleHeader);
+ }
+
+ ((STATE_MACHINE_PRIVATE_DATA*)*StateElement)->SourceAddr = ImageSourceAddr;
+ ((STATE_MACHINE_PRIVATE_DATA*)*StateElement)->TargetAddr = ImageDestinationAddr;
+ ((STATE_MACHINE_PRIVATE_DATA*)*StateElement)->BlockSize = FLASH_BLOCK_SIZE;
+ ((STATE_MACHINE_PRIVATE_DATA*)*StateElement)->IsValid = TRUE;
+ ((STATE_MACHINE_PRIVATE_DATA*)*StateElement)->UpdateStatus = FALSE;
+ ((STATE_MACHINE_PRIVATE_DATA*)*StateElement)->SmmSpiProtocol = mEfiSpiProtocol;
+
+ *StateElement = ( (STATE_MACHINE_PRIVATE_DATA*) *StateElement ) + 1;
+ ImageSourceAddr += FLASH_BLOCK_SIZE;
+ ImageDestinationAddr += FLASH_BLOCK_SIZE;
+ NumberOfBlocks++;
+ }
+
+ return NumberOfBlocks;
+}
+
+/**
+ Parse Capsule image, and record each block of the updated FV into the state machine structure.
+
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to store capsule image.
+ @retval EFI_SUCCESS Parse Capsule image successfully.
+
+**/
+EFI_STATUS
+CapsuleParse(
+ VOID
+ )
+{
+ UINT8 Index;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ UPDATE_HINT *HintTable;
+ STATE_MACHINE_PRIVATE_DATA *StateElement;
+
+ if (mCapsuleSmmBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CapsuleHeader = (EFI_CAPSULE_HEADER *) mCapsuleSmmBuffer;
+ HintTable = (UPDATE_HINT*)((UINT8*) CapsuleHeader + CapsuleHeader->HeaderSize);
+ StateElement = &mStateMachinePrivateData[0];
+
+ mUpdateStatusPacket.TotalBlocks = 0;
+
+ //
+ // Check for full SPI flash update first
+ // Also allow full update of 'BIOS_SECTION'
+ //
+ if ((HintTable->Size == (SIZE_4GB - mSpiFlashBaseAddress)) && (HintTable->TargetAddr == mSpiFlashBaseAddress)) {
+ mUpdateStatusPacket.TotalBlocks += InitialiseStateMachineData (&StateElement, CapsuleHeader, HintTable);
+ } else if ((HintTable->Size == EDKII_BIOS_SECTION_MAX_SIZE) && (HintTable->TargetAddr == EDKII_BIOS_SECTION_DEFAULT_BASE_ADDRESS)) {
+ mUpdateStatusPacket.TotalBlocks += InitialiseStateMachineData (&StateElement, CapsuleHeader, HintTable);
+ } else {
+ while(HintTable->Size != 0x00 && mUpdateStatusPacket.TotalBlocks < MAX_BLOCK_NUMBER) {
+ if (HintTable->TargetAddr < mSpiFlashBaseAddress ||
+ (UINT64)HintTable->TargetAddr + (UINT64)HintTable->Size > SIZE_4GB) {
+ //
+ // Only support to update Flash region (between mSpiFlashBaseAddress and SIZE_4GB).
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Only update SPI flash images that can be updated.
+ //
+ for (Index = 0; Index < mSpiImageListSize; Index++) {
+ if (mSpiImageList[Index].FixedAddress) {
+ if ((HintTable->TargetAddr >= mSpiImageList[Index].SpiImageDefaultBaseAddress) &&
+ (((UINT64)HintTable->TargetAddr + (UINT64)HintTable->Size) <= ((UINT64)mSpiImageList[Index].SpiImageDefaultBaseAddress + (UINT64)mSpiImageList[Index].SpiImageMaxSize)) &&
+ mSpiImageList[Index].Updatable) {
+
+ if (mSpiImageList[Index].AnyBlockUpdate) {
+ mUpdateStatusPacket.TotalBlocks += InitialiseStateMachineData (&StateElement, CapsuleHeader, HintTable);
+ } else if (HintTable->TargetAddr == mSpiImageList[Index].SpiImageDefaultBaseAddress) {
+ mUpdateStatusPacket.TotalBlocks += InitialiseStateMachineData (&StateElement, CapsuleHeader, HintTable);
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ } else {
+ //
+ // Validate this image using the MFH
+ //
+// if ((MfhValidateImageBaseAddress(HintTable->TargetAddr, (UINT32)((UINT8*) CapsuleHeader + HintTable->SourceOffset))) &&
+// (HintTable->Size <= mSpiImageList[Index].SpiImageMaxSize) && (mSpiImageList[Index].Updatable)) {
+// //
+// // If so, update SM flash data
+// //
+// mUpdateStatusPacket.TotalBlocks += InitialiseStateMachineData (&StateElement, CapsuleHeader, HintTable);
+// } else {
+// return EFI_INVALID_PARAMETER;
+// }
+ }
+ }
+ HintTable++;
+ }
+ }
+
+ //
+ // Block number can't exceed the reserved max block number.
+ //
+ ASSERT (mUpdateStatusPacket.TotalBlocks < MAX_BLOCK_NUMBER);
+
+ mCurrBlock = 0;
+ mUpdateStatusPacket.Status = EFI_SUCCESS;
+ return EFI_SUCCESS;
+}
+
+/**
+ Verify whether the capsule image is the supported and valid capsule image.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory to store Capsule image.
+ @retval EFI_INVALID_PARAMETER Capsule image format is unsupported.
+ @retval EFI_SUCCESS Get the updated Capsule images.
+
+**/
+EFI_STATUS
+ChallengeCapsule (
+ VOID
+ )
+{
+ INT8 *Buffer;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ EFI_STATUS Status;
+ UINT32 TotalCapsuleImageSize;
+
+ if (mCapsuleSmmBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get Capsule size
+ //
+ Buffer = mCapsuleSmmBuffer;
+ CapsuleHeader = (EFI_CAPSULE_HEADER *) Buffer;
+
+ //
+ // Check the format of capsule file
+ //
+ if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiQuarkCapsuleGuid)) {
+ //
+ // unsupported capsule image
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = FindTotalCapsuleImageSize (CapsuleHeader, &TotalCapsuleImageSize);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Capsule image size check.
+ //
+ if (CapsuleHeader->CapsuleImageSize != (CapsuleHeader->HeaderSize + TotalCapsuleImageSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Erase current block specified by the glboal mCurrBlock variable until all blocks are erased.
+
+ @retval EFI_SUCCESS Erase current block successfully.
+
+**/
+EFI_STATUS
+EraseBlock (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN WriteAddress;
+
+ if (!mStateMachinePrivateData[mCurrBlock].IsValid) {
+ mLastBlockDone = TRUE;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Erase Flash
+ //
+ WriteAddress = (UINTN)(mStateMachinePrivateData[mCurrBlock].TargetAddr - mSpiFlashBaseAddress);
+ Status = mStateMachinePrivateData[mCurrBlock].SmmSpiProtocol->Execute (
+ mStateMachinePrivateData[mCurrBlock].SmmSpiProtocol,
+ mSpiCtrlerInfo->EraseOpcodeIndex, // OpcodeIndex
+ 0, // PrefixOpcodeIndex
+ FALSE, // DataCycle
+ TRUE, // Atomic
+ FALSE, // ShiftOut
+ WriteAddress, // Address
+ 0, // Data Number
+ NULL,
+ EnumSpiRegionAll // SPI_REGION_TYPE
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SMIFlashDxe: Erase Flash Error WriteAddress=0x%08x TargetAddr=0x%08x, mSpiFlashBaseAddress=0x%08x\n",
+ (UINTN) WriteAddress,
+ (UINTN) mStateMachinePrivateData[mCurrBlock].TargetAddr,
+ (UINTN) mSpiFlashBaseAddress
+ ));
+ }
+ //
+ // Flash needs to be erased correctly.
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Flash write is always enabled. Todo fix. Need to disable flash write first after erase done.
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Write the update data into the current block specified by the glboal mCurrBlock variable.
+
+ @retval EFI_SUCCESS Write data into flash block correctly.
+**/
+EFI_STATUS
+WriteBlock (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN WriteAddress;
+
+ //
+ // Write Flash
+ //
+ if (!mStateMachinePrivateData[mCurrBlock].IsValid) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Write Flash
+ //
+ WriteAddress = (UINTN)(mStateMachinePrivateData[mCurrBlock].TargetAddr - mSpiFlashBaseAddress);
+ Status = mStateMachinePrivateData[mCurrBlock].SmmSpiProtocol->Execute (
+ mStateMachinePrivateData[mCurrBlock].SmmSpiProtocol,
+ mSpiCtrlerInfo->ProgramOpcodeIndex, // OpcodeIndex
+ 0, // PrefixOpcodeIndex
+ TRUE, // DataCycle
+ TRUE, // Atomic
+ TRUE, // ShiftOut
+ WriteAddress, // Address
+ mStateMachinePrivateData[mCurrBlock].BlockSize, // Data Number
+ (UINT8 *)(UINTN)mStateMachinePrivateData[mCurrBlock].SourceAddr,
+ EnumSpiRegionAll
+ );
+
+ //
+ // Data needs to be written to flash.
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Flash write is always enabled. Todo fix. Need to disable flash write first after write done.
+ //
+ mCurrBlock++;
+ mUpdateStatusPacket.BlocksCompleted = mCurrBlock;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear state machine structures for next capsule update.
+
+**/
+VOID
+ResetStateMachineDataStructures()
+{
+ UINTN Counter;
+
+ for(Counter =0; Counter < MAX_BLOCK_NUMBER; Counter++){
+ mStateMachinePrivateData[Counter].SmmSpiProtocol = NULL;
+ mStateMachinePrivateData[Counter].SourceAddr = 0x0;
+ mStateMachinePrivateData[Counter].TargetAddr = 0x0;
+ mStateMachinePrivateData[Counter].BlockSize = 0x0;
+ mStateMachinePrivateData[Counter].IsValid = FALSE;
+ mStateMachinePrivateData[Counter].UpdateStatus = FALSE;
+ }
+
+ mBufferOffset =0;
+}
+
+/**
+ Go through capsule update step by step.
+ The step is like ChallengeCapsule, CapsuleParse, and loop each block with Erase and Write.
+
+ @return Status return from each step.
+**/
+EFI_STATUS
+SmiStateMachine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if(mActiveState == SMI_FLASH_UPDATE_START){
+ mStateId = CHALLENGE_CAPSULE_STATE;
+ mActiveState = SMI_FLASH_UPDATE_IN_PROGRESS;
+ }
+ //
+ // Initialize next_state_ptr( )
+ //
+ mNextState.NextStatePointer = (NEXT_STATE_POINTER)SmiFlashUpdateStateArray[mStateId];
+ //
+ // Transition to next state
+ //
+ Status = mNextState.NextStatePointer();
+ mUpdateStatusPacket.Status = Status;
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Adjust the state_id
+ //
+ // CHALLENGE_CAPSULE_STATE=0,
+ // PARSE_CAPSULE_STATE,
+ // ERASE_BLOCK_STATE,
+ // WRITE_BLOCK_STATE
+
+ if (mStateId == WRITE_BLOCK_STATE){
+ //
+ // check if more blocks to update; if so:
+ //
+ if (mCurrBlock < MAX_BLOCK_NUMBER && mStateMachinePrivateData[mCurrBlock].IsValid == TRUE) {
+ mStateId = ERASE_BLOCK_STATE;
+ } else {
+ mStateId++;
+ }
+ } else {
+ mStateId++;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ SMI Handler to update flash and get update status.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param[in] SwRegisterContext Points to an optional handler context which was specified when the
+ handler was registered.
+ @param[in,out] SwContext A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in,out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_UNSUPPORTED The input SMI is not the expected SMI value.
+ @retval EFI_INVALID_PARAMETER The input capsule image is not the valid capsule.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to store the capsule image.
+ @retval EFI_SUCCESS Update capsule or Get update status successfully.
+**/
+EFI_STATUS
+EFIAPI
+SMIFlashSMIHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST EFI_SMM_SW_REGISTER_CONTEXT *SwRegisterContext,
+ IN OUT EFI_SMM_SW_CONTEXT *SwContext,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ UINT8 Function;
+ UINT8 Operation;
+ UPDATE_STATUS_PACKET *UpdateStatusPacketPtr;
+ CAPSULE_INFO_PACKET *CapsuleInfo;
+ CAPSULE_FRAGMENT *CapsuleFragment;
+ UINT16 Data16;
+ UINTN BufferAddress;
+ EFI_STATUS Status;
+
+ //
+ // Extract the subfunction number from AH, and process the requested subfunction.
+ //
+ Status = mSmmCpu->ReadSaveState (
+ mSmmCpu,
+ sizeof (UINT16),
+ EFI_SMM_SAVE_STATE_REGISTER_RAX,
+ SwContext->SwSmiCpuIndex,
+ &Data16
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Function and Operation
+ //
+ Function = (UINT8)((Data16 & 0xFF00) >> 8);
+ Operation = (UINT8)(Data16 & 0xFF);
+ if (Function != SMI_CAP_FUNCTION || Operation != SwRegisterContext->SwSmiInputValue) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = mSmmCpu->ReadSaveState (
+ mSmmCpu,
+ sizeof (UINTN),
+ EFI_SMM_SAVE_STATE_REGISTER_RBX,
+ SwContext->SwSmiCpuIndex,
+ &BufferAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (Operation == SMI_INPUT_UPDATE_CAP) {
+ //
+ // Copy the Capsule into SMM capsule Buffer for processing
+ //
+ CapsuleInfo = (CAPSULE_INFO_PACKET *) BufferAddress;
+ CapsuleFragment = (CAPSULE_FRAGMENT *) CapsuleInfo->CapsuleLocation;
+ if (mCapsuleSmmBuffer == NULL) {
+ //
+ // Return Error if SMM Buffer to store cap is not avaiable
+ //
+ mUpdateStatusPacket.Status = EFI_OUT_OF_RESOURCES;
+ CapsuleInfo->Status = EFI_OUT_OF_RESOURCES;
+ return mUpdateStatusPacket.Status;
+ }
+
+ mUpdateStatusPacket.TotalBlocks = (UINTN) -1;
+ mUpdateStatusPacket.BlocksCompleted = 0;
+ mUpdateStatusPacket.Status = EFI_NOT_READY;
+
+ //
+ // Process all the fragments - Each SMI could have 1 or more fragements
+ // must be terminated by NULL fragment entry
+ //
+ while ((UINT8 *)(UINTN)CapsuleFragment->Address != NULL && CapsuleFragment->Size != 0) {
+ //
+ // Check wether capsule chunk is one expected.Chunks should be passed in sequence.
+ //
+ if (CapsuleFragment->BufferOffset != mBufferOffset) {
+ mUpdateStatusPacket.Status = EFI_INVALID_PARAMETER;
+ CapsuleInfo->Status = EFI_INVALID_PARAMETER;
+ mBufferOffset = 0;
+ return mUpdateStatusPacket.Status;
+ }
+ //
+ // Make sure capsule size is not larger than ACPI NVS buffer.
+ //
+ ASSERT ((mBufferOffset + CapsuleFragment->Size) <= FixedPcdGet32(PcdMaxSizeNonPopulateCapsule));
+ if ((mBufferOffset + CapsuleFragment->Size) > FixedPcdGet32(PcdMaxSizeNonPopulateCapsule)) {
+ //
+ // return no buffer available, if capsule too big
+ //
+ mUpdateStatusPacket.Status = EFI_OUT_OF_RESOURCES;
+ CapsuleInfo->Status = EFI_OUT_OF_RESOURCES;
+ mBufferOffset = 0;
+ return mUpdateStatusPacket.Status;
+ }
+ //
+ // Copy capsule chunk to ACPI NVS buffer
+ //
+ CopyMem (mCapsuleSmmBuffer + mBufferOffset, (UINT8 *)(UINTN)CapsuleFragment->Address, CapsuleFragment->Size);
+ mBufferOffset = mBufferOffset + CapsuleFragment->Size;
+
+ //
+ // When all Capsule chunks are passed, last fragment entry flags Bit0 set to 1
+ //
+ if((CapsuleFragment->Flags & BIT0) == BIT0) {
+ ASSERT (mBufferOffset == CapsuleInfo->CapsuleSize);
+ //
+ // Update Capusle Image
+ //
+ mUpdateStatusPacket.Status = EFI_SUCCESS;
+ mActiveState = SMI_FLASH_UPDATE_START;
+ do {
+ Status = SmiStateMachine();
+ } while (!EFI_ERROR (Status) && (mStateId != (SMI_FLASH_UPDATE_MAX_STATES - 1)));
+ ResetStateMachineDataStructures();
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ break;
+ }
+ CapsuleFragment++;
+ }
+
+ //
+ // Return status for Each capsule transfer call
+ //
+ CapsuleInfo->Status = EFI_SUCCESS;
+ } else if (Operation == SMI_INPUT_GET_CAP) {
+ //
+ // Return current update status
+ //
+ UpdateStatusPacketPtr = (UPDATE_STATUS_PACKET *)BufferAddress;
+ UpdateStatusPacketPtr->Status = mUpdateStatusPacket.Status;
+ UpdateStatusPacketPtr->BlocksCompleted = mUpdateStatusPacket.BlocksCompleted;
+ UpdateStatusPacketPtr->TotalBlocks = mUpdateStatusPacket.TotalBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ SMI Flash Dxe Entry point. It intializes memory and services,
+ and registers two SMI handler for capsule update.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+SMIFlashDxeEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE SwHandle;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
+ EFI_SMM_SW_REGISTER_CONTEXT SwContext;
+ EFI_PHYSICAL_ADDRESS Memory;
+ EFI_BOOT_MODE BootMode;
+
+ BootMode = GetBootModeHob ();
+
+ mSpiImageListSize = sizeof(mSpiImageList)/sizeof(SPI_IMAGE_PRESENT);
+
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, &mEfiSpiProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find info to allow usage of SpiProtocol->Execute.
+ //
+ Status = mEfiSpiProtocol->Info (
+ mEfiSpiProtocol,
+ &mSpiCtrlerInfo
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (mSpiCtrlerInfo != NULL);
+ ASSERT (mSpiCtrlerInfo->InitTable != NULL && mSpiCtrlerInfo->EraseOpcodeIndex < SPI_NUM_OPCODE && mSpiCtrlerInfo->ProgramOpcodeIndex < SPI_NUM_OPCODE);
+
+ mSpiFlashBaseAddress = FixedPcdGet32 (PcdFlashAreaBaseAddress) - (UINT32)mSpiCtrlerInfo->InitTable->BiosStartOffset;
+ ASSERT(mSpiFlashBaseAddress >= (SIZE_4GB - SPI_FLASH_8M));
+
+ //
+ // Allocate Buffer for capsule in SMM. SMM is not enough so use ACPI NVS.
+ // mCapsuleSmmBuffer = AllocatePages (EFI_SIZE_TO_PAGES (FixedPcdGet32(PcdMaxSizeNonPopulateCapsule)));
+ //
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (FixedPcdGet32(PcdMaxSizeNonPopulateCapsule)),
+ &Memory
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mCapsuleSmmBuffer = (UINT8 *) (UINTN) Memory;
+ ASSERT (mCapsuleSmmBuffer != NULL);
+ if (mCapsuleSmmBuffer == NULL) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, &mSmmCpu);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, &SwDispatch);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register SMI handler for Update and GetInfo.
+ //
+ SwContext.SwSmiInputValue = SMI_INPUT_UPDATE_CAP;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ SMIFlashSMIHandler,
+ &SwContext,
+ &SwHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SwContext.SwSmiInputValue = SMI_INPUT_GET_CAP;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ SMIFlashSMIHandler,
+ &SwContext,
+ &SwHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Init trapping of SPI Flash access violations on secure lock builds.
+ //
+ if (FeaturePcdGet (PcdEnableSecureLock) && BootMode != BOOT_ON_FLASH_UPDATE && BootMode != BOOT_IN_RECOVERY_MODE) {
+ AccessViolationHandlerInit ();
+ QncEnableLegacyFlashAccessViolationSmi ();
+ }
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.h b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.h
new file mode 100755
index 0000000..bb01bba
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.h
@@ -0,0 +1,169 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SMIFlashDxe.h
+
+Abstract:
+
+ SMI driver to update BIOS capsule.
+
+--*/
+
+#ifndef _SMI_FLASH_DXE_H_
+#define _SMI_FLASH_DXE_H_
+
+#include <PiSmm.h>
+#include <Guid/QuarkCapsuleGuid.h>
+#include <Protocol/SmmCpu.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/Spi.h>
+#include <Protocol/SmmFirmwareVolumeBlock.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformDataLib.h>
+
+#include <FlashLayout.h>
+
+#include "AccessViolationHandler.h"
+
+#define SMI_FLASH_UPDATE_MAX_STATES 5
+#define MAX_IMAGES_PER_CAPSULE 20
+
+//
+// All the legacy SPI flash images that the SPI update mechanism is aware of.
+// The update mechansim will only consider images in the below list
+//
+#define EDKII_BOOTROM_OVERRIDE_DEFAULT_BASE_ADDRESS 0xFFFE0000
+#define EDKII_KEY_MODULE_DEFAULT_BASE_ADDRESS 0xFFFD8000
+#define EDKII_SVN_DEFAULT_BASE_ADDRESS 0xFFFD0000
+#define EDKII_RECOVERY_IMAGE1_DEFAULT_BASE_ADDRESS FixedPcdGet32 (PcdFlashFvFixedStage1AreaBase)
+#define EDKII_OEM_AREA_DEFAULT_BASE_ADDRESS 0xFFF50000
+#define EDKII_NVRAM_DEFAULT_BASE_ADDRESS FLASH_REGION_BIOS_NV_STORAGE_BASE
+#define EDKII_PLATFORM_DATA_DEFAULT_BASE_ADDRESS FixedPcdGet32 (PcdPlatformDataBaseAddress)
+#define EDKII_MFH_DEFAULT_BASE_ADDRESS FixedPcdGet32 (PcdFlashNvMfh)
+#define EDKII_RMU_DEFAULT_BASE_ADDRESS 0xFFF00000
+#define EDKII_BOOT_STAGE1_IMAGE1_DEFAULT_BASE_ADDRESS 0xFFEC0000
+#define EDKII_BOOT_STAGE1_IMAGE2_DEFAULT_BASE_ADDRESS 0xFFE80000
+#define EDKII_BOOT_STAGE2_COMPACT_DEFAULT_BASE_ADDRESS 0xFFD00000
+#define EDKII_BIOS_SECTION_DEFAULT_BASE_ADDRESS 0xFFD00000
+#define EDKII_OS_DEFAULT_BASE_ADDRESS 0xFF800000
+
+#define EDKII_BOOTROM_OVERRIDE_MAX_SIZE 0x00020000 // 128K
+#define EDKII_KEY_MODULE_MAX_SIZE 0x00008000 // 32K
+#define EDKII_SVN_MAX_SIZE 0x00008000 // 32K
+#define EDKII_RECOVERY_IMAGE1_MAX_SIZE FLASH_REGION_FV_SECPEI_RECOVERY_SIZE
+#define EDKII_OEM_AREA_MAX_SIZE 0x00040000 // 256K
+#define EDKII_NVRAM_MAX_SIZE FLASH_REGION_BIOS_NV_STORAGE_SIZE
+#define EDKII_PLATFORM_DATA_MAX_SIZE (FixedPcdGet32 (PcdPlatformDataMaxLen))
+#define EDKII_MFH_MAX_SIZE 0x00008000 // 32K
+#define EDKII_RMU_MAX_SIZE 0x00008000 // 32K
+#define EDKII_BOOT_STAGE1_IMAGE1_MAX_SIZE 0x00040000 // 256K
+#define EDKII_BOOT_STAGE1_IMAGE2_MAX_SIZE 0x00040000 // 256K
+#define EDKII_BOOT_STAGE2_COMPACT_MAX_SIZE 0x00180000 // 1.5M
+#define EDKII_BIOS_SECTION_MAX_SIZE 0x00300000 // 3M
+#define EDKII_OS_MAX_SIZE 0x00500000 // 5M
+
+#define SPI_FLASH_4M 0x400000
+#define SPI_FLASH_8M 0x800000
+
+//
+// Capsule Header Flags defined by Capsule GUID
+//
+#define PD_UPDATE_MAC 0x00000001
+
+#define SPI_ERASE_SECTOR_SIZE FLASH_BLOCK_SIZE //This is the chipset requirement
+
+#pragma pack(1)
+
+typedef struct {
+ UINT32 SpiImageDefaultBaseAddress;
+ UINT32 SpiImageMaxSize;
+ BOOLEAN FixedAddress;
+ BOOLEAN Updatable;
+ BOOLEAN AnyBlockUpdate;
+ BOOLEAN Present;
+} SPI_IMAGE_PRESENT;
+
+//
+// Periodic SMI functionality
+//
+typedef
+EFI_STATUS
+(EFIAPI *NEXT_STATE_POINTER) (
+ VOID
+ );
+
+typedef struct _NEXT_STATE {
+ NEXT_STATE_POINTER NextStatePointer;
+} NEXT_STATE;
+
+typedef enum {
+ SMI_FLASH_UPDATE_START,
+ SMI_FLASH_UPDATE_IN_PROGRESS,
+ SMI_FLASH_UPDATE_STOP
+} SMI_FLASH_STATE_MANAGER;
+
+typedef struct {
+ UINT32 TargetAddr;
+ UINT32 Size;
+ UINT32 SourceOffset;
+ UINT32 Reserved;
+} UPDATE_HINT;
+
+typedef struct {
+ EFI_SPI_PROTOCOL *SmmSpiProtocol;
+ UINT32 SourceAddr;
+ UINT32 TargetAddr;
+ UINTN BlockSize;
+ BOOLEAN IsValid;
+ BOOLEAN UpdateStatus;
+} STATE_MACHINE_PRIVATE_DATA;
+
+typedef enum {
+ CHALLENGE_CAPSULE_STATE = 0, // 0
+ PARSE_CAPSULE_STATE, // 1
+ ERASE_BLOCK_STATE, // 2
+ WRITE_BLOCK_STATE // 3
+} SMI_FLASH_STATE_ENUM; // 4
+
+#pragma pack()
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.inf b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.inf
new file mode 100755
index 0000000..c7600fe
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.inf
@@ -0,0 +1,98 @@
+## @file
+# SMI handler to update capsule image.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SMIFlashDxe
+ FILE_GUID = A62DE354-CBED-436b-954D-B66195A525CB
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SMIFlashDxeEntry
+
+[Sources]
+ SMIFlashDxe.c
+ SMIFlashDxe.h
+ AccessViolationHandler.c
+ AccessViolationHandler.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ SmmServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ PlatformDataLib
+ PlatformHelperLib
+ IntelQNCLib
+ HobLib
+
+[Protocols]
+ gEfiSmmSpiProtocolGuid # CONSUMES
+ gEfiSmmSwDispatch2ProtocolGuid # CONSUMES
+ gEfiSmmCpuProtocolGuid # CONSUMES
+ gEfiSmmFirmwareVolumeBlockProtocolGuid # CONSUMES
+ gEfiSmmVariableProtocolGuid
+
+[Guids]
+ gEfiQuarkCapsuleGuid
+ gEfiGlobalVariableGuid
+
+[FixedPcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformDataBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvMfh
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformDataMaxLen
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageSize
+
+[FeaturePcd]
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock
+
+[Depex]
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiSmmCpuProtocolGuid AND
+ gEfiSmmFirmwareVolumeBlockProtocolGuid
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.c b/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.c
new file mode 100755
index 0000000..32abe62
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.c
@@ -0,0 +1,271 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+Module Name:
+ PlatformConfigPei.c
+
+Abstract:
+ Principle source module for Clanton Peak platform config PEIM driver.
+
+--*/
+
+#include "PlatformConfigPei.h"
+
+//
+// Global variables.
+//
+
+EFI_PEI_NOTIFY_DESCRIPTOR mPcdNotifyList[1] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPcdPpiGuid,
+ PlatformConfigPcdNotifyCallback
+ }
+};
+
+//
+// Private routines to this source module.
+//
+
+STATIC
+VOID
+EFIAPI
+LegacySpiProtect (
+ VOID
+ )
+{
+ UINT32 RegVal;
+
+ RegVal = FixedPcdGet32 (PcdLegacyProtectedBIOSRange0Pei);
+ if (RegVal != 0) {
+
+ PlatformWriteFirstFreeSpiProtect (
+ RegVal,
+ 0,
+ 0
+ );
+
+ }
+ RegVal = FixedPcdGet32 (PcdLegacyProtectedBIOSRange1Pei);
+ if (RegVal != 0) {
+ PlatformWriteFirstFreeSpiProtect (
+ RegVal,
+ 0,
+ 0
+ );
+ }
+ RegVal = FixedPcdGet32 (PcdLegacyProtectedBIOSRange2Pei);
+ if (RegVal != 0) {
+ PlatformWriteFirstFreeSpiProtect (
+ RegVal,
+ 0,
+ 0
+ );
+ }
+
+ //
+ // Make legacy SPI READ/WRITE enabled if not a secure build
+ //
+ if(FeaturePcdGet (PcdEnableSecureLock)) {
+ LpcPciCfg32And (R_QNC_LPC_BIOS_CNTL, ~B_QNC_LPC_BIOS_CNTL_BIOSWE);
+ } else {
+ LpcPciCfg32Or (R_QNC_LPC_BIOS_CNTL, B_QNC_LPC_BIOS_CNTL_BIOSWE);
+ }
+
+}
+
+
+/** Set Dynamic PCD values.
+
+**/
+STATIC
+VOID
+EFIAPI
+UpdateDynamicPcds (
+ VOID
+ )
+{
+ MFH_LIB_FINDCONTEXT FindContext;
+ MFH_FLASH_ITEM *FlashItem;
+ UINT32 SecHdrSize;
+ UINT32 Temp32;
+ UINT32 SramImageIndex;
+ QUARK_EDKII_STAGE1_HEADER *SramEdk2ImageHeader;
+ QUARK_EDKII_STAGE1_HEADER *FlashEntryEdk2ImageHeader;
+ MFH_LIB_FINDCONTEXT MfhFindContext;
+ UINT32 Stage1Base;
+ UINT32 Stage1Len;
+
+ SecHdrSize = FixedPcdGet32 (PcdFvSecurityHeaderSize);
+
+ //
+ // Setup stage1 base and length PCDs.
+ //
+
+ //
+ // Assume running from fixed recovery area if no match found in MFH.
+ //
+ Stage1Base = FixedPcdGet32 (PcdFlashFvFixedStage1AreaBase);
+ Stage1Len = FixedPcdGet32 (PcdFlashFvFixedStage1AreaSize);
+
+ //
+ // If found in SPI MFH override Stage1Base & Len with MFH values.
+ //
+ SramEdk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) (FixedPcdGet32 (PcdEsramStage1Base) + SecHdrSize);
+ SramImageIndex = (UINT32) SramEdk2ImageHeader->ImageIndex;
+ FlashItem = MfhLibFindFirstWithFilter (
+ MFH_FIND_ALL_STAGE1_FILTER,
+ FALSE,
+ &MfhFindContext
+ );
+ while (FlashItem != NULL) {
+ FlashEntryEdk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) (FlashItem->FlashAddress + SecHdrSize);
+ if (SramImageIndex == FlashEntryEdk2ImageHeader->ImageIndex) {
+ Stage1Base = FlashItem->FlashAddress;
+ Stage1Len = FlashItem->LengthBytes;
+ break;
+ }
+ FlashItem = MfhLibFindNextWithFilter (
+ MFH_FIND_ALL_STAGE1_FILTER,
+ &MfhFindContext
+ );
+ }
+
+ Temp32 = PcdSet32 (PcdFlashFvRecoveryBase, (Stage1Base + SecHdrSize));
+ ASSERT (Temp32 == (Stage1Base + SecHdrSize));
+
+ Temp32 = PcdSet32 (PcdFlashFvRecoverySize, (Stage1Len - SecHdrSize));
+ ASSERT (Temp32 == (Stage1Len - SecHdrSize));
+
+ //
+ // Set FvMain base and length PCDs from SPI MFH database.
+ //
+ FlashItem = MfhLibFindFirstWithFilter (
+ MFH_FIND_ALL_STAGE2_FILTER,
+ FALSE,
+ &FindContext
+ );
+
+ if (FlashItem != NULL) {
+ Temp32 = PcdSet32 (PcdFlashFvMainBase, (FlashItem->FlashAddress + SecHdrSize));
+ ASSERT (Temp32 == (FlashItem->FlashAddress + SecHdrSize));
+
+ Temp32 = PcdSet32 (PcdFlashFvMainSize, (FlashItem->LengthBytes - SecHdrSize));
+ ASSERT (Temp32 == (FlashItem->LengthBytes - SecHdrSize));
+ }
+
+ //
+ // Set Payload base and length PCDs from SPI MFH database.
+ //
+ FlashItem = MfhLibFindFirstWithFilter (
+ MFH_FIND_ALL_BOOTLOADER_FILTER,
+ FALSE,
+ &FindContext
+ );
+
+ if (FlashItem != NULL) {
+ Temp32 = PcdSet32 (PcdFlashFvPayloadBase, (FlashItem->FlashAddress + SecHdrSize));
+ ASSERT (Temp32 == (FlashItem->FlashAddress + SecHdrSize));
+
+ Temp32 = PcdSet32 (PcdFlashFvPayloadSize, FlashItem->LengthBytes);
+ ASSERT (Temp32 == FlashItem->LengthBytes);
+ }
+}
+
+//
+// Public routines exported by this source module.
+//
+
+/** Callback to indicate Pcd services available.
+
+ Config operations to do when PCD services available.
+ 1) Call PeiQNCPreMemInit library function.
+ 2) Protect Legacy SPI Flash regions.
+ 3) Update Dynamic PCDs.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] NotifyDescriptor Information about the notify event.
+ @param[in] Ppi The notify context.
+
+ @retval EFI_SUCCESS Platform config success.
+*/
+EFI_STATUS
+EFIAPI
+PlatformConfigPcdNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ //
+ // Do SOC Init Pre memory init.
+ //
+ PeiQNCPreMemInit ();
+
+ //
+ // Protect areas specified by PCDs.
+ //
+ LegacySpiProtect ();
+
+ //
+ // Early update of Dynamic PCDs given run time info.
+ //
+ UpdateDynamicPcds ();
+ return EFI_SUCCESS;
+}
+
+/** PlatformConfigPei driver entry point.
+
+ Platform config in PEI stage.
+
+ @param[in] FfsHeader Pointer to Firmware File System file header.
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS Platform config success.
+*/
+EFI_STATUS
+EFIAPI
+PlatformConfigPeiInit (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Do config tasks when PCD PEI services available.
+ //
+ Status = PeiServicesNotifyPpi (&mPcdNotifyList[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.h b/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.h
new file mode 100644
index 0000000..b97bc26
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.h
@@ -0,0 +1,71 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+ PlatformConfigPei.h
+
+Abstract:
+ Private header file for Clanton Peak platform config PEIM module.
+
+--*/
+
+#ifndef _PLATFORM_CONFIG_PEI_H_
+#define _PLATFORM_CONFIG_PEI_H_
+
+#include <PiPei.h>
+#include <Ppi/Pcd.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MfhLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/PlatformDataLib.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/QNCAccessLib.h>
+#include <CommonIncludes.h>
+#include <Platform.h>
+#include <PlatformBoards.h>
+#include <FlashMap.h>
+
+#define EFI_PLATFORMCONFIG_DRIVER_PRIVATE_SIGNATURE \
+ SIGNATURE_32 ('P', 'C', 'F', 'G')
+
+EFI_STATUS
+EFIAPI
+PlatformConfigPcdNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf b/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
new file mode 100755
index 0000000..0ae8ff3
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
@@ -0,0 +1,104 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+# Module Name:
+#
+# PlatformConfigPei.inf
+#
+# Abstract:
+#
+# Component description file for Clanton Peak platform config PEIM module.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformConfigPei
+ FILE_GUID = 55961E20-B0D9-4553-9948-E3ECF0BE0889
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformConfigPeiInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ PlatformConfigPei.c
+ PlatformConfigPei.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ PcdLib
+ DebugLib
+ HobLib
+ IoLib
+ IntelQNCLib
+ MfhLib
+ PlatformDataLib
+ PlatformHelperLib
+
+[FeaturePcd]
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+ gQuarkPlatformTokenSpaceGuid.PcdEsramStage1Base
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdLegacyProtectedBIOSRange0Pei
+ gQuarkPlatformTokenSpaceGuid.PcdLegacyProtectedBIOSRange1Pei
+ gQuarkPlatformTokenSpaceGuid.PcdLegacyProtectedBIOSRange2Pei
+
+[Pcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoverySize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoveryBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainBase
+
+[Guids]
+
+[Ppis]
+ gPcdPpiGuid
+
+[Depex]
+ TRUE
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.c b/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.c
new file mode 100755
index 0000000..b42f058
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.c
@@ -0,0 +1,676 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PlatformInfo.c
+
+Abstract:
+
+ Platform Info PEIM.
+
+--*/
+
+#include "PlatformInfo.h"
+
+#define TEMP_BUS_NUMBER (0x3F)
+
+static EFI_PEI_PPI_DESCRIPTOR mPlatformInfoPpi = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPlatformInfoGuid,
+ NULL
+ };
+
+static EFI_GUID mPDatFileNameTable[] = { PDAT_FILE_NAME_TABLE_DEFINITION };
+static UINTN mPDatFileNameTableLen = ((sizeof(mPDatFileNameTable)) / sizeof (EFI_GUID));
+
+VOID
+CharOrIndex (
+ IN UINTN GotIndex,
+ OUT CHAR8 *EquivalentChar,
+ IN CHAR8 GotChar,
+ OUT UINTN *EquivalentIndex
+ )
+/*++
+Routine Description:
+
+ Translate table index to select key or translate key to table index.
+
+Arguments:
+
+ GotIndex - Table index to translate.
+ EquivalentChar - Key for GotIndex.
+ GotChar - Key to translate.
+ EquivalentIndex - Table index for GotChar.
+
+Returns:
+
+ EquivalentChar - Key for GotIndex.
+ EquivalentIndex - Table index for GotChar.
+
+--*/
+{
+ CHAR8 Temp;
+ if (EquivalentChar != NULL) {
+ if (GotIndex < 10) {
+ *EquivalentChar = '0' + ((CHAR8) GotIndex);
+ } else {
+ Temp = ((CHAR8) GotIndex) - 10;
+ *EquivalentChar = 'a' + Temp;
+ }
+ return;
+ }
+ if (EquivalentIndex != NULL) {
+ if (GotChar < 'a') {
+ *EquivalentIndex = (UINTN) (GotChar - '0');
+ } else {
+ Temp = (GotChar - 'a');
+ *EquivalentIndex = 10 + (UINTN) Temp;
+ }
+ }
+}
+
+EFI_STATUS
+CheckMrcParams (
+ IN UINT16 Type,
+ IN PDAT_ITEM *Item
+ )
+/*++
+Routine Description:
+
+ Check mrc config valid.
+
+Arguments:
+
+ Type - Type of platform mrc config is for.
+ Item - Mrc config item to check.
+
+Returns:
+
+ EFI_SUCCESS - Valid Mrc config.
+ EFI_INCOMPATIBLE_VERSION - Invalid item version.
+ EFI_INVALID_PARAMETER - Mrc config not for platform type specified.
+
+--*/
+{
+ PDAT_MRC_ITEM *MrcItemData;
+
+ if (Item->Header.Version < PDAT_MRC_MIN_VERSION) {
+ DEBUG ((EFI_D_ERROR, "Platform Info: Mrc Vars in Platform Data is Version:%d. Must be >= Version:%d!!!!!\n", Item->Header.Version, PDAT_MRC_MIN_VERSION));
+ return EFI_INCOMPATIBLE_VERSION;
+ }
+
+ MrcItemData = (PDAT_MRC_ITEM *) Item->Data;
+
+ //
+ // Check parameters for this platform.
+ //
+ if (Type != MrcItemData->PlatformId) {
+ DEBUG ((EFI_D_ERROR, "Platform Info: Mrc Vars for this platform not found: want id %d got id %d\n", Type, MrcItemData->PlatformId));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FindAndCheckPlatformDataFile (
+ IN CONST EFI_GUID *FileNameGuid,
+ OUT PDAT_AREA **AreaPtr,
+ OUT UINTN *AreaSize,
+ OUT PDAT_ITEM **TypeItemPtr,
+ OUT PDAT_ITEM **MrcItemPtr,
+ OUT UINT16 *TypePtr
+ )
+/*++
+Routine Description:
+
+ Find platform data file in firmware volumes and check it is valid.
+
+Arguments:
+
+ FileNameGuid - Platform data file to find.
+ AreaPtr - Pointer to be pointed to platform data area.
+ AreaSize - Update with size of platform data area.
+ TypeItemPtr - Update with address of platform type item.
+ MrcItemPtr - Update with address of mrc config item.
+ TypePtr - Store platform type at this address.
+
+Returns:
+
+ EFI_SUCCESS - Valid file found.
+ EFI_NOT_FOUND - File not found.
+ EFI_INVALID_PARAMETER - File found but data in file invalid.
+ AreaPtr - Pointing to platform data area in file.
+ AreaSize - Updated with size of platform data area.
+ TypeItemPtr - Updated with address of platform type item.
+ MrcItemPtr - Updated with address of mrc config item.
+ TypePtr - Updated with platform type.
+
+--*/
+{
+ EFI_STATUS Status;
+ Status = PlatformFindFvFileRawDataSection (NULL, FileNameGuid, (VOID **) AreaPtr, AreaSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Platform Info: File %g not found in FV\n", FileNameGuid));
+ return EFI_NOT_FOUND;
+ }
+ Status = PDatLibValidateArea (*AreaPtr, TRUE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Platform Info: File %g has bad PDAT area %r\n", FileNameGuid, Status));
+ return EFI_INVALID_PARAMETER;
+ }
+ *TypeItemPtr = PDatLibFindItem (*AreaPtr, PDAT_ITEM_ID_PLATFORM_ID, FALSE, TypePtr);
+ if (*TypeItemPtr == NULL) {
+ DEBUG ((EFI_D_INFO, "Platform Info: File %g has no PID item\n", FileNameGuid));
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((*TypePtr > TypeUnknown) && (*TypePtr < TypePlatformMax)) {
+ *MrcItemPtr = PDatLibFindItem (*AreaPtr, PDAT_ITEM_ID_MRC_VARS, FALSE, NULL);
+ if (*MrcItemPtr == NULL) {
+ DEBUG ((EFI_D_INFO, "Platform Info: File %g has no MRCCFG item\n", FileNameGuid));
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ DEBUG ((EFI_D_INFO, "Platform Info: Invalid platform type %d\n", (UINTN) *TypePtr));
+ return EFI_INVALID_PARAMETER;
+ }
+ return CheckMrcParams (*TypePtr, *MrcItemPtr);
+}
+
+VOID
+TracePlatformDataSelectList (
+ VOID
+ )
+/*++
+Routine Description:
+
+ Trace list of valid platform data files stored in Firmware volumes.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ PDAT_AREA *CurrArea;
+ UINTN CurrAreaSize;
+ PDAT_ITEM *CurrTypeItem;
+ PDAT_ITEM *CurrMrcItem;
+ UINT16 CurrType;
+ CHAR8 KeyStrForIndex [4];
+
+ AsciiStrCpy (KeyStrForIndex,"'?'");
+
+ DEBUG ((EFI_D_INFO, "Platform Info: File name table contains %d entries\n", mPDatFileNameTableLen));
+
+ for (Index=0; Index < mPDatFileNameTableLen; Index++) {
+
+ Status = FindAndCheckPlatformDataFile (
+ &mPDatFileNameTable[Index],
+ &CurrArea,
+ &CurrAreaSize,
+ &CurrTypeItem,
+ &CurrMrcItem,
+ &CurrType
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ CharOrIndex (Index, &KeyStrForIndex[1], 0, NULL);
+ DEBUG (
+ (EFI_D_ERROR,
+ "Type %a for '%s' [PID %d]\n",
+ KeyStrForIndex,
+ PlatformTypeString (CurrType),
+ (UINTN) CurrType
+ ));
+ }
+}
+
+EFI_STATUS
+UserSelectPlatformDataFile (
+ OUT PDAT_AREA **AreaPtr,
+ OUT EFI_GUID *PlatformDataFile,
+ OUT UINT16 *TypePtr,
+ OUT PDAT_MRC_ITEM *MrcConfig
+ )
+/*++
+Routine Description:
+
+ Let user select platform data file to use over debug console.
+
+Arguments:
+
+ AreaPtr - Pointer to be pointed to platform data area.
+ PlatformDataFile - GUID to be updated with platform data file name.
+ TypePtr - Store selected platform type at this address.
+ MrcConfig - Store mrc config for platform type at this address.
+
+Returns:
+
+ EFI_SUCCESS - User selected valid file.
+ EFI_NOT_FOUND - No file selected.
+ AreaPtr - Pointing to selected platform data area.
+ PlatformDataFile - Updated with selected file name.
+ TypePtr - Updated with selected platform type.
+ MrcConfig - Updated with selected mrc config.
+
+--*/
+{
+ UINTN Selected;
+ CHAR8 Key;
+ EFI_STATUS Status;
+ UINTN AreaSize;
+ PDAT_ITEM *TypeItem;
+ PDAT_ITEM *MrcItem;
+
+ //
+ // Return error if no files to search for.
+ //
+ if (mPDatFileNameTableLen == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ do {
+ //
+ // Trace list of valid platform data files stored in Firmware volumes.
+ //
+ TracePlatformDataSelectList ();
+
+ //
+ // Ask user to select file to use.
+ //
+ Key = PlatformDebugPortGetChar8 ();
+
+ //
+ // Translate key typed to index into mPDatFileNameTable.
+ //
+ CharOrIndex (0, NULL, Key, &Selected);
+ if (Selected < mPDatFileNameTableLen) {
+
+ //
+ // Update output params with selected file.
+ //
+ Status = FindAndCheckPlatformDataFile (
+ &mPDatFileNameTable[Selected],
+ AreaPtr,
+ &AreaSize,
+ &TypeItem,
+ &MrcItem,
+ TypePtr
+ );
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Valid selection return to caller.
+ //
+ CopyGuid (
+ PlatformDataFile,
+ &mPDatFileNameTable[Selected]
+ );
+ CopyMem (
+ (VOID *) MrcConfig,
+ (VOID *) MrcItem->Data,
+ sizeof (PDAT_MRC_ITEM)
+ );
+ // Use EFI_D_ERROR so user on release builds knows data found.
+ DEBUG ((EFI_D_ERROR, "Platform Info: Type = %x\n", (UINTN) *TypePtr));
+ DEBUG ((EFI_D_ERROR, "Platform Info: Platform Data Mrc Vars found: length %d version = %d\n",
+ (UINTN) MrcItem->Header.Length,
+ (UINTN) MrcItem->Header.Version
+ ));
+ break;
+ }
+ }
+ //
+ // Block until user selects valid file.
+ //
+ } while (TRUE);
+
+ return Status;
+}
+
+VOID
+GetCpuInfo (
+ UINT8 *CpuType,
+ UINT8 *CpuStepping
+ )
+/*++
+
+Routine Description:
+ Returns the Model ID of the CPU.
+ Model ID = EAX[7:4]
+
+Returns:
+
+--*/
+
+{
+ UINT32 RegEax=0;
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
+
+ *CpuStepping = (UINT8)(RegEax & 0x0F);
+ *CpuType = (UINT8)((RegEax & 0xF0) >> 4);
+}
+
+EFI_STATUS
+PdrGetPlatformInfo (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ OUT EFI_PLATFORM_INFO *PlatformInfoHob
+ )
+/*++
+Routine Description:
+
+ Update platform info hob with platform data items.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ PlatformInfoHob - Hob to update with platform data items.
+
+Returns:
+
+ EFI_SUCCESS - Hob updated with platform data items.
+ Others - All other error conditions encountered result in an ASSERT.
+
+--*/
+{
+ PDAT_ITEM *Item;
+ EFI_STATUS Status;
+ PDAT_AREA *Area;
+ PDAT_MRC_ITEM *MrcItemData;
+ QUARK_EDKII_STAGE1_HEADER *Edk2ImageHeader;
+
+ //
+ // Set default values for information derived from platform data area.
+ //
+ PlatformInfoHob->Type = (EFI_PLATFORM_TYPE) TypeUnknown;
+ SetMem (PlatformInfoHob->SysData.IohMac0Address, sizeof(PlatformInfoHob->SysData.IohMac0Address), 0xff);
+ SetMem (PlatformInfoHob->SysData.IohMac1Address, sizeof(PlatformInfoHob->SysData.IohMac1Address), 0xff);
+
+ //
+ // Return error if platform data CRC error, size error or other unexpected error.
+ // For Recovery boot => User selects 'safe embedded' platform data
+ //
+ Edk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) (FixedPcdGet32 (PcdEsramStage1Base) + FixedPcdGet32 (PcdFvSecurityHeaderSize));
+ switch ((UINT8)Edk2ImageHeader->ImageIndex & QUARK_STAGE1_IMAGE_TYPE_MASK) {
+ case QUARK_STAGE1_RECOVERY_IMAGE_TYPE:
+ //
+ // Recovery Boot
+ //
+ Status = UserSelectPlatformDataFile (
+ &Area,
+ &PlatformInfoHob->BiosPlatformDataFile,
+ &PlatformInfoHob->Type,
+ &PlatformInfoHob->MemData.MemMrcConfig
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ break;
+ default:
+ //
+ // Normal Boot
+ //
+ Status = PDatLibGetSystemAreaPointer (TRUE, &Area);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((EFI_D_ERROR, "System Platform Data Area Signature not found.\n"));
+ } else if (Status == EFI_CRC_ERROR) {
+ DEBUG ((EFI_D_ERROR, "System Platform Data Area CRC Error.\n"));
+ } else if (Status == EFI_BAD_BUFFER_SIZE) {
+ DEBUG ((EFI_D_ERROR, "System Platform Data Area length too large for this platform.\n"));
+ } else {
+ DEBUG ((EFI_D_ERROR, "System Platform Data Area get failed error = %r.\n", Status));
+ }
+ ASSERT (FeaturePcdGet (PcdEnableSecureLock) == FALSE);
+ Status = UserSelectPlatformDataFile (
+ &Area,
+ &PlatformInfoHob->BiosPlatformDataFile,
+ &PlatformInfoHob->Type,
+ &PlatformInfoHob->MemData.MemMrcConfig
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ } else {
+ PlatformInfoHob->Type = (EFI_PLATFORM_TYPE) 0;
+ Item = PDatLibFindItem (Area, PDAT_ITEM_ID_PLATFORM_ID, FALSE, &PlatformInfoHob->Type);
+ if (Item == NULL) {
+ PlatformInfoHob->Type = TypeUnknown;
+ DEBUG ((EFI_D_ERROR, "SPI PDR missing does not contain a Platform ID item!!!!\n"));
+ ASSERT (FALSE);
+ }
+
+ if ((PlatformInfoHob->Type > TypeUnknown) && (PlatformInfoHob->Type < TypePlatformMax)) {
+ //
+ // Valid Platform Identified
+ //
+ DEBUG ((EFI_D_INFO, "Platform Info: Type = %x\n", (UINTN) PlatformInfoHob->Type));
+ } else {
+ //
+ // Reading from SPI PDR Failed or a unknown platform identified
+ //
+ DEBUG ((EFI_D_WARN, "SPI PDR reports Platform ID as %x. This is unknown ID.\n", PlatformInfoHob->Type));
+ PlatformInfoHob->Type = TypeUnknown;
+ ASSERT (FALSE);
+ }
+ Item = PDatLibFindItem (Area, PDAT_ITEM_ID_MRC_VARS, TRUE, NULL);
+ if (Item == NULL) {
+ DEBUG ((EFI_D_ERROR, "Platform Info: Mrc Vars not found in Platform Data!!!!!\n"));
+ ASSERT (FALSE);
+ } else {
+ Status = CheckMrcParams (PlatformInfoHob->Type, Item);
+ ASSERT_EFI_ERROR (Status);
+ MrcItemData = (PDAT_MRC_ITEM *) Item->Data;
+ CopyMem ((VOID *) &PlatformInfoHob->MemData.MemMrcConfig, (VOID *) MrcItemData, sizeof (PlatformInfoHob->MemData.MemMrcConfig));
+ DEBUG ((EFI_D_INFO, "Platform Info: Platform Data Mrc Vars found: length %d version = %d\n",
+ (UINTN) Item->Header.Length,
+ (UINTN) Item->Header.Version
+ ));
+ }
+ }
+ break;
+ }
+
+ //
+ // Read mac addresses configured in platform data flash area.
+ //
+ Item = PDatLibFindItem (Area, PDAT_ITEM_ID_MAC0, FALSE, PlatformInfoHob->SysData.IohMac0Address);
+ if (Item == NULL) {
+ DEBUG ((EFI_D_WARN, "Mac0 address not found in platform data.!!!!\n"));
+ } else {
+ ASSERT (Item->Header.Length == sizeof(PlatformInfoHob->SysData.IohMac0Address));
+ }
+ Item = PDatLibFindItem (Area, PDAT_ITEM_ID_MAC1, FALSE, PlatformInfoHob->SysData.IohMac1Address);
+ if (Item == NULL) {
+ DEBUG ((EFI_D_WARN, "Mac1 address not found in platform data.!!!!\n"));
+ } else {
+ ASSERT (Item->Header.Length == sizeof(PlatformInfoHob->SysData.IohMac1Address));
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MfhGetPlatformInfo (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ OUT EFI_PLATFORM_INFO *PlatformInfoHob
+ )
+/*++
+Routine Description:
+
+ Update platform info hob with MFH data items.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ PlatformInfoHob - Hob to update with MFH data items.
+
+Returns:
+
+ EFI_SUCCESS - Hob updated with MFH data items.
+ Others - All other error conditions encountered result in an ASSERT.
+
+--*/
+{
+ MFH_LIB_FINDCONTEXT MfhFindContext;
+ MFH_FLASH_ITEM *FlashItem;
+
+ FlashItem = MfhLibFindFirstWithFilter (
+ MFH_FIND_IMAGE_VERSION_FILTER,
+ FALSE,
+ &MfhFindContext
+ );
+ ASSERT (FlashItem != NULL);
+
+ PlatformInfoHob->FirmwareVersion = FlashItem->TypeSpecific.ImageVersion;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PlatformInfoInit (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+Routine Description:
+
+ Platform Type detection. Because the PEI globle variable
+ is in the flash, it could not change directly.So use
+ 2 PPIs to distinguish the platform type.
+
+Arguments:
+
+ FfsHeader - Pointer to Firmware File System file header.
+ PeiServices - General purpose services available to every PEIM.
+
+Returns:
+
+ EFI_SUCCESS - Memory initialization completed successfully.
+ Others - All other error conditions encountered result in an ASSERT.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_PCI_CFG2_PPI *PciCfgPpi;
+ UINT8 CpuType;
+ UINT8 CpuStepping;
+ UINT16 Data16;
+ UINT8 Data8;
+ EFI_PLATFORM_INFO PlatformInfoHob;
+
+ PciCfgPpi = (**PeiServices).PciCfg;
+ ASSERT (PciCfgPpi != NULL);
+
+ (*PeiServices)->SetMem (
+ &PlatformInfoHob,
+ sizeof (PlatformInfoHob),
+ 0
+ );
+
+ //
+ // Update platform info hob with platform data items.
+ //
+ Status = PdrGetPlatformInfo(PeiServices, &PlatformInfoHob);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update platform info hob with MFH data items if not recovery boot.
+ //
+ if (!PlatformIsBootWithRecoveryStage1 ()) {
+ Status = MfhGetPlatformInfo(PeiServices, &PlatformInfoHob);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Update IIO Type
+ //
+ PlatformInfoHob.IioRevision = 0;
+
+ //
+ // Update QNC Type
+ //
+ //
+ // Device ID
+ //
+ PciCfgPpi->Read (
+ PeiServices,
+ PciCfgPpi,
+ EfiPeiPciCfgWidthUint16,
+ PEI_PCI_CFG_ADDRESS (MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET),
+ &Data16
+ );
+ PlatformInfoHob.QncSku= Data16;
+
+ PciCfgPpi->Read (
+ PeiServices,
+ PciCfgPpi,
+ EfiPeiPciCfgWidthUint8,
+ PEI_PCI_CFG_ADDRESS (MC_BUS, MC_DEV, MC_FUN, PCI_REVISION_ID_OFFSET),
+ &Data8
+ );
+ PlatformInfoHob.QncRevision = Data8;
+
+ PlatformInfoHob.SysData.SysSioExist = FALSE;
+
+ GetCpuInfo (&CpuType, &CpuStepping);
+ PlatformInfoHob.CpuType = CpuType;
+ PlatformInfoHob.CpuStepping = CpuStepping;
+
+ //
+ // Build HOB for setup memory information
+ //
+
+ BuildGuidDataHob (
+ &gEfiPlatformInfoGuid,
+ &(PlatformInfoHob),
+ sizeof (EFI_PLATFORM_INFO)
+ );
+
+ Status = (**PeiServices).InstallPpi (PeiServices, &mPlatformInfoPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.h b/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.h
new file mode 100755
index 0000000..60ccc6a
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.h
@@ -0,0 +1,64 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+ PlatformInfo.h
+
+Abstract:
+ Platform Info Driver.
+
+--*/
+
+#ifndef _PLATFORM_INFO_H_
+#define _PLATFORM_INFO_H_
+
+#include <PiPei.h>
+#include <Ppi/CpuIo.h>
+#include <Ppi/PciCfg.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformDataLib.h>
+#include <Library/MfhLib.h>
+#include <Guid/PlatformInfo.h>
+#include <Guid/PlatformDataFileNameGuids.h>
+#include <IndustryStandard/Pci22.h>
+#include <CpuRegs.h>
+#include <IntelQNCRegs.h>
+#include <Platform.h>
+#include <PlatformData.h>
+
+#define EFI_PLATFORMINFO_DRIVER_PRIVATE_SIGNATURE SIGNATURE_32 ('P', 'I', 'N', 'F')
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf b/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
new file mode 100755
index 0000000..0cacf3a
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
@@ -0,0 +1,92 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# PlatformInfo.inf
+#
+# Abstract:
+#
+# Component description file for Quark peak platform info module.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformInfo
+ FILE_GUID = 34CC6167-7AE7-403e-8AB2-23837F398A30
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformInfoInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ PlatformInfo.c
+ PlatformInfo.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ PcdLib
+ DebugLib
+ HobLib
+ IoLib
+ PlatformDataLib
+ BaseMemoryLib
+ PlatformHelperLib
+ MfhLib
+
+[FeaturePcd]
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+ gQuarkPlatformTokenSpaceGuid.PcdEsramStage1Base
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[Guids]
+ gEfiPlatformInfoGuid
+
+[Ppis]
+
+[Depex]
+ gEfiPciCfg2PpiGuid
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/BootMode.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/BootMode.c
new file mode 100755
index 0000000..1b3df7b
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/BootMode.c
@@ -0,0 +1,274 @@
+/** @file
+ This file provide the function to detect boot mode
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "CommonHeader.h"
+#include <Pi/PiFirmwareVolume.h>
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiBootInRecoveryModePpiGuid,
+ NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListSStateBootMode = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiSStateBootModePpiGuid,
+ NULL
+};
+
+
+/**
+ If the box was opened, it's boot with full config.
+ If the box is closed, then
+ 1. If it's first time to boot, it's boot with full config .
+ 2. If the ChassisIntrution is selected, force to be a boot with full config
+ 3. Otherwise it's boot with no change.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @retval TRUE If it's boot with no change.
+
+ @retval FALSE If boot with no change.
+**/
+STATIC
+BOOLEAN
+IsBootWithNoChange (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ BOOLEAN IsFirstBoot = FALSE;
+
+ BOOLEAN EnableFastBoot = FALSE;
+ IsFirstBoot = PcdGetBool(PcdBootState);
+ EnableFastBoot = PcdGetBool (PcdEnableFastBoot);
+
+ DEBUG ((EFI_D_INFO, "IsFirstBoot = %x , EnableFastBoot= %x. \n", IsFirstBoot, EnableFastBoot));
+
+ if ((!IsFirstBoot) && EnableFastBoot) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/**
+
+Routine Description:
+
+ This function is used to verify if the FV header is validate.
+
+ @param FwVolHeader - The FV header that to be verified.
+
+ @retval EFI_SUCCESS - The Fv header is valid.
+ @retval EFI_NOT_FOUND - The Fv header is invalid.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ EFI_BOOT_MODE *BootMode
+ )
+{
+ UINT16 *Ptr;
+ UINT16 HeaderLength;
+ UINT16 Checksum;
+
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+
+ if (BOOT_IN_RECOVERY_MODE == *BootMode) {
+ DEBUG ((EFI_D_INFO, "Boot mode recovery\n"));
+ return EFI_SUCCESS;
+ }
+ //
+ // Let's check whether FvMain header is valid, if not enter into recovery mode
+ //
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32(PcdFlashFvMainBase);
+ if ((FwVolHeader->Revision != EFI_FVH_REVISION)||
+ (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
+ (FwVolHeader->FvLength == ((UINT64) -1)) ||
+ ((FwVolHeader->HeaderLength & 0x01) != 0)
+ ) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Verify the header checksum
+ //
+ HeaderLength = (UINT16) (FwVolHeader->HeaderLength / 2);
+ Ptr = (UINT16 *) FwVolHeader;
+ Checksum = 0;
+ while (HeaderLength > 0) {
+ Checksum = Checksum +*Ptr;
+ Ptr++;
+ HeaderLength--;
+ }
+
+ if (Checksum != 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Check whether go to recovery path
+ @retval TRUE Go to recovery path
+ @retval FALSE Go to normal path
+
+**/
+BOOLEAN
+OemRecoveryBootMode ()
+{
+ return PlatformIsBootWithRecoveryStage1 ();
+}
+
+/**
+ Peform the boot mode determination logic
+ If the box is closed, then
+ 1. If it's first time to boot, it's boot with full config .
+ 2. If the ChassisIntrution is selected, force to be a boot with full config
+ 3. Otherwise it's boot with no change.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @param BootMode The detected boot mode.
+
+ @retval EFI_SUCCESS if the boot mode could be set
+**/
+EFI_STATUS
+UpdateBootMode (
+ IN EFI_PEI_SERVICES **PeiServices,
+ OUT EFI_BOOT_MODE *BootMode
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE NewBootMode;
+ PEI_CAPSULE_PPI *Capsule;
+ CHAR8 UserSelection;
+
+ //
+ // Check if we need to boot in recovery mode
+ //
+ if ((ValidateFvHeader (BootMode) != EFI_SUCCESS)) {
+ DEBUG ((EFI_D_INFO, "Force Boot mode recovery\n"));
+ NewBootMode = BOOT_IN_RECOVERY_MODE;
+ Status = PeiServicesInstallPpi (&mPpiListRecoveryBootMode);
+ ASSERT_EFI_ERROR (Status);
+ if (OemRecoveryBootMode () == FALSE) {
+ DEBUG ((EFI_D_INFO, "Recovery stage1 not Active, reboot to activate recovery stage1 image\n"));
+ OemInitiateRecoveryAndWait ();
+ }
+ } else if (OemRecoveryBootMode ()) {
+ DEBUG ((EFI_D_INFO, "Boot mode recovery\n"));
+ NewBootMode = BOOT_IN_RECOVERY_MODE;
+ Status = PeiServicesInstallPpi (&mPpiListRecoveryBootMode);
+ ASSERT_EFI_ERROR (Status);
+ } else if (QNCCheckS3AndClearState ()) {
+ //
+ // Determine if we're in capsule update mode
+ //
+ Status = (**PeiServices).LocatePpi (
+ PeiServices,
+ &gPeiCapsulePpiGuid,
+ 0,
+ NULL,
+ (VOID **)&Capsule
+ );
+ if (Status == EFI_SUCCESS) {
+ Status = Capsule->CheckCapsuleUpdate (PeiServices);
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_INFO, "Boot mode Flash Update\n"));
+ NewBootMode = BOOT_ON_FLASH_UPDATE;
+ } else {
+ DEBUG ((EFI_D_INFO, "Boot mode S3 resume\n"));
+ NewBootMode = BOOT_ON_S3_RESUME;
+ Status = PeiServicesInstallPpi (&mPpiListSStateBootMode);
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ DEBUG ((EFI_D_INFO, "Boot mode S3 resume\n"));
+ NewBootMode = BOOT_ON_S3_RESUME;
+ Status = PeiServicesInstallPpi (&mPpiListSStateBootMode);
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ //
+ // Check if this is a power on reset
+ //
+ if (QNCCheckPowerOnResetAndClearState ()) {
+ DEBUG ((EFI_D_INFO, "Power On Reset\n"));
+ PcdSetBool (PcdIsPowerOnReset, TRUE);
+ }
+ if (IsBootWithNoChange (PeiServices)) {
+ DEBUG ((EFI_D_INFO, "Boot with Minimum cfg\n"));
+ NewBootMode = BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
+ } else {
+ DEBUG ((EFI_D_INFO, "Boot with Full cfg\n"));
+ NewBootMode = BOOT_WITH_FULL_CONFIGURATION;
+ }
+ }
+ *BootMode = NewBootMode;
+ Status = PeiServicesSetBootMode (NewBootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // If Recovery Boot then prompt the user to insert a USB key with recovery nodule and
+ // continue with the recovery. Also give the user a chance to retry a normal boot.
+ //
+ if (NewBootMode == BOOT_IN_RECOVERY_MODE) {
+ DEBUG ((EFI_D_ERROR, "*****************************************************************\n"));
+ DEBUG ((EFI_D_ERROR, "***** ERROR: System boot failure!!!!!!! *****\n"));
+ DEBUG ((EFI_D_ERROR, "***** REMOVE ANY FORCE RECOVERY JUMPERS BEFORE PROCEEDING! *****\n"));
+ DEBUG ((EFI_D_ERROR, "***** - Press 'R' if you wish to force system recovery *****\n"));
+ DEBUG ((EFI_D_ERROR, "***** (connect USB key with recovery module first) *****\n"));
+ DEBUG ((EFI_D_ERROR, "***** - Press any other key to attempt another boot *****\n"));
+ DEBUG ((EFI_D_ERROR, "*****************************************************************\n"));
+ UserSelection = PlatformDebugPortGetChar8 ();
+ if ((UserSelection != 'R') && (UserSelection != 'r')) {
+ DEBUG ((EFI_D_ERROR, "New boot attempt selected........\n"));
+ //
+ // Initialte the cold reset
+ //
+ ResetCold ();
+ }
+ DEBUG ((EFI_D_ERROR, "Recovery boot selected..........\n"));
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/Capsule.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/Capsule.c
new file mode 100644
index 0000000..2e70fb5
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/Capsule.c
@@ -0,0 +1,416 @@
+/** @file
+ Provide capsule services to this component.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+#include "PlatformEarlyInit.h"
+
+/**
+ Check every capsule header.
+
+ @param CapsuleHeader The pointer to EFI_CAPSULE_HEADER
+
+ @retval FALSE Capsule is OK
+ @retval TRUE Capsule is corrupted
+
+**/
+STATIC
+BOOLEAN
+IsCapsuleCorrupted (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Check capsule header supported by our platform.
+ //
+ Status = PlatformSupportCapsuleImage (CapsuleHeader);
+ if (EFI_ERROR(Status)) {
+ return TRUE;
+ }
+
+ //
+ // A capsule to be updated across a system reset should contain CAPSULE_FLAGS_PERSIST_ACROSS_RESET.
+ //
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
+ return TRUE;
+ }
+ //
+ // Make sure the flags combination is supported by the platform.
+ //
+ if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
+ return TRUE;
+ }
+ if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Build security headers hobs
+
+ Build Hob for each secuity header found in descriptor list.
+
+ @param BlockList Pointer to the capsule descriptors.
+
+ @retval 0 if no security headers found.
+ @return number of security header hobs built.
+
+**/
+STATIC
+UINTN
+BuildSecurityHeaderHobs (
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList
+ )
+{
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ UINT64 CapsuleSize;
+ UINT32 CapsuleCount;
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr;
+ UINT8 *Found;
+ UINTN HobCnt;
+
+ //
+ // Init locals.
+ //
+ CapsuleSize = 0;
+ CapsuleCount = 0;
+ Ptr = BlockList;
+ Found = NULL;
+ HobCnt = 0;
+ while ((Ptr->Length != 0) || (Ptr->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
+ //
+ // Make sure the descriptor is aligned at UINT64 in memory.
+ //
+ if ((UINTN) Ptr & 0x07) {
+ DEBUG ((EFI_D_ERROR, "PlatCapsule: BlockList address failed alignment check\n"));
+ return 0;
+ }
+
+ if (Ptr->Length == 0) {
+ //
+ // Descriptor points to another list of block descriptors somewhere
+ // else.
+ //
+ Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Ptr->Union.ContinuationPointer;
+ } else {
+ //
+ // To enhance the reliability of check-up, the first capsule's header is checked here.
+ // More reliabilities check-up will do later.
+ //
+ if (CapsuleSize == 0) {
+ //
+ //Move to the first capsule to check its header.
+ //
+ CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Ptr->Union.DataBlock);
+ Found = (UINT8 *) CapsuleHeader;
+ Found -= FixedPcdGet32 (PcdFvSecurityHeaderSize);
+
+ if (IsCapsuleCorrupted (CapsuleHeader)) {
+ return 0;
+ }
+ Found = BuildCapsuleSecurityHeaderHob (Found);
+ DEBUG ((EFI_D_INFO, "PlatCapsule:SecHdrHob: 0x%08x\n", (UINTN) Found));
+ HobCnt += (Found != NULL) ? 1 : 0;
+
+ CapsuleCount ++;
+ CapsuleSize = CapsuleHeader->CapsuleImageSize;
+ }
+
+ if (CapsuleSize >= Ptr->Length) {
+ CapsuleSize = CapsuleSize - Ptr->Length;
+ } else {
+ CapsuleSize = 0;
+ }
+
+ //
+ // Move to next BLOCK descriptor.
+ //
+ Ptr++;
+ }
+ }
+
+ return HobCnt;
+}
+
+/**
+ Checks for the presence of capsule descriptors.
+ Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
+ and save to DescriptorBuffer.
+
+ @param DescriptorBuffer Pointer to the capsule descriptors
+
+ @retval EFI_SUCCESS a valid capsule is present
+ @retval EFI_NOT_FOUND if a valid capsule is not present
+**/
+STATIC
+EFI_STATUS
+GetCapsuleDescriptors (
+ IN EFI_PHYSICAL_ADDRESS *DescriptorBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINTN Index;
+ UINTN TempIndex;
+ UINTN ValidIndex;
+ BOOLEAN Flag;
+ CHAR16 CapsuleVarName[30];
+ CHAR16 *TempVarName;
+ EFI_PHYSICAL_ADDRESS CapsuleDataPtr64;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
+
+ Index = 0;
+ TempVarName = NULL;
+ CapsuleVarName[0] = 0;
+ ValidIndex = 0;
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PPIVariableServices
+ );
+ if (Status == EFI_SUCCESS) {
+ StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+ Size = sizeof (CapsuleDataPtr64);
+ while (TRUE) {
+ if (Index == 0) {
+ //
+ // For the first Capsule Image
+ //
+ Status = PPIVariableServices->GetVariable (
+ PPIVariableServices,
+ CapsuleVarName,
+ &gEfiCapsuleVendorGuid,
+ NULL,
+ &Size,
+ (VOID *) &CapsuleDataPtr64
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PlatCapsule: capsule variable not set (%r)\n", Status));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // We have a chicken/egg situation where the memory init code needs to
+ // know the boot mode prior to initializing memory. For this case, our
+ // validate function will fail. We can detect if this is the case if blocklist
+ // pointer is null. In that case, return success since we know that the
+ // variable is set.
+ //
+ if (DescriptorBuffer == NULL) {
+ return EFI_SUCCESS;
+ }
+ } else {
+ UnicodeValueToString (TempVarName, 0, Index, 0);
+ Status = PPIVariableServices->GetVariable (
+ PPIVariableServices,
+ CapsuleVarName,
+ &gEfiCapsuleVendorGuid,
+ NULL,
+ &Size,
+ (VOID *) &CapsuleDataPtr64
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // If this BlockList has been linked before, skip this variable
+ //
+ Flag = FALSE;
+ for (TempIndex = 0; TempIndex < ValidIndex; TempIndex++) {
+ if (DescriptorBuffer[TempIndex] == CapsuleDataPtr64) {
+ Flag = TRUE;
+ break;
+ }
+ }
+ if (Flag) {
+ Index ++;
+ continue;
+ }
+ }
+
+ //
+ // Cache BlockList which has been processed
+ //
+ DescriptorBuffer[ValidIndex++] = CapsuleDataPtr64;
+ Index ++;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Build capsule security header hob.
+
+ @param SecHdr Pointer to security header.
+
+ @retval NULL if failure to build HOB.
+ @return pointer to built hob.
+**/
+VOID *
+EFIAPI
+BuildCapsuleSecurityHeaderHob (
+ IN VOID *SecHdr
+ )
+{
+ QuarkSecurityHeader_t *SecHdrFields;
+
+ if (SecHdr != NULL) {
+ SecHdrFields = (QuarkSecurityHeader_t *) SecHdr;
+ if (SecHdrFields->CSH_Identifier == QUARK_CSH_IDENTIFIER) {
+ return BuildGuidDataHob(
+ &gEfiQuarkCapsuleSecurityHeaderGuid,
+ SecHdr,
+ FixedPcdGet32 (PcdFvSecurityHeaderSize)
+ );
+ }
+ }
+ return NULL;
+}
+
+/**
+ Find security headers using EFI_CAPSULE_VARIABLE_NAME variables and build Hobs.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @retval 0 if no security headers found.
+ @return number of security header hobs built.
+**/
+UINTN
+EFIAPI
+FindCapsuleSecurityHeadersAndBuildHobs (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ UINTN Index;
+ UINTN Size;
+ UINTN VariableCount;
+ CHAR16 CapsuleVarName[30];
+ CHAR16 *TempVarName;
+ EFI_PHYSICAL_ADDRESS CapsuleDataPtr64;
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
+ EFI_PHYSICAL_ADDRESS *VariableArrayAddress;
+ UINTN HobCnt;
+
+ HobCnt = 0;
+ Index = 0;
+ VariableCount = 0;
+ CapsuleVarName[0] = 0;
+
+ //
+ // Someone should have already ascertained the boot mode. If it's not
+ // capsule update, then return normally.
+ //
+ Status = PeiServicesGetBootMode (&BootMode);
+ if (EFI_ERROR (Status) || (BootMode != BOOT_ON_FLASH_UPDATE)) {
+ DEBUG ((EFI_D_ERROR, "PlatCapsule: Boot mode is not correct for finding capsule security header.\n"));
+ return 0;
+ }
+
+ //
+ // User may set the same ScatterGatherList with several different variables,
+ // so cache all ScatterGatherList for check later.
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PPIVariableServices
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Size = sizeof (CapsuleDataPtr64);
+ StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+ while (TRUE) {
+ if (Index > 0) {
+ UnicodeValueToString (TempVarName, 0, Index, 0);
+ }
+ Status = PPIVariableServices->GetVariable (
+ PPIVariableServices,
+ CapsuleVarName,
+ &gEfiCapsuleVendorGuid,
+ NULL,
+ &Size,
+ (VOID *) &CapsuleDataPtr64
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // There is no capsule variables, quit
+ //
+ break;
+ }
+ VariableCount++;
+ Index++;
+ }
+
+ //
+ // The last entry is the end flag.
+ //
+ Status = PeiServicesAllocatePool (
+ (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS),
+ (VOID **)&VariableArrayAddress
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem (VariableArrayAddress, (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS));
+
+ //
+ // Find out if we actually have a capsule.
+ // GetCapsuleDescriptors depends on variable PPI, so it should run in 32-bit environment.
+ //
+ Status = GetCapsuleDescriptors (VariableArrayAddress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PlatCapsule: Fail to find capsule variables.\n"));
+ } else {
+ //
+ // Run through desciptors looking for capsule security headers.
+ //
+
+ Index = 0;
+ while (VariableArrayAddress[Index] != 0) {
+ HobCnt += BuildSecurityHeaderHobs ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)VariableArrayAddress[Index]);
+ Index ++;
+ }
+ }
+
+ return HobCnt;
+}
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/Common/FlashMap.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/Common/FlashMap.c
new file mode 100755
index 0000000..43883f1
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/Common/FlashMap.c
@@ -0,0 +1,290 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ FlashMap.c
+
+Abstract:
+
+ Build GUIDed HOBs for platform specific flash map.
+
+--*/
+#include <FlashLayout.h>
+
+#include <Ppi/FlashMap.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+#include <Guid/FlashMapHob.h>
+#include <Guid/SystemNvDataGuid.h>
+#include <Guid/SystemNvDataHobGuid.h>
+#include <Guid/FirmwareFileSystem2.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PlatformHelperLib.h>
+
+EFI_STATUS
+EFIAPI
+GetAreaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_FLASH_MAP_PPI * This,
+ IN EFI_FLASH_AREA_TYPE AreaType,
+ IN EFI_GUID *AreaTypeGuid,
+ OUT UINT32 *NumEntries,
+ OUT EFI_FLASH_SUBAREA_ENTRY **Entries
+ );
+
+EFI_GUID mFvBlockGuid = EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID;
+
+EFI_GUID mFfsGuid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;
+
+EFI_GUID mSystemDataGuid = EFI_SYSTEM_NV_DATA_HOB_GUID;
+
+STATIC PEI_FLASH_MAP_PPI mFlashMapPpi = { GetAreaInfo };
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPpiListFlashMap = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiFlashMapPpiGuid,
+ &mFlashMapPpi
+};
+
+static EFI_FLASH_AREA_DATA mFlashAreaData[] = { EFI_FLASH_AREA_DATA_DEFINITION };
+
+#define NUM_FLASH_AREA_DATA (sizeof (mFlashAreaData) / sizeof (mFlashAreaData[0]))
+
+static EFI_HOB_FLASH_MAP_ENTRY_TYPE mFlashMapHobData[] = { EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION };
+
+#define NUM_HOB_FLASH_MAP_DATA (sizeof (mFlashMapHobData) / sizeof (mFlashMapHobData[0]))
+
+EFI_STATUS
+PeimInstallFlashMapPpi (
+ IN EFI_PEI_FILE_HANDLE *FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ //
+ // Install FlashMap PPI
+ //
+ Status = PeiServicesInstallPpi (&mPpiListFlashMap);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "Flash Map PEIM Loaded\n"));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PeimInitializeFlashMap (
+ IN EFI_PEI_FILE_HANDLE *FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+
+Routine Description:
+
+ Build GUID HOBs for platform specific flash map.
+
+Arguments:
+
+ FfsHeader Pointer this FFS file header.
+ PeiServices General purpose services available to every PEIM.
+
+Returns:
+
+ EFI_SUCCESS Guid HOBs for platform flash map is built.
+ Otherwise Failed to build the Guid HOB data.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_FLASH_AREA_HOB_DATA FlashHobData;
+ EFI_HOB_FLASH_MAP_ENTRY_TYPE *Hob;
+
+ //
+ // Build flash area entries as GUIDed HOBs.
+ //
+
+ for (Index = 0; Index < NUM_FLASH_AREA_DATA; Index++) {
+ SetMem (&FlashHobData, sizeof (EFI_FLASH_AREA_HOB_DATA), 0);
+
+ FlashHobData.AreaType = mFlashAreaData[Index].AreaType;
+ FlashHobData.NumberOfEntries = 1;
+ FlashHobData.SubAreaData.Attributes = mFlashAreaData[Index].Attributes;
+
+ //
+ // Default to table values, maybe overridden in following switch statement.
+ //
+ FlashHobData.SubAreaData.Base = (EFI_PHYSICAL_ADDRESS) (UINTN) mFlashAreaData[Index].Base;
+ FlashHobData.SubAreaData.Length = (EFI_PHYSICAL_ADDRESS) (UINTN) mFlashAreaData[Index].Length;
+
+ switch (FlashHobData.AreaType) {
+ case EFI_FLASH_AREA_RECOVERY_BIOS:
+ case EFI_FLASH_AREA_MAIN_BIOS:
+ if ((FlashHobData.AreaType == EFI_FLASH_AREA_RECOVERY_BIOS)) {
+ //
+ // Setup Stage1 which comes from Dynamic PCDs.
+ //
+ FlashHobData.SubAreaData.Base = (EFI_PHYSICAL_ADDRESS) FLASH_REGION_FV_SECPEI_NORMAL_BASE;
+ FlashHobData.SubAreaData.Length = (EFI_PHYSICAL_ADDRESS) FLASH_REGION_FV_SECPEI_NORMAL_SIZE;
+ } else {
+ //
+ // Setup FvMain which comes from Dynamic PCDs.
+ //
+ FlashHobData.SubAreaData.Base = (EFI_PHYSICAL_ADDRESS) FLASH_REGION_FVMAIN_BASE;
+ FlashHobData.SubAreaData.Length = (EFI_PHYSICAL_ADDRESS) FLASH_REGION_FVMAIN_SIZE;
+ }
+ if (PlatformIsBootWithRecoveryStage1 ()) {
+ DEBUG (
+ (DEBUG_INFO, "FlashMap - Do not create FV Hobs for FV:0x%08x since recovery boot.\n",
+ FlashHobData.SubAreaData.Base
+ ));
+ continue;
+ }
+
+ CopyMem (
+ &FlashHobData.AreaTypeGuid,
+ &mFfsGuid,
+ sizeof (EFI_GUID)
+ );
+ CopyMem (
+ &FlashHobData.SubAreaData.FileSystem,
+ &mFvBlockGuid,
+ sizeof (EFI_GUID)
+ );
+ break;
+
+ case EFI_FLASH_AREA_GUID_DEFINED:
+ CopyMem (
+ &FlashHobData.AreaTypeGuid,
+ &mSystemDataGuid,
+ sizeof (EFI_GUID)
+ );
+ CopyMem (
+ &FlashHobData.SubAreaData.FileSystem,
+ &mFvBlockGuid,
+ sizeof (EFI_GUID)
+ );
+ break;
+
+ default:
+ break;
+ }
+
+ Hob = BuildGuidDataHob (
+ &gEfiFlashMapHobGuid,
+ &FlashHobData,
+ sizeof (EFI_FLASH_AREA_HOB_DATA)
+ );
+ ASSERT (Hob);
+ }
+
+ for (Index = 0; Index < NUM_HOB_FLASH_MAP_DATA; Index++) {
+ Status = PeiServicesCreateHob (
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ (UINT16) (sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE)),
+ &Hob
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (
+ Hob,
+ &mFlashMapHobData[Index],
+ sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE)
+ );
+ if (mFlashMapHobData[Index].AreaType == EFI_FLASH_AREA_EFI_VARIABLES) {
+ Hob->Entries[0].Base = Hob->Entries[0].Base + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH;
+ Hob->Entries[0].Length = Hob->Entries[0].Length - EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetAreaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_FLASH_MAP_PPI * This,
+ IN EFI_FLASH_AREA_TYPE AreaType,
+ IN EFI_GUID *AreaTypeGuid,
+ OUT UINT32 *NumEntries,
+ OUT EFI_FLASH_SUBAREA_ENTRY **Entries
+ )
+/*++
+
+Routine Description:
+
+ Get data from the platform specific flash area map.
+
+Arguments:
+
+ PeiServices General purpose services available to every PEIM.
+ AreaType Flash map area type.
+ AreaTypeGuid Guid for the flash map area type.
+ NumEntries On return, filled with the number of sub-areas with the same type.
+ Entries On return, filled with entry pointer to the sub-areas.
+
+Returns:
+
+ EFI_SUCCESS The type of area exists in the flash map and data is returned.
+ EFI_NOT_FOUND The type of area does not exist in the flash map.
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_FLASH_MAP_ENTRY_TYPE *FlashMapEntry;
+
+ Hob.Raw = GetHobList ();
+ while (Hob.Raw != NULL) {
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, Hob.Raw);
+ if (CompareGuid (&Hob.Guid->Name, &gEfiFlashMapHobGuid)) {
+ FlashMapEntry = (EFI_HOB_FLASH_MAP_ENTRY_TYPE *) Hob.Raw;
+ ASSERT (FlashMapEntry != NULL);
+ if ((AreaType != FlashMapEntry->AreaType) ||
+ ((AreaType == EFI_FLASH_AREA_GUID_DEFINED) && !CompareGuid (AreaTypeGuid, &FlashMapEntry->AreaTypeGuid))
+ ) {
+ continue;
+ }
+
+ *NumEntries = FlashMapEntry->NumEntries;
+ *Entries = FlashMapEntry->Entries;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/CommonHeader.h b/QuarkPlatformPkg/Platform/Pei/PlatformInit/CommonHeader.h
new file mode 100644
index 0000000..31c4968
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/CommonHeader.h
@@ -0,0 +1,112 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+
+#include <FrameworkPei.h>
+#include <QuarkPlatformPeim.h>
+#include <IntelQNCPeim.h>
+#include "Ioh.h"
+#include <Platform.h>
+#include <PlatformBoards.h>
+
+#include <IndustryStandard/SmBus.h>
+#include <IndustryStandard/Pci22.h>
+
+#include <Guid/AcpiVariable.h>
+#include <Ppi/AtaController.h>
+#include <Guid/Capsule.h>
+#include <Ppi/SStateBootMode.h>
+#include <Ppi/Cache.h>
+#include <Ppi/MasterBootMode.h>
+#include <Guid/PlatformInfo.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/RecoveryDevice.h>
+#include <Guid/MemoryConfigData.h>
+#include <Guid/PlatformMemoryLayout.h>
+#include <Guid/MemoryOverwriteControl.h>
+#include <Guid/CapsuleVendor.h>
+#include <Guid/QuarkCapsuleGuid.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/FvLoadFile.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Ppi/DeviceRecoveryModule.h>
+#include <Ppi/Capsule.h>
+#include <Ppi/Reset.h>
+#include <Ppi/Stall.h>
+#include <Ppi/BootInRecoveryMode.h>
+#include <Guid/FirmwareFileSystem2.h>
+#include <Ppi/MemoryDiscovered.h>
+#include <Ppi/RecoveryModule.h>
+#include <Ppi/Smbus2.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Ppi/EndOfPeiPhase.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/PciCf8Lib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/PcdLib.h>
+#include <Library/SmbusLib.h>
+#include <Library/RecoveryOemHookLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/SwBpeLib.h>
+#include <Library/MfhLib.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformPcieHelperLib.h>
+#include <Library/PlatformDataLib.h>
+#include <Library/QuarkBootRomLib.h>
+#include <Library/RedirectPeiServicesLib.h>
+
+#include <Uefi/UefiBaseType.h>
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/Generic/Recovery.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/Generic/Recovery.c
new file mode 100755
index 0000000..edaa235
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/Generic/Recovery.c
@@ -0,0 +1,539 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Recovery.c
+
+Abstract:
+
+ Install Platform EFI_PEI_RECOVERY_MODULE_PPI and Implementation of
+ EFI_PEI_LOAD_RECOVERY_CAPSULE service.
+
+--*/
+
+#include "CommonHeader.h"
+#include "PlatformEarlyInit.h"
+
+#include <Ppi/BlockIo.h>
+
+//
+// Capsule Types supported in this platform module
+//
+#include <Guid/CapsuleOnFatFloppyDisk.h>
+#include <Guid/CapsuleOnFatIdeDisk.h>
+#include <Guid/CapsuleOnFatUsbDisk.h>
+#include <Guid/CapsuleOnDataCD.h>
+#include <Guid/QuarkCapsuleGuid.h>
+#include <Ppi/Cache.h>
+
+#include <Ppi/RecoveryModule.h>
+#include <Ppi/DeviceRecoveryModule.h>
+
+#include <Library/PeiServicesLib.h>
+
+//
+// Required Service
+//
+EFI_STATUS
+EFIAPI
+PlatformRecoveryModule (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_MODULE_PPI *This
+ );
+
+VOID
+AssertNoCapsulesError (
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+VOID
+AssertMediaDeviceError (
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+VOID
+ReportLoadCapsuleSuccess (
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+VOID
+CheckIfMediaPresentOnBlockIoDevice (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT BOOLEAN *MediaDeviceError,
+ IN OUT BOOLEAN *MediaPresent
+ );
+
+//
+// Module globals
+//
+STATIC EFI_PEI_RECOVERY_MODULE_PPI mRecoveryPpi = { PlatformRecoveryModule };
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mRecoveryPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiRecoveryModulePpiGuid,
+ &mRecoveryPpi
+};
+
+EFI_STATUS
+EFIAPI
+PeimInitializeRecovery (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+
+Routine Description:
+
+ Provide the functionality of the Recovery Module.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+
+Returns:
+
+ EFI_SUCCESS - If the interface could be successfully
+ installed.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesInstallPpi (&mRecoveryPpiList);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PlatformRecoveryModule (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_MODULE_PPI *This
+ )
+/*++
+
+Routine Description:
+
+ Provide the functionality of the Platform Recovery Module.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ This - Pointer to EFI_PEI_RECOVERY_MODULE_PPI.
+
+Returns:
+
+ EFI_SUCCESS - If the interface could be successfully
+ installed.
+ EFI_UNSUPPORTED - Not supported.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *DeviceRecoveryModule;
+ UINTN NumberOfImageProviders;
+ BOOLEAN ProviderAvailable;
+ UINTN NumberRecoveryCapsules;
+ UINTN RecoveryCapsuleSize;
+ EFI_GUID DeviceId;
+ BOOLEAN ImageFound;
+ EFI_PHYSICAL_ADDRESS Address;
+ VOID *Buffer;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_PEI_HOB_POINTERS HobOld;
+ BOOLEAN HobUpdate;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ UINTN Index;
+ EFI_STATUS AuthStatus;
+ VOID *CapsuleSecurityHeader;
+ EFI_GUID mEfiCapsuleHeaderGuid = QUARK_CAPSULE_GUID;
+
+ Index = 0;
+
+ Status = EFI_SUCCESS;
+ AuthStatus = EFI_SUCCESS;
+ CapsuleSecurityHeader = NULL;
+ HobUpdate = FALSE;
+
+ ProviderAvailable = TRUE;
+ ImageFound = FALSE;
+ NumberOfImageProviders = 0;
+
+ DeviceRecoveryModule = NULL;
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Entry\n"));
+
+ //
+ // Search the platform for some recovery capsule if the DXE IPL
+ // discovered a recovery condition and has requested a load.
+ //
+ while (ProviderAvailable) {
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiDeviceRecoveryModulePpiGuid,
+ Index,
+ NULL,
+ &DeviceRecoveryModule
+ );
+
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Device Recovery PPI located\n"));
+ NumberOfImageProviders++;
+
+ Status = DeviceRecoveryModule->GetNumberRecoveryCapsules (
+ PeiServices,
+ DeviceRecoveryModule,
+ &NumberRecoveryCapsules
+ );
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Number Of Recovery Capsules: %d\n", NumberRecoveryCapsules));
+
+ if (NumberRecoveryCapsules == 0) {
+ Index++;
+ } else {
+ break;
+ }
+ } else {
+ ProviderAvailable = FALSE;
+ }
+ }
+ //
+ // The number of recovery capsules is 0.
+ //
+ if (!ProviderAvailable) {
+ AssertNoCapsulesError (PeiServices);
+ }
+ //
+ // If there is an image provider, get the capsule ID
+ //
+ if (ProviderAvailable) {
+ RecoveryCapsuleSize = 0;
+ if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
+ Status = DeviceRecoveryModule->GetRecoveryCapsuleInfo (
+ PeiServices,
+ DeviceRecoveryModule,
+ 0,
+ &RecoveryCapsuleSize,
+ &DeviceId
+ );
+ } else {
+ Status = DeviceRecoveryModule->GetRecoveryCapsuleInfo (
+ PeiServices,
+ DeviceRecoveryModule,
+ 1,
+ &RecoveryCapsuleSize,
+ &DeviceId
+ );
+
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Capsule Size: %d\n", RecoveryCapsuleSize));
+
+ //
+ // Only support the 2 capsule types known
+ // Future enhancement is to rank-order the selection
+ //
+ if ((!CompareGuid (&DeviceId, &gPeiCapsuleOnFatIdeDiskGuid)) &&
+ (!CompareGuid (&DeviceId, &gPeiCapsuleOnDataCDGuid)) &&
+ (!CompareGuid (&DeviceId, &gPeiCapsuleOnFatUsbDiskGuid))
+ ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Buffer = NULL;
+ Address = (UINTN) AllocatePages ((RecoveryCapsuleSize - 1) / 0x1000 + 1);
+ ASSERT (Address);
+
+ Buffer = (UINT8 *) (UINTN) Address;
+ if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
+ Status = DeviceRecoveryModule->LoadRecoveryCapsule (
+ PeiServices,
+ DeviceRecoveryModule,
+ 0,
+ Buffer
+ );
+ } else {
+ Status = DeviceRecoveryModule->LoadRecoveryCapsule (
+ PeiServices,
+ DeviceRecoveryModule,
+ 1,
+ Buffer
+ );
+
+ }
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "LoadRecoveryCapsule Returns: %r\n", Status));
+
+ if (Status == EFI_DEVICE_ERROR) {
+ AssertMediaDeviceError (PeiServices);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ } else {
+ ReportLoadCapsuleSuccess (PeiServices);
+ }
+
+ //
+ // Update FV Hob if found
+ //
+ Buffer = (VOID *)((UINT8 *) Buffer + FixedPcdGet32 (PcdFvSecurityHeaderSize));
+ Status = PeiServicesGetHobList (&Hob.Raw);
+ HobOld.Raw = Hob.Raw;
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_FV) {
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Hob FV Length: %x\n", Hob.FirmwareVolume->Length));
+
+ if (Hob.FirmwareVolume->BaseAddress == (UINTN) PcdGet32 (PcdFlashFvMainBase)) {
+ HobUpdate = TRUE;
+ //
+ // This looks like the Hob we are interested in
+ //
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Hob Updated\n"));
+ Hob.FirmwareVolume->BaseAddress = (UINTN) Buffer;
+ Hob.FirmwareVolume->Length = RecoveryCapsuleSize;
+ }
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+ //
+ // Check if the top of the file is a firmware volume header
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;
+ CapsuleHeader = (EFI_CAPSULE_HEADER *) Buffer;
+ if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
+ //
+ // build FV Hob if it is not built before
+ //
+ if (!HobUpdate) {
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "FV Hob is not found, Build FV Hob then..\n"));
+ BuildFvHob (
+ (UINTN) Buffer,
+ FvHeader->FvLength
+ );
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Install FV Info PPI..\n"));
+
+ PeiServicesInstallFvInfoPpi (
+ NULL,
+ Buffer,
+ (UINT32) FvHeader->FvLength,
+ NULL,
+ NULL
+ );
+ }
+ //
+ // Point to the location immediately after the FV.
+ //
+ CapsuleHeader = (EFI_CAPSULE_HEADER *) ((UINT8 *) Buffer + FvHeader->FvLength + FixedPcdGet32 (PcdFvSecurityHeaderSize));
+ CapsuleSecurityHeader = ((UINT8 *) Buffer + FvHeader->FvLength);
+ }
+
+ //
+ // Check if pointer is still within the buffer
+ //
+ if ((UINTN) CapsuleHeader < (UINTN) ((UINT8 *) Buffer + RecoveryCapsuleSize)) {
+
+ //
+ // Check if it is a capsule
+ //
+ if (CompareGuid ((EFI_GUID *) CapsuleHeader, &mEfiCapsuleHeaderGuid)) {
+
+ CapsuleSecurityHeader = BuildCapsuleSecurityHeaderHob (
+ CapsuleSecurityHeader
+ );
+ DEBUG (
+ (EFI_D_INFO,
+ "Recovery:SecHdrHob: 0x%08x\n",
+ (UINTN) CapsuleSecurityHeader
+ ));
+
+ //
+ // Set bootmode to capsule update so the capsule hob gets the right bootmode in the hob header.
+ //
+ Status = (**PeiServices).SetBootMode (PeiServices, BOOT_ON_FLASH_UPDATE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Build capsule hob
+ //
+ BuildCvHob ((EFI_PHYSICAL_ADDRESS)CapsuleHeader, (UINT64)(EFI_CAPSULE_HEADER *)CapsuleHeader->CapsuleImageSize);
+ }
+ }
+ }
+
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Module Returning: %r\n", Status));
+ return Status;
+}
+
+/*
+ AssertNoCapsulesError:
+ There were no recovery capsules found.
+ Case 1: Report the error that no recovery block io device/media is readable and assert.
+ Case 2: Report the error that there is no media present on any recovery block io device and assert.
+ Case 3: There is media present on some recovery block io device,
+ but there is no recovery capsule on it. Report the error and assert.
+*/
+VOID
+AssertNoCapsulesError (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ BOOLEAN MediaDeviceError;
+ BOOLEAN MediaPresent;
+
+ MediaDeviceError = TRUE;
+ MediaPresent = FALSE;
+
+ CheckIfMediaPresentOnBlockIoDevice (PeiServices, &MediaDeviceError, &MediaPresent);
+/* if (MediaDeviceError) {
+ ReportStatusCode (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ (EFI_PERIPHERAL_RECOVERY_MEDIA | EFI_P_EC_MEDIA_DEVICE_ERROR)
+ );
+
+ } else if (!MediaPresent) {
+ ReportStatusCode (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ (EFI_PERIPHERAL_RECOVERY_MEDIA | EFI_P_EC_MEDIA_NOT_PRESENT)
+ );
+
+ } else {
+ ReportStatusCode (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_EC_NO_RECOVERY_CAPSULE)
+ );
+ }*/
+ //
+ // Hang.
+ //
+ CpuDeadLoop();
+}
+
+#define MAX_BLOCK_IO_PPI 32
+
+/*
+ CheckIfMediaPresentOnBlockIoDevice:
+ Checks to see whether there was a media device error or to see if there is media present.
+*/
+VOID
+CheckIfMediaPresentOnBlockIoDevice (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT BOOLEAN *MediaDeviceError,
+ IN OUT BOOLEAN *MediaPresent
+ )
+{
+ EFI_STATUS Status;
+ UINTN BlockIoPpiInstance;
+ EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;
+ UINTN NumberBlockDevices;
+ EFI_PEI_BLOCK_IO_MEDIA Media;
+
+ *MediaDeviceError = TRUE;
+ *MediaPresent = FALSE;
+
+ for (BlockIoPpiInstance = 0; BlockIoPpiInstance < MAX_BLOCK_IO_PPI; BlockIoPpiInstance++) {
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiVirtualBlockIoPpiGuid,
+ BlockIoPpiInstance,
+ NULL,
+ &BlockIoPpi
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Done with all Block Io Ppis
+ //
+ break;
+ }
+
+ Status = BlockIoPpi->GetNumberOfBlockDevices (
+ PeiServices,
+ BlockIoPpi,
+ &NumberBlockDevices
+ );
+ if (EFI_ERROR (Status) || (NumberBlockDevices == 0)) {
+ continue;
+ }
+ //
+ // Just retrieve the first block
+ //
+ Status = BlockIoPpi->GetBlockDeviceMediaInfo (
+ PeiServices,
+ BlockIoPpi,
+ 0,
+ &Media
+ );
+ if (!EFI_ERROR (Status)) {
+ *MediaDeviceError = FALSE;
+ if (Media.MediaPresent) {
+ *MediaPresent = TRUE;
+ break;
+ }
+ }
+ }
+}
+
+VOID
+AssertMediaDeviceError (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+/* ReportStatusCode (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ (EFI_PERIPHERAL_RECOVERY_MEDIA | EFI_P_EC_MEDIA_DEVICE_ERROR)
+ );
+*/
+ CpuDeadLoop ();
+}
+
+VOID
+ReportLoadCapsuleSuccess (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ //
+ // EFI_SW_PEI_PC_CAPSULE_START: (from the status code spec):
+ // Loaded the recovery capsule. About to hand off control to the capsule.
+ //
+/* ReportStatusCode (
+ EFI_PROGRESS_CODE,
+ (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_CAPSULE_LOAD_SUCCESS)
+ );*/
+}
+
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
new file mode 100755
index 0000000..9b56419
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
@@ -0,0 +1,319 @@
+/** @file
+ This file includes a memory call back function notified when MRC is done,
+ following action is performed in this file,
+ 1. ICH initialization after MRC.
+ 2. SIO initialization.
+ 3. Install ResetSystem and FinvFv PPI.
+ 4. Set MTRR for PEI
+ 5. Create FV HOB and Flash HOB
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "CommonHeader.h"
+
+#include "PlatformEarlyInit.h"
+#include <Cpu/CpuRegs.h>
+
+extern EFI_PEI_PPI_DESCRIPTOR mPpiStall[];
+
+STATIC EFI_PEI_RESET_PPI mResetPpi = { ResetSystem };
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPpiList[1] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiResetPpiGuid,
+ &mResetPpi
+ }
+};
+
+//
+// RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE
+// Workaround to make default SMRAM UnCachable
+//
+MTRR_FIXED_SETTINGS mFixedMtrrTable = {
+ 0x0606060600060606,
+ 0x0606060606060606,
+ 0,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000
+ };
+
+/**
+ This function reset the entire platform, including all processor and devices, and
+ reboots the system.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+ResetSystem (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ ResetCold();
+ return EFI_SUCCESS;
+}
+
+/**
+ This function provides a blocking stall for reset at least the given number of microseconds
+ stipulated in the final argument.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @param this Pointer to the local data for the interface.
+
+ @param Microseconds number of microseconds for which to stall.
+
+ @retval EFI_SUCCESS the function provided at least the required stall.
+**/
+EFI_STATUS
+EFIAPI
+Stall (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_STALL_PPI *This,
+ IN UINTN Microseconds
+ )
+{
+ MicroSecondDelay (Microseconds);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function will be called when MRC is done.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @param NotifyDescriptor Information about the notify event..
+
+ @param Ppi The notify context.
+
+ @retval EFI_SUCCESS If the function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+MemoryDiscoveredPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ UINT64 MemoryLength;
+ UINT64 MemoryLengthUc;
+ UINT64 MaxMemoryLength;
+ UINT64 MemOverflow;
+ EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
+ UINTN NumSmramRegions;
+ UINT64 EnlargedMemoryLength;
+ UINT32 RmuMainBaseAddress;
+ UINTN Index;
+ MTRR_SETTINGS MtrrSetting;
+ UINT32 RegData32;
+ EFI_PHYSICAL_ADDRESS NewBuffer;
+ UINT8 CpuAddressWidth;
+ EFI_CPUID_REGISTER FeatureInfo;
+
+ DEBUG ((EFI_D_INFO, "Platform PEIM Memory Callback\n"));
+
+ NumSmramRegions = 0;
+ SmramDescriptor = NULL;
+ RmuMainBaseAddress = 0;
+
+ PERF_START (NULL, "SetCache", NULL, 0);
+
+ InfoPostInstallMemory (&RmuMainBaseAddress, &SmramDescriptor, &NumSmramRegions);
+ ASSERT (SmramDescriptor != NULL);
+ ASSERT (RmuMainBaseAddress != 0);
+
+ MemoryLength = ((UINT64) RmuMainBaseAddress) + 0x10000;
+ EnlargedMemoryLength = MemoryLength;
+
+ if (NumSmramRegions > 0) {
+ //
+ // Find the TSEG
+ //
+ for (Index = 0; Index < NumSmramRegions; Index ++) {
+ if ((SmramDescriptor[Index].PhysicalStart) == EnlargedMemoryLength) {
+ if (SmramDescriptor[Index].RegionState & EFI_CACHEABLE) {
+ //
+ // Enlarge memory length to include TSEG size
+ //
+ EnlargedMemoryLength += (SmramDescriptor[Index].PhysicalSize);
+ }
+ }
+ }
+ }
+
+ //
+ // Check if a UC region is present
+ //
+ MaxMemoryLength = EnlargedMemoryLength;
+ // Round up to nearest 256MB
+ MemOverflow = (MemoryLength & 0x0fffffff);
+ if (MemOverflow != 0) {
+ MaxMemoryLength = MemoryLength + (0x10000000 - MemOverflow);
+ }
+
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS));
+ (**PeiServices).CopyMem ((VOID *)&MtrrSetting.Fixed,(VOID *)&mFixedMtrrTable, sizeof(MTRR_FIXED_SETTINGS) );
+ //
+ // Cache the flash area to improve the boot performance in PEI phase
+ //
+ MtrrSetting.Variables.Mtrr[0].Base = (QUARK_BOOTROM_BASE_ADDRESS | CacheWriteBack);
+ MtrrSetting.Variables.Mtrr[0].Mask = (((~(QUARK_BOOTROM_SIZE_BYTES - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED);
+
+ MtrrSetting.Variables.Mtrr[1].Base = CacheWriteBack;
+ MtrrSetting.Variables.Mtrr[1].Mask = ((~(MaxMemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED;
+
+ Index = 2;
+ while (MaxMemoryLength != MemoryLength) {
+ MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength);
+
+ //Status = MtrrSetMemoryAttribute (MaxMemoryLength - MemoryLengthUc, MemoryLengthUc, CacheUncacheable);
+ //ASSERT_EFI_ERROR (Status);
+
+ MtrrSetting.Variables.Mtrr[Index].Base = ((MaxMemoryLength - MemoryLengthUc) & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheUncacheable;
+ MtrrSetting.Variables.Mtrr[Index].Mask= ((~(MemoryLengthUc - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED;
+ MaxMemoryLength -= MemoryLengthUc;
+ Index++;
+ }
+
+ AsmInvd ();
+
+ MtrrSetting.MtrrDefType = MTRR_LIB_CACHE_MTRR_ENABLED | MTRR_LIB_CACHE_FIXED_MTRR_ENABLED;
+ MtrrSetAllMtrrs(&MtrrSetting);
+
+ PERF_END (NULL, "SetCache", NULL, 0);
+
+ //
+ // Install PeiReset for PeiResetSystem service
+ //
+ Status = PeiServicesInstallPpi (&mPpiList[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Do QNC initialization after MRC
+ //
+ PeiQNCPostMemInit ();
+
+ Status = PeiServicesInstallPpi (&mPpiStall[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set E000/F000 Routing
+ //
+ RegData32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ RegData32 |= (BIT2|BIT1);
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32);
+
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ PeiServicesInstallFvInfoPpi (
+ NULL,
+ (VOID *) (UINTN) PcdGet32 (PcdFlashFvRecovery2Base),
+ PcdGet32 (PcdFlashFvRecovery2Size),
+ NULL,
+ NULL
+ );
+ Status = PeimInitializeRecovery (PeiServices);
+ ASSERT_EFI_ERROR (Status);
+
+ } else if (BootMode == BOOT_ON_S3_RESUME) {
+ return EFI_SUCCESS;
+
+ } else {
+ //
+ // Allocate the memory so that it gets preserved into DXE
+ //
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (PcdGet32 (PcdFvSecurityHeaderSize) + PcdGet32 (PcdFlashFvMainSize)),
+ &NewBuffer
+ );
+
+ //
+ // Copy the compressed main Firmware Volume to memory for faster processing later
+ //
+ CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) (PcdGet32 (PcdFlashFvMainBase) - PcdGet32 (PcdFvSecurityHeaderSize)), (PcdGet32 (PcdFvSecurityHeaderSize) +PcdGet32 (PcdFlashFvMainSize)));
+
+ PeiServicesInstallFvInfoPpi (
+ NULL,
+ (VOID *) (UINTN) (NewBuffer + PcdGet32 (PcdFvSecurityHeaderSize)),
+ PcdGet32 (PcdFlashFvMainSize),
+ NULL,
+ NULL
+ );
+ }
+
+ //
+ // Build flash HOB, it's going to be used by GCD and E820 building
+ // Map full SPI flash decode range (regardless of smaller SPI flash parts installed)
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_FIRMWARE_DEVICE,
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+ (SIZE_4GB - SIZE_8MB),
+ SIZE_8MB
+ );
+
+ //
+ // Create a CPU hand-off information
+ //
+ CpuAddressWidth = 32;
+ AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &FeatureInfo.RegEax, NULL, NULL, NULL);
+ if (FeatureInfo.RegEax >= EFI_CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (EFI_CPUID_VIR_PHY_ADDRESS_SIZE, &FeatureInfo.RegEax, NULL, NULL, NULL);
+ CpuAddressWidth = (UINT8) (FeatureInfo.RegEax & 0xFF);
+ }
+ DEBUG ((EFI_D_INFO, "CpuAddressWidth: %d\n", CpuAddressWidth));
+
+ BuildCpuHob (CpuAddressWidth, 16);
+
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c
new file mode 100755
index 0000000..0c25942
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c
@@ -0,0 +1,1845 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ MrcWrapper.c
+
+Abstract:
+
+ Framework PEIM to initialize memory on a Quark Memory Controller.
+
+
+--*/
+
+
+#include "CommonHeader.h"
+#include "MrcWrapper.h"
+#include "IioUniversalData.h"
+#include <Ioh.h>
+#include "Platform.h"
+#include <CpuRegs.h>
+
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformDataLib.h>
+
+//
+// ------------------------ TSEG Base
+// ...............
+// ------------------------ RESERVED_CPU_S3_SAVE_OFFSET
+// CPU S3 data
+// ------------------------ RESERVED_ACPI_S3_RANGE_OFFSET
+// S3 Memory base structure
+// ------------------------ TSEG + 1 page
+
+#define RESERVED_CPU_S3_SAVE_OFFSET (RESERVED_ACPI_S3_RANGE_OFFSET - sizeof (SMM_S3_RESUME_STATE))
+
+// Strap configuration register specifying DDR setup
+#define QUARK_SCSS_REG_STPDDRCFG 0x00
+
+// Macro counting array elements
+#define COUNT(a) (sizeof(a)/sizeof(*a))
+
+
+EFI_MEMORY_TYPE_INFORMATION mDefaultCltMemoryTypeInformation[] = {
+ { EfiReservedMemoryType, EDKII_RESERVED_SIZE_PAGES }, // BIOS Reserved
+ { EfiACPIMemoryNVS, ACPI_NVS_SIZE_PAGES }, // S3, SMM, etc
+ { EfiRuntimeServicesData, RUNTIME_SERVICES_DATA_SIZE_PAGES },
+ { EfiRuntimeServicesCode, RUNTIME_SERVICES_CODE_SIZE_PAGES },
+ { EfiACPIReclaimMemory, ACPI_RECLAIM_SIZE_PAGES }, // ACPI ASL
+ { EfiMaxMemoryType, 0 }
+};
+
+/**
+ Read south cluster GPIO input from Port A
+
+**/
+static UINT32
+ScGpioRead(
+ VOID
+ )
+{
+ UINT32 GipMmioBase = 0xC1000000;
+ UINT32 GipData;
+ UINT32 GipAddr;
+ UINT8 Cmd;
+
+ GipAddr = PCI_LIB_ADDRESS(
+ IOH_I2C_GPIO_BUS_NUMBER,
+ IOH_I2C_GPIO_DEVICE_NUMBER,
+ IOH_I2C_GPIO_FUNCTION_NUMBER, 0);
+
+ Cmd = PciRead8 ( GipAddr + PCI_COMMAND_OFFSET);
+
+ if( Cmd & EFI_PCI_COMMAND_MEMORY_SPACE) {
+ // Someone already enabled mmio decoding
+ GipMmioBase = PciRead32 ( GipAddr + PCI_BASE_ADDRESSREG_OFFSET);
+
+ // Interested in address bits only
+ GipMmioBase &= 0xFFFFFF00;
+ DEBUG ((EFI_D_INFO, "SC GPIO already enabled at %08X\n", GipMmioBase));
+
+ // Assume default configuration all input
+ GipData = MmioRead32( GipMmioBase + GPIO_EXT_PORTA);
+ }
+ else {
+ DEBUG ((EFI_D_INFO, "SC GPIO temporary enable at %08X\n", GipMmioBase));
+
+ // Use predefined tempory memory resource
+ PciWrite32 ( GipAddr + PCI_BASE_ADDRESSREG_OFFSET, GipMmioBase);
+ PciWrite8 ( GipAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ // Assume default configuration all input
+ GipData = MmioRead32( GipMmioBase + GPIO_EXT_PORTA);
+
+ // Disable mmio decoding
+ PciWrite8 ( GipAddr + PCI_COMMAND_OFFSET, 0);
+ }
+
+ // Only 20 bits valid
+ return GipData & 0x000FFFFF;
+}
+
+
+/**
+ Configure Uart mmio base for MRC serial log purpose
+
+ @param MrcData - MRC configuration data updated
+
+**/
+static VOID
+MrcUartConfig(
+ MRC_PARAMS *MrcData
+ )
+{
+ UINT8 UartIdx;
+ UINT32 RegData32;
+ UINT8 IohUartBus;
+ UINT8 IohUartDev;
+
+ UartIdx = PcdGet8(PcdIohUartFunctionNumber);
+ IohUartBus = PcdGet8(PcdIohUartBusNumber);
+ IohUartDev = PcdGet8(PcdIohUartDevNumber);
+
+ RegData32 = PciRead32 (PCI_LIB_ADDRESS(IohUartBus, IohUartDev, UartIdx, PCI_BASE_ADDRESSREG_OFFSET));
+ MrcData->uart_mmio_base = RegData32 & 0xFFFFFFF0;
+}
+
+/**
+ Configure MRC from memory controller fuse settings.
+
+ @param MrcData - MRC configuration data to be updated.
+
+ @return EFI_SUCCESS MRC Config parameters updated from platform data.
+**/
+static
+EFI_STATUS
+MrcConfigureFromMcFuses (
+ OUT MRC_PARAMS *MrcData
+ )
+{
+ UINT32 McFuseStat;
+
+ McFuseStat = QNCPortRead (
+ QUARK_NC_MEMORY_CONTROLLER_SB_PORT_ID,
+ QUARK_NC_MEMORY_CONTROLLER_REG_DFUSESTAT
+ );
+
+ DEBUG ((EFI_D_INFO, "MRC McFuseStat 0x%08x\n", McFuseStat));
+
+ if ((McFuseStat & B_DFUSESTAT_ECC_DIS) != 0) {
+ DEBUG ((EFI_D_INFO, "MRC Fuse : fus_dun_ecc_dis.\n"));
+ MrcData->ecc_enables = 0;
+ } else {
+ MrcData->ecc_enables = 1;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Configure MRC from platform info hob.
+
+ @param MrcData - MRC configuration data to be updated.
+
+ @return EFI_SUCCESS MRC Config parameters updated from hob.
+ @return EFI_NOT_FOUND Platform Info or MRC Config parameters not found.
+ @return EFI_INVALID_PARAMETER Wrong params in hob.
+**/
+static
+EFI_STATUS
+MrcConfigureFromInfoHob (
+ OUT MRC_PARAMS *MrcData
+ )
+{
+ PDAT_MRC_ITEM *ItemData;
+ EFI_PLATFORM_INFO *PlatformInfo;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
+ PlatformInfo = GET_GUID_HOB_DATA (GuidHob);
+ if (PlatformInfo == NULL) {
+ DEBUG ((EFI_D_ERROR, "MrcWapper: PlatformInfo Not found.!!!!!\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ ItemData = &PlatformInfo->MemData.MemMrcConfig;
+
+ MrcData->channel_enables = ItemData->ChanMask;
+ MrcData->channel_width = ItemData->ChanWidth;
+ MrcData->address_mode = ItemData->AddrMode;
+ // Enable scrambling if requested.
+ MrcData->scrambling_enables = (ItemData->Flags & PDAT_MRC_FLAG_SCRAMBLE_EN) != 0;
+ MrcData->ddr_type = ItemData->DramType;
+ MrcData->dram_width = ItemData->DramWidth;
+ MrcData->ddr_speed = ItemData->DramSpeed;
+ // Enable ECC if requested.
+ MrcData->rank_enables = ItemData->RankMask;
+ MrcData->params.DENSITY = ItemData->DramDensity;
+ MrcData->params.tCL = ItemData->tCL;
+ MrcData->params.tRAS = ItemData->tRAS;
+ MrcData->params.tWTR = ItemData->tWTR;
+ MrcData->params.tRRD = ItemData->tRRD;
+ MrcData->params.tFAW = ItemData->tFAW;
+
+ MrcData->refresh_rate = ItemData->SrInt;
+ MrcData->sr_temp_range = ItemData->SrTemp;
+ MrcData->ron_value = ItemData->DramRonVal;
+ MrcData->rtt_nom_value = ItemData->DramRttNomVal;
+ MrcData->rd_odt_value = ItemData->SocRdOdtVal;
+
+ DEBUG ((EFI_D_INFO, "MRC dram_width %d\n", MrcData->dram_width));
+ DEBUG ((EFI_D_INFO, "MRC rank_enables %d\n",MrcData->rank_enables));
+ DEBUG ((EFI_D_INFO, "MRC ddr_speed %d\n", MrcData->ddr_speed));
+ DEBUG ((EFI_D_INFO, "MRC flags: %s\n",
+ (MrcData->scrambling_enables) ? L"SCRAMBLE_EN" : L""
+ ));
+
+ DEBUG ((EFI_D_INFO, "MRC density=%d tCL=%d tRAS=%d tWTR=%d tRRD=%d tFAW=%d\n",
+ MrcData->params.DENSITY,
+ MrcData->params.tCL,
+ MrcData->params.tRAS,
+ MrcData->params.tWTR,
+ MrcData->params.tRRD,
+ MrcData->params.tFAW
+ ));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Configure ECC scrub
+
+ @param MrcData - MRC configuration
+
+**/
+static VOID
+EccScrubSetup(
+ const MRC_PARAMS *MrcData
+ )
+{
+ UINT32 BgnAdr = 0;
+ UINT32 EndAdr = MrcData->mem_size;
+ UINT32 BlkSize = PcdGet8(PcdEccScrubBlkSize) & SCRUB_CFG_BLOCKSIZE_MASK;
+ UINT32 Interval = PcdGet8(PcdEccScrubInterval) & SCRUB_CFG_INTERVAL_MASK;
+
+ if( MrcData->ecc_enables == 0 || MrcData->boot_mode == bmS3 || Interval == 0) {
+ // No scrub configuration needed if ECC not enabled
+ // On S3 resume reconfiguration is done as part of resume
+ // script, see SNCS3Save.c ==> SaveRuntimeScriptTable()
+ // Also if PCD disables scrub, then we do nothing.
+ return;
+ }
+
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_END_MEM_REG, EndAdr);
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_START_MEM_REG, BgnAdr);
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_NEXT_READ_REG, BgnAdr);
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG,
+ Interval << SCRUB_CFG_INTERVAL_SHIFT |
+ BlkSize << SCRUB_CFG_BLOCKSIZE_SHIFT);
+
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = SCRUB_RESUME_MSG();
+}
+
+/** Post InstallS3Memory / InstallEfiMemory tasks given MrcData context.
+
+ @param[in] MrcData MRC configuration.
+ @param[in] IsS3 TRUE if after InstallS3Memory.
+
+**/
+STATIC
+VOID
+PostInstallMemory (
+ IN MRC_PARAMS *MrcData,
+ IN BOOLEAN IsS3
+ )
+{
+ UINT32 RmuMainDestBaseAddress;
+ UINT32 *RmuMainSrcBaseAddress;
+ UINTN RmuMainSize;
+ EFI_STATUS Status;
+
+ //
+ // Setup ECC policy (All boot modes).
+ //
+ QNCPolicyDblEccBitErr (V_WDT_CONTROL_DBL_ECC_BIT_ERR_WARM);
+
+ //
+ // Find the 64KB of memory for Rmu Main at the top of available memory.
+ //
+ InfoPostInstallMemory (&RmuMainDestBaseAddress, NULL, NULL);
+ DEBUG ((EFI_D_INFO, "RmuMain Base Address : 0x%x\n", RmuMainDestBaseAddress));
+
+ //
+ // Relocate RmuMain.
+ //
+ if (IsS3) {
+ QNCSendOpcodeDramReady (RmuMainDestBaseAddress);
+ } else {
+ Status = PlatformFindFvFileRawDataSection (NULL, PcdGetPtr(PcdQuarkMicrocodeFile), (VOID **) &RmuMainSrcBaseAddress, &RmuMainSize);
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Found Microcode ADDR:SIZE 0x%08x:0x%04x\n", (UINTN) RmuMainSrcBaseAddress, RmuMainSize));
+ }
+
+ RmuMainRelocation (RmuMainDestBaseAddress, (UINT32) RmuMainSrcBaseAddress, RmuMainSize);
+ QNCSendOpcodeDramReady (RmuMainDestBaseAddress);
+ EccScrubSetup (MrcData);
+ }
+}
+
+/**
+
+ Do memory initialisation for QNC DDR3 SDRAM Controller
+
+ @param FfsHeader Not used.
+ @param PeiServices General purpose services available to every PEIM.
+
+ @return EFI_SUCCESS Memory initialisation completed successfully.
+ All other error conditions encountered result in an ASSERT.
+
+**/
+EFI_STATUS
+MemoryInit (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ MRC_PARAMS MrcData;
+ EFI_BOOT_MODE BootMode;
+ EFI_STATUS Status;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
+ EFI_STATUS_CODE_VALUE ErrorCodeValue;
+ PEI_CLT_MEMORY_INIT_PPI *CltMemoryInitPpi;
+ UINT16 PmswAdr;
+
+ ErrorCodeValue = 0;
+
+ //
+ // It is critical that both of these data structures are initialized to 0.
+ // This PEIM knows the number of DIMMs in the system and works with that
+ // information. The MCH PEIM that consumes these data structures does not
+ // know the number of DIMMs so it expects the entire structure to be
+ // properly initialized. By initializing these to zero, all flags indicating
+ // that the SPD is present or the row should be configured are set to false.
+ //
+ ZeroMem (&MrcData, sizeof(MrcData));
+
+ //
+ // Get necessary PPI
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid, // GUID
+ 0, // INSTANCE
+ NULL, // EFI_PEI_PPI_DESCRIPTOR
+ (VOID **)&VariableServices // PPI
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Determine boot mode
+ //
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Error type for reporting status code
+ //
+ switch (BootMode) {
+ case BOOT_ON_FLASH_UPDATE:
+ ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY + EFI_CU_MEMORY_EC_UPDATE_FAIL;
+ break;
+ case BOOT_ON_S3_RESUME:
+ ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY + EFI_CU_MEMORY_EC_S3_RESUME_FAIL;
+ break;
+ default:
+ ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY;
+ break;
+ }
+
+ //
+ // Specify MRC boot mode
+ //
+ switch (BootMode) {
+ case BOOT_ON_S3_RESUME:
+ case BOOT_ON_FLASH_UPDATE:
+ MrcData.boot_mode = bmS3;
+ break;
+ case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+ MrcData.boot_mode = bmFast;
+ break;
+ default:
+ MrcData.boot_mode = bmCold;
+ break;
+ }
+
+ //
+ // Configure MRC input parameters.
+ //
+ Status = MrcConfigureFromMcFuses (&MrcData);
+ ASSERT_EFI_ERROR (Status);
+ Status = MrcConfigureFromInfoHob (&MrcData);
+ ASSERT_EFI_ERROR (Status);
+ MrcUartConfig(&MrcData);
+
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ //
+ // Always do bmCold on recovery.
+ //
+ DEBUG ((DEBUG_INFO, "MemoryInit:Force bmCold on Recovery\n"));
+ MrcData.boot_mode = bmCold;
+ } else {
+
+ //
+ // Load Memory configuration data saved in previous boot from variable
+ //
+ Status = LoadConfig (
+ PeiServices,
+ VariableServices,
+ &MrcData
+ );
+
+ if (EFI_ERROR (Status)) {
+
+ switch (BootMode) {
+ case BOOT_ON_S3_RESUME:
+ case BOOT_ON_FLASH_UPDATE:
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE + EFI_ERROR_UNRECOVERED,
+ ErrorCodeValue
+ );
+ PeiServicesResetSystem ();
+ break;
+
+ default:
+ MrcData.boot_mode = bmCold;
+ break;
+ }
+ }
+ }
+
+ //
+ // Locate Memory Reference Code PPI
+ //
+ Status = PeiServicesLocatePpi (
+ &gCltMemoryInitPpiGuid, // GUID
+ 0, // INSTANCE
+ NULL, // EFI_PEI_PPI_DESCRIPTOR
+ (VOID **)&CltMemoryInitPpi // PPI
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PmswAdr = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_PMSW;
+ if( IoRead32 (PmswAdr) & B_QNC_GPE0BLK_PMSW_DRAM_INIT) {
+ // MRC did not complete last execution, force cold boot path
+ MrcData.boot_mode = bmCold;
+ }
+
+ // Mark MRC pending
+ IoOr32 (PmswAdr, (UINT32)B_QNC_GPE0BLK_PMSW_DRAM_INIT);
+
+ //
+ // Call Memory Reference Code's Routines
+ //
+ CltMemoryInitPpi->MrcStart (&MrcData);
+
+ // Mark MRC completed
+ IoAnd32 (PmswAdr, ~(UINT32)B_QNC_GPE0BLK_PMSW_DRAM_INIT);
+
+
+ //
+ // Note emulation platform has to read actual memory size
+ // MrcData.mem_size from PcdGet32 (PcdMemorySize);
+
+ if (BootMode == BOOT_ON_S3_RESUME) {
+
+ DEBUG ((EFI_D_INFO, "Following BOOT_ON_S3_RESUME boot path.\n"));
+
+ Status = InstallS3Memory (PeiServices, VariableServices, MrcData.mem_size);
+ if (EFI_ERROR (Status)) {
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE + EFI_ERROR_UNRECOVERED,
+ ErrorCodeValue
+ );
+ PeiServicesResetSystem ();
+ }
+ PostInstallMemory (&MrcData, TRUE);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Assign physical memory to PEI and DXE
+ //
+ DEBUG ((EFI_D_INFO, "InstallEfiMemory.\n"));
+
+ Status = InstallEfiMemory (
+ PeiServices,
+ VariableServices,
+ BootMode,
+ MrcData.mem_size
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PostInstallMemory (&MrcData, FALSE);
+
+ //
+ // Save current configuration into Hob and will save into Variable later in DXE
+ //
+ DEBUG ((EFI_D_INFO, "SaveConfig.\n"));
+ Status = SaveConfig (
+ &MrcData
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "MemoryInit Complete.\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function saves a config to a HOB.
+
+ @param RowInfo The MCH row configuration information.
+ @param TimingData Timing data to be saved.
+ @param RowConfArray Row configuration information for each row in the system.
+ @param SpdData SPD info read for each DIMM slot in the system.
+
+ @return EFI_SUCCESS: The function completed successfully.
+
+**/
+EFI_STATUS
+SaveConfig (
+ IN MRC_PARAMS *MrcData
+ )
+{
+ IIO_UDS IioUds; // Module Universal Data Store!
+ EFI_GUID UniversalDataGuid = IIO_UNIVERSAL_DATA_GUID;
+ EFI_PLATFORM_INFO *PlatformInfo;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UINT8 Ctr1;
+ UINT8 CpuAddressWidth;
+ EFI_CPUID_REGISTER FeatureInfo;
+
+ // Build HOB data for Memory Config
+ // HOB data size (stored in variable) is required to be multiple of 8bytes
+ BuildGuidDataHob (
+ &gEfiMemoryConfigDataGuid,
+ (VOID *) &MrcData->timings,
+ ((sizeof (MrcData->timings) + 0x7) & (~0x7))
+ );
+
+ //
+ // Update the platform info hob with system PCI resource info
+ //
+ GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
+ PlatformInfo = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (PlatformInfo);
+
+ // Update PlatformInfo
+ PlatformInfo->PciData.PciResourceIoBase = (PcdGet16(PcdPciHostBridgeIoBase));
+ PlatformInfo->PciData.PciResourceIoLimit = PlatformInfo->PciData.PciResourceIoBase + (PcdGet16(PcdPciHostBridgeIoSize) - 1);
+ PlatformInfo->PciData.PciResourceMem32Base = (PcdGet32(PcdPciHostBridgeMemory32Base));
+ PlatformInfo->PciData.PciResourceMem32Limit = PlatformInfo->PciData.PciResourceMem32Base + (PcdGet32(PcdPciHostBridgeMemory32Size) - 1);
+ PlatformInfo->PciData.PciResourceMem64Base = (PcdGet64(PcdPciHostBridgeMemory64Base));
+ PlatformInfo->PciData.PciResourceMem64Limit = PlatformInfo->PciData.PciResourceMem64Base + (PcdGet64(PcdPciHostBridgeMemory64Size) - 1);
+ PlatformInfo->PciData.PciExpressBase = (PcdGet64(PcdPciExpressBaseAddress));
+ PlatformInfo->PciData.PciExpressSize = (UINT32)(PcdGet64(PcdPciExpressSize));
+ PlatformInfo->MemData.MemTsegSize = FixedPcdGet32(PcdTSegSize);
+
+ CpuAddressWidth = 32;
+ AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &FeatureInfo.RegEax, NULL, NULL, NULL);
+ if (FeatureInfo.RegEax >= EFI_CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (EFI_CPUID_VIR_PHY_ADDRESS_SIZE, &FeatureInfo.RegEax, NULL, NULL, NULL);
+ CpuAddressWidth = (UINT8) (FeatureInfo.RegEax & 0xFF);
+ }
+ PlatformInfo->CpuData.CpuAddressWidth = CpuAddressWidth;
+ DEBUG ((EFI_D_INFO, "CpuData.CpuAddressWidth : %d\n", PlatformInfo->CpuData.CpuAddressWidth));
+
+ // Initialize UDS stack variables to zero
+ ZeroMem(&IioUds, sizeof IioUds);
+
+ // Init UDS data here
+ IioUds.PlatformData.Pci64BitResourceAllocation = 0;
+ IioUds.PlatformData.PfSbspId = 0;
+ IioUds.PlatformData.PfGIoBase = PlatformInfo->PciData.PciResourceIoBase;
+ IioUds.PlatformData.PfGIoLimit = PlatformInfo->PciData.PciResourceIoLimit;
+ IioUds.PlatformData.PfGMmiolBase = PlatformInfo->PciData.PciResourceMem32Base;
+ IioUds.PlatformData.PfGMmiolLimit = PlatformInfo->PciData.PciResourceMem32Limit;
+ IioUds.PlatformData.PfGMmiohBase = PlatformInfo->PciData.PciResourceMem64Base;
+ IioUds.PlatformData.PfGMmiohLimit = PlatformInfo->PciData.PciResourceMem64Limit;
+ IioUds.PlatformData.MemTsegSize = PlatformInfo->MemData.MemTsegSize;
+ IioUds.PlatformData.PciExpressBase = PlatformInfo->PciData.PciExpressBase;
+ IioUds.PlatformData.PciExpressSize = PlatformInfo->PciData.PciExpressSize;
+ IioUds.PlatformData.numofIIO = 0;
+ IioUds.PlatformData.MaxBusNumber = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT;
+
+ for (Ctr1 = 0; Ctr1 < MAX_NODE; ++Ctr1) {
+ IioUds.PlatformData.numofIIO++;
+ IioUds.PlatformData.IIO_resource[Ctr1].Valid = 1;
+ IioUds.PlatformData.IIO_resource[Ctr1].SocketID = Ctr1;
+ IioUds.PlatformData.IIO_resource[Ctr1].BusBase = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE;
+ IioUds.PlatformData.IIO_resource[Ctr1].BusLimit = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT;
+ DEBUG((EFI_D_INFO, "IIO[%d] busbase = %x Limit=%x\n",Ctr1,IioUds.PlatformData.IIO_resource[Ctr1].BusBase,
+ IioUds.PlatformData.IIO_resource[Ctr1].BusLimit));
+
+ IioUds.PlatformData.IIO_resource[Ctr1].PciResourceIoBase = IioUds.PlatformData.PfGIoBase;
+ IioUds.PlatformData.IIO_resource[Ctr1].PciResourceIoLimit = IioUds.PlatformData.PfGIoLimit;
+ DEBUG((EFI_D_INFO, "IIO[%d] IoBase = %x IoLimit=%x\n",Ctr1,IioUds.PlatformData.IIO_resource[Ctr1].PciResourceIoBase,
+ IioUds.PlatformData.IIO_resource[Ctr1].PciResourceIoLimit));
+ IioUds.PlatformData.IIO_resource[Ctr1].IoApicBase = IOAPIC_BASE;
+ IioUds.PlatformData.IIO_resource[Ctr1].IoApicLimit = (IOAPIC_BASE + IOAPIC_SIZE -1);
+ DEBUG((EFI_D_INFO, "IIO[%d] IoApicBase = %x IoApicLimit=%x\n",Ctr1,IioUds.PlatformData.IIO_resource[Ctr1].IoApicBase,
+ IioUds.PlatformData.IIO_resource[Ctr1].IoApicLimit ));
+ IioUds.PlatformData.IIO_resource[Ctr1].PciResourceMem32Base = IioUds.PlatformData.PfGMmiolBase;
+ IioUds.PlatformData.IIO_resource[Ctr1].PciResourceMem32Limit = IioUds.PlatformData.PfGMmiolLimit;
+ IioUds.PlatformData.IIO_resource[Ctr1].PciResourceMem64Base = IioUds.PlatformData.PfGMmiohBase;
+ IioUds.PlatformData.IIO_resource[Ctr1].PciResourceMem64Limit = IioUds.PlatformData.PfGMmiohLimit;
+ DEBUG((EFI_D_INFO, "IIO[%d] Mem32Base = %x Mem32Limit=%x\n",Ctr1,IioUds.PlatformData.IIO_resource[Ctr1].PciResourceMem32Base,
+ IioUds.PlatformData.IIO_resource[Ctr1].PciResourceMem32Limit ));
+
+ // Reserve RBCA address
+ IioUds.PlatformData.IIO_resource[Ctr1].RcbaAddress = (UINT32)PcdGet64(PcdRcbaMmioBaseAddress);
+ DEBUG((EFI_D_INFO, "IIO[%d] RcbaAddress=%x\n",Ctr1,IioUds.PlatformData.IIO_resource[Ctr1].RcbaAddress));
+ }
+
+ // Build HOB data to forward to DXE phase now that all initialization is complete!
+ BuildGuidDataHob (
+ &UniversalDataGuid,
+ (VOID *) &IioUds,
+ sizeof(IIO_UDS)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Load a configuration stored in a variable.
+
+ @param TimingData Timing data to be loaded from NVRAM.
+ @param RowConfArray Row configuration information for each row in the system.
+
+ @return EFI_SUCCESS The function completed successfully.
+ Other Could not read variable.
+
+**/
+EFI_STATUS
+LoadConfig (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,
+ IN OUT MRC_PARAMS *MrcData
+ )
+{
+
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ PLATFORM_VARIABLE_MEMORY_CONFIG_DATA VarData;
+
+ BufferSize = ((sizeof (VarData.timings) + 0x7) & (~0x7)); // HOB data size (stored in variable) is required to be multiple of 8bytes
+
+ Status = VariableServices->GetVariable (
+ VariableServices,
+ EFI_MEMORY_CONFIG_DATA_NAME,
+ &gEfiMemoryConfigDataGuid,
+ NULL,
+ &BufferSize,
+ &VarData.timings
+ );
+ if (!EFI_ERROR (Status)) {
+ CopyMem (&MrcData->timings, &VarData.timings, sizeof(MrcData->timings));
+ }
+ return Status;
+}
+
+
+/**
+
+ This function installs memory.
+
+ @param PeiServices PEI Services table.
+ @param BootMode The specific boot path that is being followed
+ @param Mch Pointer to the DualChannelDdrMemoryInit PPI
+ @param RowConfArray Row configuration information for each row in the system.
+
+ @return EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+
+**/
+EFI_STATUS
+InstallEfiMemory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,
+ IN EFI_BOOT_MODE BootMode,
+ IN UINT32 TotalMemorySize
+ )
+{
+ EFI_DIMM_LAYOUT *DimmLayout;
+ EFI_PHYSICAL_ADDRESS PeiMemoryBaseAddress;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS Hob;
+ PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES];
+ UINT8 CurrentSocket;
+ UINT8 Index;
+ UINT8 NumRanges;
+ UINT8 SmramIndex;
+ UINT8 SmramRanges;
+ UINT64 PeiMemoryLength;
+ UINTN BufferSize;
+ UINTN PeiMemoryIndex;
+ UINTN RequiredMemSize;
+ EFI_RESOURCE_ATTRIBUTE_TYPE Attribute;
+ EFI_PHYSICAL_ADDRESS BadMemoryAddress;
+ EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable;
+ VOID *CapsuleBuffer;
+ UINTN CapsuleBufferLength;
+ PEI_CAPSULE_PPI *Capsule;
+ VOID *LargeMemRangeBuf;
+ UINTN LargeMemRangeBufLen;
+
+ //
+ // Test the memory from 1M->TOM
+ //
+ if (BootMode != BOOT_ON_FLASH_UPDATE) {
+ Status = BaseMemoryTest (
+ PeiServices,
+ 0x100000,
+ (TotalMemorySize - 0x100000),
+ Quick,
+ &BadMemoryAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+
+ //
+ // Get the Memory Map
+ //
+ NumRanges = MAX_RANGES;
+
+ ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * NumRanges);
+
+ Status = GetMemoryMap (
+ PeiServices,
+ TotalMemorySize,
+ (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *) MemoryMap,
+ &NumRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find the highest memory range in processor native address space to give to
+ // PEI. Then take the top.
+ //
+ PeiMemoryBaseAddress = 0;
+
+ //
+ // Query the platform for the minimum memory size
+ //
+
+ Status = GetPlatformMemorySize (
+ PeiServices,
+ BootMode,
+ &PeiMemoryLength
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get required memory size for ACPI use. This helps to put ACPI memory on the topest
+ //
+ RequiredMemSize = 0;
+ RetriveRequiredMemorySize (PeiServices, &RequiredMemSize);
+
+ PeiMemoryIndex = 0;
+
+ for (Index = 0; Index < NumRanges; Index++)
+ {
+ DEBUG ((EFI_D_INFO, "Found 0x%x bytes at ", MemoryMap[Index].RangeLength));
+ DEBUG ((EFI_D_INFO, "0x%x.\n", MemoryMap[Index].PhysicalAddress));
+
+ if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&
+ (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < MAX_ADDRESS) &&
+ (MemoryMap[Index].PhysicalAddress >= PeiMemoryBaseAddress) &&
+ (MemoryMap[Index].RangeLength >= PeiMemoryLength)) {
+ PeiMemoryBaseAddress = MemoryMap[Index].PhysicalAddress +
+ MemoryMap[Index].RangeLength -
+ PeiMemoryLength;
+ PeiMemoryIndex = Index;
+ }
+ }
+
+ //
+ // Find the largest memory range excluding that given to PEI.
+ //
+ LargeMemRangeBuf = NULL;
+ LargeMemRangeBufLen = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&
+ (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < MAX_ADDRESS)) {
+ if (Index != PeiMemoryIndex) {
+ if (MemoryMap[Index].RangeLength > LargeMemRangeBufLen) {
+ LargeMemRangeBuf = (VOID *) ((UINTN) MemoryMap[Index].PhysicalAddress);
+ LargeMemRangeBufLen = (UINTN) MemoryMap[Index].RangeLength;
+ }
+ } else {
+ if ((MemoryMap[Index].RangeLength - PeiMemoryLength) >= LargeMemRangeBufLen) {
+ LargeMemRangeBuf = (VOID *) ((UINTN) MemoryMap[Index].PhysicalAddress);
+ LargeMemRangeBufLen = (UINTN) (MemoryMap[Index].RangeLength - PeiMemoryLength);
+ }
+ }
+ }
+ }
+
+ Capsule = NULL;
+ CapsuleBuffer = NULL;
+ CapsuleBufferLength = 0;
+ if (BootMode == BOOT_ON_FLASH_UPDATE) {
+ Status = PeiServicesLocatePpi (
+ &gPeiCapsulePpiGuid, // GUID
+ 0, // INSTANCE
+ NULL, // EFI_PEI_PPI_DESCRIPTOR
+ (VOID **)&Capsule // PPI
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (Status == EFI_SUCCESS) {
+ CapsuleBuffer = LargeMemRangeBuf;
+ CapsuleBufferLength = LargeMemRangeBufLen;
+
+ FindCapsuleSecurityHeadersAndBuildHobs (PeiServices);
+
+ //
+ // Call the Capsule PPI Coalesce function to coalesce the capsule data.
+ //
+ Status = Capsule->Coalesce (
+ PeiServices,
+ &CapsuleBuffer,
+ &CapsuleBufferLength
+ );
+ //
+ // If it failed, then NULL out our capsule PPI pointer so that the capsule
+ // HOB does not get created below.
+ //
+ if (Status != EFI_SUCCESS) {
+ Capsule = NULL;
+ }
+ }
+ } else {
+ //
+ // Setup redirected memory allocation services to use found LargeMemRangeBuf.
+ // For quark this buffer must be external to protected IMR memory ranges.
+ //
+ RedirectMemoryServicesSetPool (
+ LargeMemRangeBuf,
+ LargeMemRangeBufLen
+ );
+ }
+
+ //
+ // Set up the IMR policy required for this platform
+ //
+ Status = SetPlatformImrPolicy (
+ PeiMemoryBaseAddress,
+ PeiMemoryLength,
+ RequiredMemSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Carve out the top memory reserved for ACPI
+ //
+ Status = (*PeiServices)->InstallPeiMemory (PeiServices, PeiMemoryBaseAddress, (PeiMemoryLength - RequiredMemSize));
+ ASSERT_EFI_ERROR (Status);
+
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_TESTED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ PeiMemoryBaseAddress, // MemoryBegin
+ PeiMemoryLength // MemoryLength
+ );
+
+ //
+ // Install physical memory descriptor hobs for each memory range.
+ //
+ SmramRanges = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ Attribute = 0;
+ if (MemoryMap[Index].Type == DualChannelDdrMainMemory)
+ {
+ if (Index == PeiMemoryIndex) {
+ //
+ // This is a partially tested Main Memory range, give it to EFI
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ MemoryMap[Index].PhysicalAddress,
+ MemoryMap[Index].RangeLength - PeiMemoryLength
+ );
+ } else {
+ //
+ // This is an untested Main Memory range, give it to EFI
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ MemoryMap[Index].PhysicalAddress, // MemoryBegin
+ MemoryMap[Index].RangeLength // MemoryLength
+ );
+ }
+ } else {
+ if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)) {
+ SmramRanges++;
+ }
+ if ((MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrGraphicsMemoryNonCacheable)) {
+ Attribute |= EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;
+ }
+ if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrGraphicsMemoryCacheable)) {
+ //
+ // TSEG and HSEG can be used with a write-back(WB) cache policy; however,
+ // the specification requires that the TSEG and HSEG space be cached only
+ // inside of the SMI handler. when using HSEG or TSEG an IA-32 processor
+ // does not automatically write back and invalidate its cache before entering
+ // SMM or before existing SMM therefore any MTRR defined for the active TSEG
+ // or HSEG must be set to un-cacheable(UC) outside of SMM.
+ //
+ Attribute |= EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;
+ }
+ if (MemoryMap[Index].Type == DualChannelDdrReservedMemory) {
+ Attribute |= EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;
+ }
+ //
+ // Make sure non-system memory is marked as reserved
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_RESERVED, // MemoryType,
+ Attribute, // MemoryAttribute
+ MemoryMap[Index].PhysicalAddress, // MemoryBegin
+ MemoryMap[Index].RangeLength // MemoryLength
+ );
+ }
+ }
+
+ //
+ // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM memory that contains a pointer
+ // to the SMM Services Table that is required on the S3 resume path
+ //
+ ASSERT (SmramRanges > 0);
+ BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK);
+ BufferSize += ((SmramRanges - 1) * sizeof (EFI_SMRAM_DESCRIPTOR));
+
+ Hob.Raw = BuildGuidHob (
+ &gEfiSmmPeiSmramMemoryReserveGuid,
+ BufferSize
+ );
+ ASSERT (Hob.Raw);
+
+ SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *) (Hob.Raw);
+ SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges;
+
+ SmramIndex = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)
+ ) {
+ //
+ // This is an SMRAM range, create an SMRAM descriptor
+ //
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = MemoryMap[Index].PhysicalAddress;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = MemoryMap[Index].CpuAddress;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = MemoryMap[Index].RangeLength;
+ if (MemoryMap[Index].Type == DualChannelDdrSmramCacheable) {
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;
+ } else {
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED;
+ }
+
+ SmramIndex++;
+ }
+ }
+
+ //
+ // Build a HOB with the location of the reserved memory range.
+ //
+ CopyMem(&DescriptorAcpiVariable, &SmramHobDescriptorBlock->Descriptor[SmramRanges-1], sizeof(EFI_SMRAM_DESCRIPTOR));
+ DescriptorAcpiVariable.CpuStart += RESERVED_CPU_S3_SAVE_OFFSET;
+ BuildGuidDataHob (
+ &gEfiAcpiVariableGuid,
+ &DescriptorAcpiVariable,
+ sizeof (EFI_SMRAM_DESCRIPTOR)
+ );
+
+ //
+ // Build a HOB describing memory layout and state
+ //
+ BufferSize = sizeof (EFI_DIMM_LAYOUT) + sizeof (EFI_DIMM_STATE) * (MAX_SOCKETS);
+
+ Hob.Raw = BuildGuidHob (
+ &gEfiPlatformMemoryLayoutGuid,
+ BufferSize
+ );
+ ASSERT (Hob.Raw);
+
+ DimmLayout = (EFI_DIMM_LAYOUT *) Hob.Raw;
+ //
+ // Initialize the layout structure.
+ // This sets all reserved bits to 0 and all DIMM to not present, not
+ // configured, and not disabled.
+ // Do not remove this as it is required for the following algorithm to behave
+ // correctly.
+ //
+ SetMem (DimmLayout, BufferSize, 0);
+
+ DimmLayout->DimmSets = (UINT8) (MAX_SOCKET_SETS);
+ DimmLayout->DimmsPerSet = MAX_CHANNELS;
+ DimmLayout->RowsPerSet = MAX_SIDES;
+
+ for (CurrentSocket = 0; CurrentSocket < MAX_SOCKETS; CurrentSocket++) {
+ DimmLayout->State[CurrentSocket].Present = TRUE;
+ DimmLayout->State[CurrentSocket].Configured = TRUE;
+ }
+
+ //
+ // If we found the capsule PPI (and we didn't have errors), then
+ // call the capsule PEIM to allocate memory for the capsule.
+ //
+ if (Capsule != NULL) {
+ Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Find memory that is reserved so PEI has some to use.
+
+ @param PeiServices PEI Services table.
+ @param VariableSevices Variable PPI instance.
+
+ @return EFI_SUCCESS The function completed successfully.
+ Error value from LocatePpi()
+ Error Value from VariableServices->GetVariable()
+
+**/
+EFI_STATUS
+InstallS3Memory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,
+ IN UINT32 TotalMemorySize
+ )
+{
+ EFI_STATUS Status;
+ UINTN S3MemoryBase;
+ UINTN S3MemorySize;
+ UINT8 SmramRanges;
+ UINT8 NumRanges;
+ UINT8 Index;
+ UINT8 SmramIndex;
+ UINTN BufferSize;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;
+ PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES];
+ RESERVED_ACPI_S3_RANGE *S3MemoryRangeData;
+ EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable;
+
+ //
+ // Get the Memory Map
+ //
+ NumRanges = MAX_RANGES;
+
+ ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * NumRanges);
+
+ Status = GetMemoryMap (
+ PeiServices,
+ TotalMemorySize,
+ (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *) MemoryMap,
+ &NumRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install physical memory descriptor hobs for each memory range.
+ //
+ SmramRanges = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)) {
+ SmramRanges++;
+ }
+ }
+
+ ASSERT (SmramRanges > 0);
+
+ //
+ // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM memory that contains a pointer
+ // to the SMM Services Table that is required on the S3 resume path
+ //
+ BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK);
+ if (SmramRanges > 0) {
+ BufferSize += ((SmramRanges - 1) * sizeof (EFI_SMRAM_DESCRIPTOR));
+ }
+
+ Hob.Raw = BuildGuidHob (
+ &gEfiSmmPeiSmramMemoryReserveGuid,
+ BufferSize
+ );
+ ASSERT (Hob.Raw);
+
+ SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *) (Hob.Raw);
+ SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges;
+
+ SmramIndex = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)
+ ) {
+ //
+ // This is an SMRAM range, create an SMRAM descriptor
+ //
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = MemoryMap[Index].PhysicalAddress;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = MemoryMap[Index].CpuAddress;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = MemoryMap[Index].RangeLength;
+ if (MemoryMap[Index].Type == DualChannelDdrSmramCacheable) {
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;
+ } else {
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED;
+ }
+
+ SmramIndex++;
+ }
+ }
+
+ //
+ // Build a HOB with the location of the reserved memory range.
+ //
+ CopyMem(&DescriptorAcpiVariable, &SmramHobDescriptorBlock->Descriptor[SmramRanges-1], sizeof(EFI_SMRAM_DESCRIPTOR));
+ DescriptorAcpiVariable.CpuStart += RESERVED_CPU_S3_SAVE_OFFSET;
+ BuildGuidDataHob (
+ &gEfiAcpiVariableGuid,
+ &DescriptorAcpiVariable,
+ sizeof (EFI_SMRAM_DESCRIPTOR)
+ );
+
+ //
+ // Get the location and size of the S3 memory range in the reserved page and
+ // install it as PEI Memory.
+ //
+
+ DEBUG ((EFI_D_INFO, "TSEG Base = 0x%08x\n", SmramHobDescriptorBlock->Descriptor[SmramRanges-1].PhysicalStart));
+ S3MemoryRangeData = (RESERVED_ACPI_S3_RANGE*)(UINTN)
+ (SmramHobDescriptorBlock->Descriptor[SmramRanges-1].PhysicalStart + RESERVED_ACPI_S3_RANGE_OFFSET);
+
+ S3MemoryBase = (UINTN) (S3MemoryRangeData->AcpiReservedMemoryBase);
+ DEBUG ((EFI_D_INFO, "S3MemoryBase = 0x%08x\n", S3MemoryBase));
+ S3MemorySize = (UINTN) (S3MemoryRangeData->AcpiReservedMemorySize);
+ DEBUG ((EFI_D_INFO, "S3MemorySise = 0x%08x\n", S3MemorySize));
+
+ Status = (*PeiServices)->InstallPeiMemory (PeiServices, S3MemoryBase, S3MemorySize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Retrieve the system memory length and build memory hob for the system
+ // memory above 1MB. So Memory Callback can set cache for the system memory
+ // correctly on S3 boot path, just like it does on Normal boot path.
+ //
+ ASSERT_EFI_ERROR ((S3MemoryRangeData->SystemMemoryLength - 0x100000) > 0);
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ 0x100000,
+ S3MemoryRangeData->SystemMemoryLength - 0x100000
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+
+ Fix me
+
+ @param PeiServices PEI Services table.
+ @param Size The memory log for storing events
+
+ @return None
+
+**/
+VOID
+RetriveRequiredMemorySize (
+ IN EFI_PEI_SERVICES **PeiServices,
+ OUT UINTN *Size
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_MEMORY_TYPE_INFORMATION *MemoryData;
+ UINT8 Index;
+ UINTN TempPageNum;
+
+ MemoryData = NULL;
+ TempPageNum = 0;
+ Index = 0;
+
+ Status = PeiServicesGetHobList ((VOID **)&Hob.Raw);
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION &&
+ CompareGuid (&Hob.Guid->Name, &gEfiMemoryTypeInformationGuid)
+ ) {
+ MemoryData = (EFI_MEMORY_TYPE_INFORMATION *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID));
+ break;
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+ //
+ // Platform PEIM should supply such a information. Generic PEIM doesn't assume any default value
+ //
+ if (!MemoryData) {
+ return ;
+ }
+
+ while (MemoryData[Index].Type != EfiMaxMemoryType) {
+ //
+ // Accumulate default memory size requirements
+ //
+ TempPageNum += MemoryData[Index].NumberOfPages;
+ Index++;
+ }
+
+ if (TempPageNum == 0) {
+ return ;
+ }
+
+ //
+ // Add additional pages used by DXE memory manager
+ //
+ (*Size) = (TempPageNum + EDKII_DXE_MEM_SIZE_PAGES) * EFI_PAGE_SIZE;
+
+ return ;
+}
+
+/**
+
+ This function returns the memory ranges to be enabled, along with information
+ describing how the range should be used.
+
+ @param PeiServices PEI Services Table.
+ @param TimingData Detected DDR timing parameters for installed memory.
+ @param RowConfArray Pointer to an array of EFI_DUAL_CHANNEL_DDR_ROW_CONFIG structures. The number
+ of items in the array must match MaxRows returned by the McGetRowInfo() function.
+ @param MemoryMap Buffer to record details of the memory ranges tobe enabled.
+ @param NumRanges On input, this contains the maximum number of memory ranges that can be described
+ in the MemoryMap buffer.
+
+ @return MemoryMap The buffer will be filled in
+ NumRanges will contain the actual number of memory ranges that are to be anabled.
+ EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetMemoryMap (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT32 TotalMemorySize,
+ IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,
+ IN OUT UINT8 *NumRanges
+ )
+{
+ EFI_PHYSICAL_ADDRESS MemorySize;
+ EFI_PHYSICAL_ADDRESS RowLength;
+ EFI_STATUS Status;
+ PEI_MEMORY_RANGE_PCI_MEMORY PciMemoryMask;
+ PEI_MEMORY_RANGE_OPTION_ROM OptionRomMask;
+ PEI_MEMORY_RANGE_SMRAM SmramMask;
+ PEI_MEMORY_RANGE_SMRAM TsegMask;
+ UINT32 BlockNum;
+ UINT8 EsmramcRegister;
+ UINT8 ExtendedMemoryIndex;
+ UINT32 Register;
+
+ if ((*NumRanges) < MAX_RANGES) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *NumRanges = 0;
+
+ //
+ // Find out which memory ranges to reserve on this platform
+ //
+ Status = ChooseRanges (
+ &OptionRomMask,
+ &SmramMask,
+ &PciMemoryMask
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Generate Memory ranges for the memory map.
+ //
+ EsmramcRegister = 0;
+ MemorySize = 0;
+
+ RowLength = TotalMemorySize;
+
+ //
+ // Add memory below 640KB to the memory map. Make sure memory between
+ // 640KB and 1MB are reserved, even if not used for SMRAM
+ //
+ MemoryMap[*NumRanges].PhysicalAddress = MemorySize;
+ MemoryMap[*NumRanges].CpuAddress = MemorySize;
+ MemoryMap[*NumRanges].RangeLength = 0xA0000;
+ MemoryMap[*NumRanges].Type = DualChannelDdrMainMemory;
+ (*NumRanges)++;
+
+ //
+ // Just mark this range reserved
+ //
+ MemoryMap[*NumRanges].PhysicalAddress = 0xA0000;
+ MemoryMap[*NumRanges].CpuAddress = 0xA0000;
+ MemoryMap[*NumRanges].RangeLength = 0x60000;
+ MemoryMap[*NumRanges].Type = DualChannelDdrReservedMemory;
+ (*NumRanges)++;
+
+ RowLength -= (0x100000 - MemorySize);
+ MemorySize = 0x100000;
+
+ //
+ // Add remaining memory to the memory map
+ //
+ MemoryMap[*NumRanges].PhysicalAddress = MemorySize;
+ MemoryMap[*NumRanges].CpuAddress = MemorySize;
+ MemoryMap[*NumRanges].RangeLength = RowLength;
+ MemoryMap[*NumRanges].Type = DualChannelDdrMainMemory;
+ (*NumRanges)++;
+ MemorySize += RowLength;
+
+ ExtendedMemoryIndex = (UINT8) (*NumRanges - 1);
+
+ // See if we need to trim TSEG out of the highest memory range
+ //
+ if (SmramMask & PEI_MR_SMRAM_TSEG_MASK) {//pcd
+ //
+ // Create the new range for TSEG and remove that range from the previous SdrDdrMainMemory range
+ //
+ TsegMask = (SmramMask & PEI_MR_SMRAM_SIZE_MASK);
+
+ BlockNum = 1;
+ while (TsegMask) {
+ TsegMask >>= 1;
+ BlockNum <<= 1;
+ }
+
+ BlockNum >>= 1;
+
+ if (BlockNum) {
+
+ MemoryMap[*NumRanges].RangeLength = (BlockNum * 128 * 1024);
+ Register = (UINT32)((MemorySize - 1) & SMM_END_MASK);
+ MemorySize -= MemoryMap[*NumRanges].RangeLength;
+ MemoryMap[*NumRanges].PhysicalAddress = MemorySize;
+ MemoryMap[*NumRanges].CpuAddress = MemorySize;
+ MemoryMap[ExtendedMemoryIndex].RangeLength -= MemoryMap[*NumRanges].RangeLength;
+
+ //
+ // Update QuarkNcSoc HSMMCTL register
+ //
+ Register |= (UINT32)(((RShiftU64(MemorySize, 16)) & SMM_START_MASK) + (SMM_WRITE_OPEN | SMM_READ_OPEN | SMM_CODE_RD_OPEN));
+ QncHsmmcWrite (Register);
+ }
+
+ //
+ // Chipset only supports cacheable SMRAM
+ //
+ MemoryMap[*NumRanges].Type = DualChannelDdrSmramCacheable;
+
+ (*NumRanges)++;
+ }
+
+ //
+ // trim 64K memory from highest memory range for Rmu Main binary shadow
+ //
+ MemoryMap[*NumRanges].RangeLength = 0x10000;
+ MemorySize -= MemoryMap[*NumRanges].RangeLength;
+ MemoryMap[*NumRanges].PhysicalAddress = MemorySize;
+ MemoryMap[*NumRanges].CpuAddress = MemorySize;
+ MemoryMap[ExtendedMemoryIndex].RangeLength -= MemoryMap[*NumRanges].RangeLength;
+ MemoryMap[*NumRanges].Type = DualChannelDdrReservedMemory;
+ (*NumRanges)++;
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+Routine Description:
+
+ Fill in bit masks to specify reserved memory ranges on the Lakeport platform
+
+Arguments:
+
+Returns:
+
+ OptionRomMask - Bit mask specifying memory regions reserved for Legacy option
+ ROM use (if any)
+
+ SmramMask - Bit mask specifying memory regions reserved for SMM use (if any)
+
+**/
+EFI_STATUS
+ChooseRanges (
+ IN OUT PEI_MEMORY_RANGE_OPTION_ROM *OptionRomMask,
+ IN OUT PEI_MEMORY_RANGE_SMRAM *SmramMask,
+ IN OUT PEI_MEMORY_RANGE_PCI_MEMORY *PciMemoryMask
+ )
+{
+
+ //
+ // Choose regions to reserve for Option ROM use
+ //
+ *OptionRomMask = PEI_MR_OPTION_ROM_NONE;
+
+ //
+ // Choose regions to reserve for SMM use (AB/H SEG and TSEG). Size is in 128K blocks
+ //
+ *SmramMask = PEI_MR_SMRAM_CACHEABLE_MASK | PEI_MR_SMRAM_TSEG_MASK | ((FixedPcdGet32(PcdTSegSize)) >> 17);
+
+ *PciMemoryMask = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetPlatformMemorySize (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode,
+ IN OUT UINT64 *MemorySize
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
+ UINTN DataSize;
+ EFI_MEMORY_TYPE_INFORMATION MemoryData [EfiMaxMemoryType + 1];
+ UINTN Index;
+
+ DataSize = sizeof (MemoryData);
+
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+
+ //
+ // // Treat recovery as if variable not found (eg 1st boot).
+ //
+ Status = EFI_NOT_FOUND;
+
+ } else {
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **)&Variable
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Variable->GetVariable (
+ Variable,
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+ &gEfiMemoryTypeInformationGuid,
+ NULL,
+ &DataSize,
+ &MemoryData
+ );
+ }
+
+ //
+ // Accumulate maximum amount of memory needed
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Start with minimum memory
+ //
+ *MemorySize = PEI_MIN_MEMORY_SIZE;
+
+ for (Index = 0; Index < sizeof(mDefaultCltMemoryTypeInformation) / sizeof (EFI_MEMORY_TYPE_INFORMATION); Index++) {
+ *MemorySize += mDefaultCltMemoryTypeInformation[Index].NumberOfPages * EFI_PAGE_SIZE;
+ }
+
+ //
+ // Build the GUID'd HOB for DXE
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ mDefaultCltMemoryTypeInformation,
+ sizeof(mDefaultCltMemoryTypeInformation)
+ );
+ } else {
+ //
+ // Start with at least PEI_MIN_MEMORY_SIZE pages of memory for the DXE Core and the DXE Stack
+ //
+
+ *MemorySize = PEI_MIN_MEMORY_SIZE;
+ for (Index = 0; Index < DataSize / sizeof (EFI_MEMORY_TYPE_INFORMATION); Index++) {
+ DEBUG ((EFI_D_INFO, "Index %d, Page: %d\n", Index, MemoryData[Index].NumberOfPages));
+ *MemorySize += MemoryData[Index].NumberOfPages * EFI_PAGE_SIZE;
+ }
+
+ //
+ // Build the GUID'd HOB for DXE
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ MemoryData,
+ DataSize
+ );
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+BaseMemoryTest (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS BeginAddress,
+ IN UINT64 MemoryLength,
+ IN PEI_MEMORY_TEST_OP Operation,
+ OUT EFI_PHYSICAL_ADDRESS *ErrorAddress
+ )
+{
+ UINT32 TestPattern;
+ EFI_PHYSICAL_ADDRESS TempAddress;
+ UINT32 SpanSize;
+
+ TestPattern = 0x5A5A5A5A;
+ SpanSize = 0;
+
+ //
+ // Make sure we don't try and test anything above the max physical address range
+ //
+ ASSERT (BeginAddress + MemoryLength < MAX_ADDRESS);
+
+ switch (Operation) {
+ case Extensive:
+ SpanSize = 0x4;
+ break;
+
+ case Sparse:
+ case Quick:
+ SpanSize = 0x40000;
+ break;
+
+ case Ignore:
+ goto Done;
+ break;
+ }
+ //
+ // Write the test pattern into memory range
+ //
+ TempAddress = BeginAddress;
+ while (TempAddress < BeginAddress + MemoryLength) {
+ (*(UINT32 *) (UINTN) TempAddress) = TestPattern;
+ TempAddress += SpanSize;
+ }
+ //
+ // Read pattern from memory and compare it
+ //
+ TempAddress = BeginAddress;
+ while (TempAddress < BeginAddress + MemoryLength) {
+ if ((*(UINT32 *) (UINTN) TempAddress) != TestPattern) {
+ *ErrorAddress = TempAddress;
+ DEBUG ((EFI_D_ERROR, "Memory test failed at 0x%x.\n", TempAddress));
+ return EFI_DEVICE_ERROR;
+ }
+
+ TempAddress += SpanSize;
+ }
+
+Done:
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function sets up the platform specific IMR protection for the various
+ memory regions.
+
+ @param PeiMemoryBaseAddress Base address of memory allocated for PEI.
+ @param PeiMemoryLength Length in bytes of the PEI memory (includes ACPI memory).
+ @param RequiredMemSize Size in bytes of the ACPI/Runtime memory
+
+ @return EFI_SUCCESS The function completed successfully.
+ EFI_ACCESS_DENIED Access to IMRs failed.
+
+**/
+EFI_STATUS
+SetPlatformImrPolicy (
+ IN EFI_PHYSICAL_ADDRESS PeiMemoryBaseAddress,
+ IN UINT64 PeiMemoryLength,
+ IN UINTN RequiredMemSize
+ )
+{
+ UINT8 Index;
+ UINT32 Register;
+ UINT16 DeviceId;
+
+ //
+ // Check what Soc we are running on (read Host bridge DeviceId)
+ //
+ DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
+
+ //
+ // If any IMR register is locked then we cannot proceed
+ //
+ for (Index = (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL); Index <=(QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL); Index=Index+4)
+ {
+ Register = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index);
+ if (Register & IMR_LOCK) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ //
+ // Add IMR0 protection for the 'PeiMemory'
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR0,
+ (UINT32)(((RShiftU64(PeiMemoryBaseAddress, 8)) & IMRL_MASK) | IMR_EN),
+ (UINT32)((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-RequiredMemSize + EFI_PAGES_TO_SIZE(EDKII_DXE_MEM_SIZE_PAGES-1) - 1), 8)) & IMRL_MASK),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM)
+ );
+
+ //
+ // Add IMR2 protection for shadowed RMU binary.
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR2,
+ (UINT32)(((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength), 8)) & IMRH_MASK) | IMR_EN),
+ (UINT32)((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength+PcdGet32(PcdFlashQNCMicrocodeSize)-1), 8)) & IMRH_MASK),
+ (UINT32)(CPU_SNOOP + RMU + CPU0_NON_SMM),
+ (UINT32)(CPU_SNOOP + RMU + CPU0_NON_SMM)
+ );
+
+ //
+ // Add IMR3 protection for the default SMRAM.
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR3,
+ (UINT32)(((RShiftU64((SMM_DEFAULT_SMBASE), 8)) & IMRL_MASK) | IMR_EN),
+ (UINT32)((RShiftU64((SMM_DEFAULT_SMBASE+SMM_DEFAULT_SMBASE_SIZE_BYTES-1), 8)) & IMRH_MASK),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM)
+ );
+
+ //
+ // Add IMR5 protection for the legacy S3 and AP Startup Vector region (below 1MB).
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR5,
+ (UINT32)(((RShiftU64(AP_STARTUP_VECTOR, 8)) & IMRL_MASK) | IMR_EN),
+ (UINT32)((RShiftU64((AP_STARTUP_VECTOR + EFI_PAGE_SIZE - 1), 8)) & IMRH_MASK),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM)
+ );
+
+ //
+ // Add IMR6 protection for the ACPI Reclaim/ACPI/Runtime Services.
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR6,
+ (UINT32)(((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-RequiredMemSize+EFI_PAGES_TO_SIZE(EDKII_DXE_MEM_SIZE_PAGES-1)), 8)) & IMRL_MASK) | IMR_EN),
+ (UINT32)((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-EFI_PAGE_SIZE-1), 8)) & IMRH_MASK),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM)
+ );
+
+ //
+ // Enable IMR4 protection of eSRAM.
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR4,
+ (UINT32)(((RShiftU64((UINTN)FixedPcdGet32 (PcdEsramStage1Base), 8)) & IMRL_MASK) | IMR_EN),
+ (UINT32)((RShiftU64(((UINTN)FixedPcdGet32 (PcdEsramStage1Base) + (UINTN)FixedPcdGet32 (PcdESramMemorySize) - 1), 8)) & IMRH_MASK),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM),
+ (UINT32)(CPU_SNOOP + CPU0_NON_SMM)
+ );
+
+ //
+ // Enable Interrupt on IMR/SMM Violation
+ //
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BIMRVCTL, (UINT32)(EnableIMRInt));
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BSMMVCTL, (UINT32)(EnableSMMInt));
+ }
+
+ //
+ // Disable IMR7 memory protection (eSRAM + DDR3 memory) since our policies
+ // are now setup.
+ //
+ QncImrWrite (
+ QUARK_NC_MEMORY_MANAGER_IMR7,
+ (UINT32)(IMRL_RESET & ~IMR_EN),
+ (UINT32)IMRH_RESET,
+ (UINT32)IMRX_ALL_ACCESS,
+ (UINT32)IMRX_ALL_ACCESS
+ );
+
+ return EFI_SUCCESS;
+}
+
+/** Return info derived from Installing Memory by MemoryInit.
+
+ @param[out] RmuMainBaseAddressPtr Return RmuMainBaseAddress to this location.
+ @param[out] SmramDescriptorPtr Return start of Smram descriptor list to this location.
+ @param[out] NumSmramRegionsPtr Return numbers of Smram regions to this location.
+
+ @return Address of RMU shadow region at the top of available memory.
+ @return List of Smram descriptors for each Smram region.
+ @return Numbers of Smram regions.
+**/
+VOID
+EFIAPI
+InfoPostInstallMemory (
+ OUT UINT32 *RmuMainBaseAddressPtr OPTIONAL,
+ OUT EFI_SMRAM_DESCRIPTOR **SmramDescriptorPtr OPTIONAL,
+ OUT UINTN *NumSmramRegionsPtr OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS Hob;
+ UINT64 CalcLength;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;
+
+ if ((RmuMainBaseAddressPtr == NULL) && (SmramDescriptorPtr == NULL) && (NumSmramRegionsPtr == NULL)) {
+ return;
+ }
+
+ SmramHobDescriptorBlock = NULL;
+ if (SmramDescriptorPtr != NULL) {
+ *SmramDescriptorPtr = NULL;
+ }
+ if (NumSmramRegionsPtr != NULL) {
+ *NumSmramRegionsPtr = 0;
+ }
+
+ //
+ // Calculate RMU shadow region base address.
+ // Set to 1 MB. Since 1MB cacheability will always be set
+ // until override by CSM.
+ //
+ CalcLength = 0x100000;
+
+ Status = PeiServicesGetHobList ((VOID **) &Hob.Raw);
+ ASSERT_EFI_ERROR (Status);
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ //
+ // Skip the memory region below 1MB
+ //
+ if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {
+ CalcLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
+ }
+ }
+ } else if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
+ if (CompareGuid (&(Hob.Guid->Name), &gEfiSmmPeiSmramMemoryReserveGuid)) {
+ SmramHobDescriptorBlock = (VOID*) (Hob.Raw + sizeof (EFI_HOB_GUID_TYPE));
+ if (SmramDescriptorPtr != NULL) {
+ *SmramDescriptorPtr = SmramHobDescriptorBlock->Descriptor;
+ }
+ if (NumSmramRegionsPtr != NULL) {
+ *NumSmramRegionsPtr = SmramHobDescriptorBlock->NumberOfSmmReservedRegions;
+ }
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+ if (RmuMainBaseAddressPtr != NULL) {
+ *RmuMainBaseAddressPtr = (UINT32) CalcLength;
+ }
+}
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.h b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.h
new file mode 100755
index 0000000..7d9f8e8
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.h
@@ -0,0 +1,205 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ MrcWrapper.h
+
+Abstract:
+
+ Framework PEIM to initialize memory on an DDR2 SDRAM Memory Controller.
+
+--*/
+
+#ifndef _MRC_WRAPPER_H
+#define _MRC_WRAPPER_H
+
+#include <Ppi/CltMemoryInit.h>
+#include "PlatformEarlyInit.h"
+
+//
+// Define the default memory areas required
+//
+#define EDKII_RESERVED_SIZE_PAGES 0x10
+#define ACPI_RECLAIM_SIZE_PAGES 0x40
+#define ACPI_NVS_SIZE_PAGES 0xD00
+#define RUNTIME_SERVICES_CODE_SIZE_PAGES 0x60
+#define RUNTIME_SERVICES_DATA_SIZE_PAGES 0x60
+#define EDKII_DXE_MEM_SIZE_PAGES 0x20
+
+#define AP_STARTUP_VECTOR 0x00097000
+
+//
+// Maximum number of "Socket Sets", where a "Socket Set is a set of matching
+// DIMM's from the various channels
+//
+#define MAX_SOCKET_SETS 2
+
+//
+// Maximum number of memory ranges supported by the memory controller
+//
+#define MAX_RANGES (MAX_ROWS + 5)
+
+//
+// Min. of 48MB PEI phase
+//
+#define PEI_MIN_MEMORY_SIZE (6 * 0x800000)
+#define PEI_RECOVERY_MIN_MEMORY_SIZE (6 * 0x800000)
+
+#define PEI_MEMORY_RANGE_OPTION_ROM UINT32
+#define PEI_MR_OPTION_ROM_NONE 0x00000000
+
+//
+// SMRAM Memory Range
+//
+#define PEI_MEMORY_RANGE_SMRAM UINT32
+#define PEI_MR_SMRAM_ALL 0xFFFFFFFF
+#define PEI_MR_SMRAM_NONE 0x00000000
+#define PEI_MR_SMRAM_CACHEABLE_MASK 0x80000000
+#define PEI_MR_SMRAM_SEGTYPE_MASK 0x00FF0000
+#define PEI_MR_SMRAM_ABSEG_MASK 0x00010000
+#define PEI_MR_SMRAM_HSEG_MASK 0x00020000
+#define PEI_MR_SMRAM_TSEG_MASK 0x00040000
+//
+// SMRAM Size is a multiple of 128KB.
+//
+#define PEI_MR_SMRAM_SIZE_MASK 0x0000FFFF
+
+//
+// Pci Memory Hole
+//
+#define PEI_MEMORY_RANGE_PCI_MEMORY UINT32
+
+typedef enum {
+ Ignore,
+ Quick,
+ Sparse,
+ Extensive
+} PEI_MEMORY_TEST_OP;
+
+//
+// MRC Params Variable structure.
+//
+
+typedef struct {
+ MrcTimings_t timings; // Actual MRC config values saved in variable store.
+ UINT8 VariableStorePad[8]; // Allow for data stored in variable is required to be multiple of 8bytes.
+} PLATFORM_VARIABLE_MEMORY_CONFIG_DATA;
+
+//
+// Function prototypes.
+//
+
+EFI_STATUS
+InstallEfiMemory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,
+ IN EFI_BOOT_MODE BootMode,
+ IN UINT32 TotalMemorySize
+ );
+
+EFI_STATUS
+InstallS3Memory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,
+ IN UINT32 TotalMemorySize
+ );
+
+EFI_STATUS
+MemoryInit (
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+
+EFI_STATUS
+LoadConfig (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,
+ IN OUT MRCParams_t *MrcData
+ );
+
+EFI_STATUS
+SaveConfig (
+ IN MRCParams_t *MrcData
+ );
+
+VOID
+RetriveRequiredMemorySize (
+ IN EFI_PEI_SERVICES **PeiServices,
+ OUT UINTN *Size
+ );
+
+EFI_STATUS
+GetMemoryMap (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT32 TotalMemorySize,
+ IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,
+ IN OUT UINT8 *NumRanges
+ );
+
+EFI_STATUS
+ChooseRanges (
+ IN OUT PEI_MEMORY_RANGE_OPTION_ROM *OptionRomMask,
+ IN OUT PEI_MEMORY_RANGE_SMRAM *SmramMask,
+ IN OUT PEI_MEMORY_RANGE_PCI_MEMORY *PciMemoryMask
+ );
+
+EFI_STATUS
+GetPlatformMemorySize (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode,
+ IN OUT UINT64 *MemorySize
+ );
+
+EFI_STATUS
+BaseMemoryTest (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS BeginAddress,
+ IN UINT64 MemoryLength,
+ IN PEI_MEMORY_TEST_OP Operation,
+ OUT EFI_PHYSICAL_ADDRESS *ErrorAddress
+ );
+
+EFI_STATUS
+SetPlatformImrPolicy (
+ IN EFI_PHYSICAL_ADDRESS PeiMemoryBaseAddress,
+ IN UINT64 PeiMemoryLength,
+ IN UINTN RequiredMemSize
+ );
+
+VOID
+EFIAPI
+InfoPostInstallMemory (
+ OUT UINT32 *RmuBaseAddressPtr OPTIONAL,
+ OUT EFI_SMRAM_DESCRIPTOR **SmramDescriptorPtr OPTIONAL,
+ OUT UINTN *NumSmramRegionsPtr OPTIONAL
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/PeiFvSecurity.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PeiFvSecurity.c
new file mode 100644
index 0000000..c5b1d5a
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PeiFvSecurity.c
@@ -0,0 +1,151 @@
+/** @file
+ EFI PEI Platform Security services
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PeiFvSecurity.h"
+#include <Library/QuarkBootRomLib.h>
+
+EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoSecurityList = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiFirmwareVolumeInfoPpiGuid,
+ FirmwareVolmeInfoPpiNotifySecurityCallback
+};
+
+/**
+ Callback function to perform FV security checking on a FV Info PPI.
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param NotifyDescriptor Address of the notification descriptor data structure.
+ @param Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+FirmwareVolmeInfoPpiNotifySecurityCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;
+ EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
+
+ FvInfoPpi = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;
+
+ //
+ // Locate the corresponding FV_PPI according to founded FV's format guid
+ //
+ Status = PeiServicesLocatePpi (
+ &FvInfoPpi->FvFormat,
+ 0,
+ NULL,
+ (VOID**)&FvPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Don't authenticate FlashFvRecovery2 since already checked at the same time
+ // as the main recovery stage1 FV.
+ //
+ if (((UINTN) FvInfoPpi->FvInfo) == ((UINTN) FixedPcdGet32 (PcdFlashFvRecovery2Base))) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Only authenticate parent Firmware Volume (child firmware volumes are covered by the parent)
+ //
+ if ((VOID *)FvInfoPpi->ParentFvName == NULL && (VOID *)FvInfoPpi->ParentFileName == NULL) {
+ Status = PeiSecurityVerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) FvInfoPpi->FvInfo);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Authenticates the Firmware Volume
+
+ @param CurrentFvAddress Pointer to the current Firmware Volume under consideration
+
+ @retval EFI_SUCCESS Firmware Volume is legal
+
+**/
+EFI_STATUS
+PeiSecurityVerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Call Security library to authenticate the Firmware Volume
+ //
+ DEBUG ((DEBUG_INFO, "PeiSecurityVerifyFv - CurrentFvAddress=0x%8x\n", (UINT32)CurrentFvAddress));
+ Status = SecurityAuthenticateImage(
+ (VOID *) CurrentFvAddress,
+ NULL,
+ TRUE,
+ NULL,
+ (QUARK_AUTH_ALLOC_POOL) AllocatePool,
+ (QUARK_AUTH_FREE_POOL) FreePool
+ );
+
+ return Status;
+}
+
+/**
+
+ Entry point for the PEI Security PEIM
+ Sets up a notification to perform PEI security checking
+
+ @param FfsHeader Not used.
+ @param PeiServices General purpose services available to every PEIM.
+
+ @return EFI_SUCCESS PEI Security notification installed successfully.
+ All others: PEI Security notification failed to install.
+
+**/
+EFI_STATUS
+PeiInitializeFvSecurity (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesNotifyPpi (&mNotifyOnFvInfoSecurityList);
+
+ return Status;
+}
+
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/PeiFvSecurity.h b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PeiFvSecurity.h
new file mode 100644
index 0000000..a777251
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PeiFvSecurity.h
@@ -0,0 +1,91 @@
+/** @file
+ Definition of Pei Core Structures and Services
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _PEI_FV_SECURITY_H_
+#define _PEI_FV_SECURITY_H_
+
+#include <Ppi/FirmwareVolume.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+ Callback function to perform FV security checking on a FV Info PPI.
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param NotifyDescriptor Address of the notification descriptor data structure.
+ @param Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+FirmwareVolmeInfoPpiNotifySecurityCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ Authenticates the Firmware Volume
+
+ @param CurrentFvAddress Pointer to the current Firmware Volume under consideration
+
+ @retval EFI_SUCCESS Firmware Volume is legal
+
+**/
+EFI_STATUS
+PeiSecurityVerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress
+ );
+
+/**
+
+ Entry point for the PEI Security PEIM
+ Sets up a notification to perform PEI security checking
+
+ @param FfsHeader Not used.
+ @param PeiServices General purpose services available to every PEIM.
+
+ @return EFI_SUCCESS PEI Security notification installed successfully.
+ All others: PEI Security notification failed to install.
+
+**/
+EFI_STATUS
+PeiInitializeFvSecurity (
+ VOID
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.c
new file mode 100755
index 0000000..4d5ad75
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.c
@@ -0,0 +1,703 @@
+/** @file
+ This PEIM initialize platform for MRC, following action is performed,
+ 1. Initizluize GMCH
+ 2. Detect boot mode
+ 3. Detect video adapter to determine whether we need pre allocated memory
+ 4. Calls MRC to initialize memory and install a PPI notify to do post memory initialization.
+ This file contains the main entrypoint of the PEIM.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "CommonHeader.h"
+#include "PlatformEarlyInit.h"
+#include "PeiFvSecurity.h"
+
+EFI_STATUS
+EFIAPI
+EndOfPeiSignalPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+//
+// Function prototypes to routines implemented in other source modules
+// within this component.
+//
+
+EFI_STATUS
+EFIAPI
+PlatformErratasPostMrc (
+ VOID
+ );
+
+//
+// The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory
+//
+BOOLEAN ImageInMemory = FALSE;
+
+BOARD_LEGACY_GPIO_CONFIG mBoardLegacyGpioConfigTable[] = { PLATFORM_LEGACY_GPIO_TABLE_DEFINITION };
+UINTN mBoardLegacyGpioConfigTableLen = (sizeof(mBoardLegacyGpioConfigTable) / sizeof(BOARD_LEGACY_GPIO_CONFIG));
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[1] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMasterBootModePpiGuid,
+ NULL
+ }
+};
+
+EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ MemoryDiscoveredPpiNotifyCallback
+ }
+};
+
+EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiSignalPpiNotifyList[1] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ EndOfPeiSignalPpiNotifyCallback
+ }
+};
+
+EFI_PEI_STALL_PPI mStallPpi = {
+ PEI_STALL_RESOLUTION,
+ Stall
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiStall[1] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiStallPpiGuid,
+ &mStallPpi
+ }
+};
+
+/**
+ This is the entrypoint of PEIM
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+PeiInitPlatform (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ EFI_PEI_STALL_PPI *StallPpi;
+ EFI_PEI_PPI_DESCRIPTOR *StallPeiPpiDescriptor;
+ EFI_FV_FILE_INFO FileInfo;
+ EFI_PLATFORM_INFO *PlatformInfo;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_PLATFORM_TYPE PlatformType;
+
+ GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
+ PlatformInfo = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (PlatformInfo != NULL);
+ PlatformType = (EFI_PLATFORM_TYPE) PlatformInfo->Type;
+
+ //
+ // Initialize Firmware Volume security.
+ // This must be done before any firmware volume accesses (excl. BFV)
+ //
+ Status = PeiInitializeFvSecurity();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Allocate an initial buffer from heap for debugger use
+ //
+ DEBUG_CODE (
+ BpeDsAllocation ();
+ );
+
+ //
+ // Do any early platform specific initialisation
+ //
+ EarlyPlatformInit (PlatformType);
+
+ //
+ // This is a second path on entry, in recovery boot path the Stall PPI need to be memory-based
+ // to improve recovery performance.
+ //
+ Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // The follow conditional check only works for memory-mapped FFS,
+ // so we ASSERT that the file is really a MM FFS.
+ //
+ ASSERT (FileInfo.Buffer != NULL);
+ if (!(((UINTN) FileInfo.Buffer <= (UINTN) PeiInitPlatform) &&
+ ((UINTN) PeiInitPlatform <= (UINTN) FileInfo.Buffer + FileInfo.BufferSize))) {
+ //
+ // Now that module in memory, update the
+ // PPI that describes the Stall to other modules
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiStallPpiGuid,
+ 0,
+ &StallPeiPpiDescriptor,
+ (VOID **) &StallPpi
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ Status = PeiServicesReInstallPpi (
+ StallPeiPpiDescriptor,
+ &mPpiStall[0]
+ );
+ } else {
+
+ Status = PeiServicesInstallPpi (&mPpiStall[0]);
+ }
+ return Status;
+ }
+
+ //
+ // Initialise System Phys
+ //
+
+ // Program USB Phy
+ InitializeUSBPhy();
+
+ //
+ // Do platform specific logic to create a boot mode
+ //
+ Status = UpdateBootMode ((EFI_PEI_SERVICES**)PeiServices, &BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Signal possible dependent modules that there has been a
+ // final boot mode determination
+ //
+ if (!EFI_ERROR(Status)) {
+ Status = PeiServicesInstallPpi (&mPpiBootMode[0]);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ QNCClearSmiAndWake ();
+ }
+
+ //
+ // Create the platform Flash Map
+ //
+ Status = PeimInitializeFlashMap (FileHandle, PeiServices);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeimInstallFlashMapPpi (FileHandle, PeiServices);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "MRC Entry\n"));
+ MemoryInit ((EFI_PEI_SERVICES**)PeiServices);
+
+ //
+ // Do Early PCIe init if not GalileoFabE Platform.
+ //
+ if (PlatformType != GalileoFabE) {
+ DEBUG ((EFI_D_INFO, "Early PCIe controller initialisation\n"));
+ PlatformPciExpressEarlyInit (PlatformType);
+ }
+
+ DEBUG ((EFI_D_INFO, "Platform Erratas After MRC\n"));
+ PlatformErratasPostMrc ();
+
+ //
+ // Now that all of the pre-permament memory activities have
+ // been taken care of, post a call-back for the permament-memory
+ // resident services, such as HOB construction.
+ // PEI Core will switch stack after this PEIM exit. After that the MTRR
+ // can be set.
+ //
+ Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList[0]);
+ ASSERT_EFI_ERROR (Status);
+/*
+
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ Status = PeiServicesNotifyPpi (mEndOfPeiSignalPpiNotifyList);
+ ASSERT_EFI_ERROR (Status);
+ }
+*/
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ PeiServicesRegisterForShadow (FileHandle);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+EndOfPeiSignalPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_INFO, "End of PEI Signal Callback\n"));
+
+ //
+ // Restore the flash region to be UC
+ // for both normal boot as we build a Resource Hob to
+ // describe this region as UC to DXE core.
+ //
+ WriteBackInvalidateDataCacheRange (
+ (VOID *) (UINTN) PcdGet32 (PcdFlashAreaBaseAddress),
+ PcdGet32 (PcdFlashAreaSize)
+ );
+
+ Status = MtrrSetMemoryAttribute (PcdGet32 (PcdFlashAreaBaseAddress), PcdGet32 (PcdFlashAreaSize), CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will initialize USB Phy registers associated with QuarkSouthCluster.
+
+ @param VOID No Argument
+
+ @retval EFI_SUCCESS All registers have been initialized
+**/
+VOID
+EFIAPI
+InitializeUSBPhy (
+ VOID
+ )
+{
+ UINT32 RegData32;
+
+ /** In order to configure the PHY to use clk120 (ickusbcoreclk) as PLL reference clock
+ * and Port2 as a USB device port, the following sequence must be followed
+ *
+ **/
+
+ // Sideband register write to USB AFE (Phy)
+ RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_GLOBAL_PORT);
+ RegData32 &= ~(BIT1);
+ //
+ // Sighting #4930631 PDNRESCFG [8:7] of USB2_GLOBAL_PORT = 11b.
+ // For port 0 & 1 as host and port 2 as device.
+ //
+ RegData32 |= (BIT8 | BIT7);
+ QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_GLOBAL_PORT, RegData32);
+
+ //
+ // Sighting #4930653 Required BIOS change on Disconnect vref to change to 600mV.
+ //
+ RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_COMPBG);
+ RegData32 &= ~(BIT10 | BIT9 | BIT8 | BIT7);
+ RegData32 |= (BIT10 | BIT7);
+ QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_COMPBG, RegData32);
+
+ // Sideband register write to USB AFE (Phy)
+ // (pllbypass) to bypass/Disable PLL before switch
+ RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
+ RegData32 |= BIT29;
+ QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
+
+ // Sideband register write to USB AFE (Phy)
+ // (coreclksel) to select 120MHz (ickusbcoreclk) clk source.
+ // (Default 0 to select 96MHz (ickusbclk96_npad/ppad))
+ RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1);
+ RegData32 |= BIT1;
+ QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1, RegData32);
+
+ // Sideband register write to USB AFE (Phy)
+ // (divide by 8) to achieve internal 480MHz clock
+ // for 120MHz input refclk. (Default: 4'b1000 (divide by 10) for 96MHz)
+ RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1);
+ RegData32 &= ~(BIT5 | BIT4 | BIT3);
+ RegData32 |= BIT6;
+ QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1, RegData32);
+
+ // Sideband register write to USB AFE (Phy)
+ // Clear (pllbypass)
+ RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
+ RegData32 &= ~BIT29;
+ QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
+
+ // Sideband register write to USB AFE (Phy)
+ // Set (startlock) to force the PLL FSM to restart the lock
+ // sequence due to input clock/freq switch.
+ RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
+ RegData32 |= BIT24;
+ QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
+
+ // At this point the PLL FSM and COMP FSM will complete
+
+}
+
+/**
+ This function provides early platform Thermal sensor initialisation.
+**/
+VOID
+EFIAPI
+EarlyPlatformThermalSensorInit (
+ VOID
+ )
+{
+ DEBUG ((EFI_D_INFO, "Early Platform Thermal Sensor Init\n"));
+
+ //
+ // Set Thermal sensor mode.
+ //
+ QNCThermalSensorSetRatiometricMode ();
+
+ //
+ // Enable RMU Thermal sensor with a Catastrophic Trip point.
+ //
+ QNCThermalSensorEnableWithCatastrophicTrip (PLATFORM_CATASTROPHIC_TRIP_CELSIUS);
+
+ //
+ // Lock all RMU Thermal sensor control & trip point registers.
+ //
+ QNCThermalSensorLockAllRegisters ();
+}
+
+/**
+ Print early platform info messages includeing the Stage1 module that's
+ running, MFH item list and platform data item list.
+**/
+VOID
+EFIAPI
+EarlyPlatformInfoMessages (
+ VOID
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ QUARK_EDKII_STAGE1_HEADER *Edk2ImageHeader;
+ MFH_LIB_FINDCONTEXT MfhFindContext;
+ MFH_FLASH_ITEM *FlashItem;
+ PDAT_ITEM *Item;
+ PDAT_LIB_FINDCONTEXT PDatFindContext;
+ CHAR8 Desc[PDAT_ITEM_DESC_LENGTH+1];
+
+ //
+ // Find which 'Stage1' image we are running and print the details
+ //
+ Edk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) (FixedPcdGet32 (PcdEsramStage1Base) + FixedPcdGet32 (PcdFvSecurityHeaderSize));
+ DEBUG ((EFI_D_INFO, "\n************************************************************\n"));
+
+ if(FeaturePcdGet (PcdEnableSecureLock)) {
+ DEBUG ((EFI_D_INFO, "**** Quark EDKII SECURE LOCKDOWN ENABLED ****\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "**** Quark EDKII SECURE LOCKDOWN DISABLED ****\n"));
+ }
+
+ switch ((UINT8)Edk2ImageHeader->ImageIndex & QUARK_STAGE1_IMAGE_TYPE_MASK) {
+ case QUARK_STAGE1_BOOT_IMAGE_TYPE:
+ DEBUG ((EFI_D_INFO, "**** Quark EDKII Stage 1 Boot Image %d ****\n", ((UINT8)Edk2ImageHeader->ImageIndex & ~(QUARK_STAGE1_IMAGE_TYPE_MASK))));
+ break;
+
+ case QUARK_STAGE1_RECOVERY_IMAGE_TYPE:
+ DEBUG ((EFI_D_INFO, "**** Quark EDKII Stage 1 Recovery Image %d ****\n", ((UINT8)Edk2ImageHeader->ImageIndex & ~(QUARK_STAGE1_IMAGE_TYPE_MASK))));
+ break;
+
+ default:
+ DEBUG ((EFI_D_INFO, "**** Quark EDKII Unknown Stage 1 Image !!!! ****\n"));
+ break;
+ }
+ DEBUG (
+ (EFI_D_INFO,
+ "**** Quark EDKII Stage 2 Image 0x%08X:0x%08X ****\n" ,
+ (UINTN) PcdGet32 (PcdFlashFvMainBase),
+ (UINTN) PcdGet32 (PcdFlashFvMainSize)
+ ));
+
+ DEBUG (
+ (EFI_D_INFO,
+ "**** Quark EDKII Payload Image 0x%08X:0x%08X ****\n" ,
+ (UINTN) PcdGet32 (PcdFlashFvPayloadBase),
+ (UINTN) PcdGet32 (PcdFlashFvPayloadSize)
+ ));
+
+ DEBUG ((EFI_D_INFO, "************************************************************\n\n"));
+
+ DEBUG ((EFI_D_INFO, "MFH Flash Item List:\n"));
+ FlashItem = MfhLibFindFirstWithFilter (
+ MFH_FIND_ANY_FIT_FILTER,
+ FALSE,
+ &MfhFindContext
+ );
+ while (FlashItem != NULL) {
+ DEBUG ((EFI_D_INFO, "**** Quark 0x%08X:0x%08X %s ****\n", FlashItem->FlashAddress, FlashItem->LengthBytes, MfhLibFlashItemTypePrintString(FlashItem->Type)));
+ FlashItem = MfhLibFindNextWithFilter (
+ MFH_FIND_ANY_FIT_FILTER,
+ &MfhFindContext
+ );
+ }
+ DEBUG ((EFI_D_INFO, "MFH Boot Priority List:\n"));
+ FlashItem = MfhLibFindFirstWithFilter (
+ MFH_FIND_ALL_STAGE1_FILTER,
+ TRUE,
+ &MfhFindContext
+ );
+ while (FlashItem != NULL) {
+ DEBUG ((EFI_D_INFO, "**** Quark 0x%08X:0x%08X %s ****\n", FlashItem->FlashAddress, FlashItem->LengthBytes, MfhLibFlashItemTypePrintString(FlashItem->Type)));
+ FlashItem = MfhLibFindNextWithFilter (
+ MFH_FIND_ALL_STAGE1_FILTER,
+ &MfhFindContext
+ );
+ }
+
+ DEBUG ((EFI_D_INFO, "\nPlatform Data Item List in System Area:\n"));
+ Item = PDatLibFindFirstWithFilter (NULL, PDAT_FIND_ANY_ITEM_FILTER, &PDatFindContext, NULL);
+ if (Item != NULL) {
+ Desc[PDAT_ITEM_DESC_LENGTH] = 0;
+ do {
+ CopyMem (Desc, Item->Header.Description, PDAT_ITEM_DESC_LENGTH);
+ DEBUG ((EFI_D_INFO, "**** Quark Data Id:Len = 0x%04X:0x%04X Desc = %a Ver=%04x ****\n", Item->Header.Identifier, Item->Header.Length, Desc, (UINTN) Item->Header.Version));
+ Item = PDatLibFindNextWithFilter(PDAT_FIND_ANY_ITEM_FILTER, &PDatFindContext, NULL);
+ } while (Item != NULL);
+ }
+ DEBUG ((EFI_D_INFO, "*************************************************\n\n"));
+
+ DEBUG_CODE_END ();
+}
+
+/**
+ Check if system reset due to error condition.
+
+ @param ClearErrorBits If TRUE clear error flags and value bits.
+
+ @retval TRUE if system reset due to error condition.
+ @retval FALSE if NO reset error conditions.
+**/
+BOOLEAN
+CheckForResetDueToErrors (
+ IN BOOLEAN ClearErrorBits
+ )
+{
+ UINT32 RegValue;
+ BOOLEAN ResetDueToError;
+
+ ResetDueToError = FALSE;
+
+ //
+ // Check if RMU reset system due to access violations.
+ // RMU updates a SOC Unit register before reseting the system.
+ //
+ RegValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW);
+ if ((RegValue & B_CFG_STICKY_RW_VIOLATION) != 0) {
+ ResetDueToError = TRUE;
+
+ DEBUG (
+ (EFI_D_ERROR,
+ "\nReset due to access violation: %s %s %s %s\n",
+ ((RegValue & B_CFG_STICKY_RW_IMR_VIOLATION) != 0) ? L"'IMR'" : L".",
+ ((RegValue & B_CFG_STICKY_RW_DECC_VIOLATION) != 0) ? L"'DECC'" : L".",
+ ((RegValue & B_CFG_STICKY_RW_SMM_VIOLATION) != 0) ? L"'SMM'" : L".",
+ ((RegValue & B_CFG_STICKY_RW_HMB_VIOLATION) != 0) ? L"'HMB'" : L"."
+ ));
+
+ //
+ // Clear error bits.
+ //
+ if (ClearErrorBits) {
+ RegValue &= ~(B_CFG_STICKY_RW_VIOLATION);
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW, RegValue);
+ }
+ }
+
+ return ResetDueToError;
+}
+
+/**
+ This function provides early platform initialisation.
+
+ @param PlatformType Platform type to init.
+
+**/
+VOID
+EFIAPI
+EarlyPlatformInit (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+{
+
+ //
+ // Check if system reset due to error condition.
+ //
+ if (CheckForResetDueToErrors (TRUE)) {
+ if(FeaturePcdGet (WaitIfResetDueToError)) {
+ DEBUG ((EFI_D_ERROR, "Press any key to continue.\n"));
+ PlatformDebugPortGetChar8 ();
+ }
+ }
+
+ //
+ // Display platform info messages.
+ //
+ EarlyPlatformInfoMessages ();
+
+ //
+ // Early Gpio Init.
+ //
+ EarlyPlatformGpioInit (PlatformType);
+
+ //
+ // Early platform GPIO manipulation depending on GPIOs
+ // setup by EarlyPlatformGpioInit.
+ //
+ EarlyPlatformGpioManipulation (PlatformType);
+
+ //
+ // Early Thermal Sensor Init.
+ //
+ EarlyPlatformThermalSensorInit ();
+
+ //
+ // Init Redirect PEI services.
+ //
+ RedirectServicesInit ();
+
+}
+
+/**
+ This function provides early platform GPIO initialisation.
+
+ @param PlatformType Platform type for GPIO init.
+
+**/
+VOID
+EFIAPI
+EarlyPlatformGpioInit (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+{
+ BOARD_LEGACY_GPIO_CONFIG *LegacyGpioConfig;
+ UINT32 NewValue;
+ UINT32 GpioBaseAddress;
+
+ //
+ // Assert if platform type outside table range.
+ //
+ ASSERT ((UINTN) PlatformType < mBoardLegacyGpioConfigTableLen);
+
+ LegacyGpioConfig = &mBoardLegacyGpioConfigTable[(UINTN) PlatformType];
+ DEBUG ((EFI_D_INFO, "EarlyPlatformGpioInit for PlatType=0x%02x\n", (UINTN) PlatformType));
+
+ GpioBaseAddress = (UINT32)PcdGet16 (PcdGbaIoBaseAddress);
+
+ NewValue = 0x0;
+ //
+ // Program QNC GPIO Registers.
+ //
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGEN_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellEnable;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGEN_CORE_WELL, NewValue );
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGIO_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellIoSelect;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGIO_CORE_WELL, NewValue);
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGLVL_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellLvlForInputOrOutput;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGLVL_CORE_WELL, NewValue);
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTPE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerPositiveEdge;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTPE_CORE_WELL, NewValue );
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTNE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerNegativeEdge;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTNE_CORE_WELL, NewValue);
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGGPE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellGPEEnable;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGGPE_CORE_WELL, NewValue);
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGSMI_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellSMIEnable;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGSMI_CORE_WELL, NewValue );
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTS_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerStatus;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTS_CORE_WELL, NewValue);
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CNMIEN_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellNMIEnable;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CNMIEN_CORE_WELL, NewValue);
+
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGEN_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellEnable;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGEN_RESUME_WELL, NewValue );
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGIO_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellIoSelect;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGIO_RESUME_WELL, NewValue) ;
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellLvlForInputOrOutput;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL, NewValue);
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTPE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerPositiveEdge;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTPE_RESUME_WELL, NewValue );
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTNE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerNegativeEdge;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTNE_RESUME_WELL, NewValue) ;
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGGPE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellGPEEnable;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGGPE_RESUME_WELL, NewValue);
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGSMI_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellSMIEnable;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGSMI_RESUME_WELL, NewValue );
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTS_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerStatus;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTS_RESUME_WELL, NewValue) ;
+ NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RNMIEN_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellNMIEnable;
+ IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RNMIEN_RESUME_WELL, NewValue);
+}
+
+/**
+ Performs any early platform specific GPIO manipulation.
+
+ @param PlatformType Platform type GPIO manipulation.
+
+**/
+VOID
+EFIAPI
+EarlyPlatformGpioManipulation (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ )
+{
+ if (PlatformType == CrossHill) {
+
+ //
+ // Pull TPM reset low for 80us (equivalent to cold reset, Table 39
+ // Infineon SLB9645 Databook), then pull TPM reset high and wait for
+ // 150ms to give time for TPM to stabilise (Section 4.7.1 Infineon
+ // SLB9645 Databook states TPM is ready to receive command after 30ms
+ // but section 4.7 states some TPM commands may take longer to execute
+ // upto 150ms after test).
+ //
+
+ PlatformLegacyGpioSetLevel (
+ R_QNC_GPIO_RGLVL_RESUME_WELL,
+ PLATFORM_RESUMEWELL_TPM_RST_GPIO,
+ FALSE
+ );
+ MicroSecondDelay (80);
+
+ PlatformLegacyGpioSetLevel (
+ R_QNC_GPIO_RGLVL_RESUME_WELL,
+ PLATFORM_RESUMEWELL_TPM_RST_GPIO,
+ TRUE
+ );
+ MicroSecondDelay (150000);
+ }
+
+}
+
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.h b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.h
new file mode 100755
index 0000000..367e0c4
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.h
@@ -0,0 +1,311 @@
+/** @file
+ The header file of Platform PEIM.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#ifndef __PLATFORM_EARLY_INIT_H__
+#define __PLATFORM_EARLY_INIT_H__
+
+#define PEI_STALL_RESOLUTION 1
+#define STALL_PEIM_SIGNATURE SIGNATURE_32('p','p','u','s')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ EFI_PEI_NOTIFY_DESCRIPTOR StallNotify;
+} STALL_CALLBACK_STATE_INFORMATION;
+
+#define STALL_PEIM_FROM_THIS(a) CR (a, STALL_CALLBACK_STATE_INFORMATION, StallNotify, STALL_PEIM_SIGNATURE)
+
+//
+// USB Phy Registers
+//
+#define USB2_GLOBAL_PORT 0x4001
+#define USB2_PLL1 0x7F02
+#define USB2_PLL2 0x7F03
+#define USB2_COMPBG 0x7F04
+
+/**
+ Peform the boot mode determination logic
+ If the box is closed, then
+ 1. If it's first time to boot, it's boot with full config .
+ 2. If the ChassisIntrution is selected, force to be a boot with full config
+ 3. Otherwise it's boot with no change.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @param BootMode The detected boot mode.
+
+ @retval EFI_SUCCESS if the boot mode could be set
+**/
+EFI_STATUS
+UpdateBootMode (
+ IN EFI_PEI_SERVICES **PeiServices,
+ OUT EFI_BOOT_MODE *BootMode
+ );
+
+/**
+ This function reset the entire platform, including all processor and devices, and
+ reboots the system.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+ResetSystem (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ );
+
+/**
+ This function will be called when MRC is done.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @param NotifyDescriptor Information about the notify event..
+
+ @param Ppi The notify context.
+
+ @retval EFI_SUCCESS If the function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+MemoryDiscoveredPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ This is the callback function notified by FvFileLoader PPI, it depends on FvFileLoader PPI to load
+ the PEIM into memory.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param NotifyDescriptor The context of notification.
+ @param Ppi The notify PPI.
+
+ @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+FvFileLoaderPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ This function provides a blocking stall for reset at least the given number of microseconds
+ stipulated in the final argument.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @param this Pointer to the local data for the interface.
+
+ @param Microseconds number of microseconds for which to stall.
+
+ @retval EFI_SUCCESS the function provided at least the required stall.
+**/
+EFI_STATUS
+EFIAPI
+Stall (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_STALL_PPI *This,
+ IN UINTN Microseconds
+ );
+
+EFI_STATUS
+PeimInitializeFlashMap (
+ IN EFI_PEI_FILE_HANDLE *FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ );
+
+EFI_STATUS
+PeimInstallFlashMapPpi (
+ IN EFI_PEI_FILE_HANDLE *FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ );
+
+/**
+ This function initialize recovery functionality by installing the recovery PPI.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS if the interface could be successfully installed.
+**/
+EFI_STATUS
+EFIAPI
+PeimInitializeRecovery (
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+/**
+ This function
+ 1. Calling MRC to initialize memory.
+ 2. Install EFI Memory.
+ 3. Create HOB of system memory.
+
+ @param PeiServices Pointer to the PEI Service Table
+
+ @retval EFI_SUCCESS If it completes successfully.
+
+**/
+EFI_STATUS
+MemoryInit (
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+/** Return info derived from Installing Memory by MemoryInit.
+
+ @param[out] RmuMainBaseAddressPtr Return RmuMainBaseAddress to this location.
+ @param[out] SmramDescriptorPtr Return start of Smram descriptor list to this location.
+ @param[out] NumSmramRegionsPtr Return numbers of Smram regions to this location.
+
+ @return Address of RMU shadow region at the top of available memory.
+ @return List of Smram descriptors for each Smram region.
+ @return Numbers of Smram regions.
+**/
+VOID
+EFIAPI
+InfoPostInstallMemory (
+ OUT UINT32 *RmuMainBaseAddressPtr OPTIONAL,
+ OUT EFI_SMRAM_DESCRIPTOR **SmramDescriptorPtr OPTIONAL,
+ OUT UINTN *NumSmramRegionsPtr OPTIONAL
+ );
+
+/**
+ This function provides the implementation of AtaController PPI Enable Channel function.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param this Pointer to the local data for the interface.
+ @param ChannelMask This parameter is used to specify primary or slavery IDE channel.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+**/
+
+EFI_STATUS
+EnableAtaChannel (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_ATA_CONTROLLER_PPI *This,
+ IN UINT8 ChannelMask
+ );
+
+/**
+ This function provides the implementation of AtaController PPI Get IDE channel Register Base Address
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param this Pointer to the local data for the interface.
+ @param IdeRegsBaseAddr Pointer to IDE_REGS_BASE_ADDR struct, which is used to record
+ IDE Command and Control regeisters Base Address.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+**/
+
+EFI_STATUS
+GetIdeRegsBaseAddr (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_ATA_CONTROLLER_PPI *This,
+ IN IDE_REGS_BASE_ADDR *IdeRegsBaseAddr
+ );
+
+VOID
+EFIAPI
+InitializeUSBPhy (
+ VOID
+ );
+
+/**
+ This function provides early platform initialisation.
+
+ @param PlatformType Platform type to init.
+
+**/
+VOID
+EFIAPI
+EarlyPlatformInit (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+/**
+ This function provides early platform GPIO initialisation.
+
+ @param PlatformType Platform type for GPIO init.
+
+**/
+VOID
+EFIAPI
+EarlyPlatformGpioInit (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+/**
+ Performs any early platform specific GPIO manipulation.
+
+ @param PlatformType Platform type GPIO manipulation.
+
+**/
+VOID
+EFIAPI
+EarlyPlatformGpioManipulation (
+ IN CONST EFI_PLATFORM_TYPE PlatformType
+ );
+
+/**
+ Find security headers using EFI_CAPSULE_VARIABLE_NAME variables and build Hobs.
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @retval 0 if no security headers found.
+ @return number of security header hobs built.
+**/
+UINTN
+EFIAPI
+FindCapsuleSecurityHeadersAndBuildHobs (
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+/**
+ Build capsule security header hob.
+
+ @param SecHdr Pointer to security header.
+
+ @retval NULL if failure to build HOB.
+ @return pointer to built hob.
+**/
+VOID *
+EFIAPI
+BuildCapsuleSecurityHeaderHob (
+ IN VOID *SecHdr
+ );
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf
new file mode 100755
index 0000000..c83d773
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf
@@ -0,0 +1,234 @@
+## @file
+# This is the Platform PEIM to initialize whole platform on PEI phase.
+#
+# This PEIM includes 3 parts, pre memory initialization, MRC
+# wrapper and post memory initialization.
+# On pre memory, following action is performed,
+# 1. Initizluize GMCH.
+# 2. Detect boot mode.
+# 3. Detect video adapter to determine whether we need pre allocated
+# memory.
+#
+# After that MRC wrapper calls MRC to initialize memory and install a PPI
+# notify to do post memory
+# initialization. MRC wrapper performance following actions,
+# 1. Install EFI Memory.
+# 2. Create HOB of system memory.
+#
+# On post memory, following action is performed,
+# 1. QNC initialization after MRC.
+# 2. SIO initialization.
+# 3. Install ResetSystem and FinvFv PPI, relocate Stall to memory on
+# recovery boot mode.
+# 4. Set MTRR for PEI
+# 5. Create FV HOB and Flash HOB
+# 6. Install RecoveryModule and AtaController PPI if on recovery boot mode.
+#
+# This PEIM does not have any register access directly, it depends on
+# IntelQNCLib, QNCAccess libraries to access Chipset
+# registers.
+#
+# Platform.c - Provide main flow and entrypoint of PEIM.
+# MemoryCallback.c - Includes a memory call back function notified when
+# MRC is done.
+# Recovery.c - provides the platform recoveyr functionality.
+# MrcWrapper.c - Contains the logic to call MRC PPI and do Framework
+# memory specific stuff like build memory map, build
+# resource description hob for DXE phase,etc.
+# Bootmode.c - Detect boot mode.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformEarlyInitPei
+ FILE_GUID = 9618C0DC-50A4-496c-994F-7241F282ED01
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PeiInitPlatform
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ Generic/Recovery.c
+ PlatformErratas.c
+ MrcWrapper.c
+ MrcWrapper.h
+ Common/FlashMap.c
+ PlatformEarlyInit.c
+ PlatformEarlyInit.h
+ MemoryCallback.c
+ BootMode.c
+ CommonHeader.h
+ PeiFvSecurity.c
+ PeiFvSecurity.h
+ Capsule.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ ResetSystemLib
+ PrintLib
+ TimerLib
+ RecoveryOemHookLib
+ PcdLib
+ IntelQNCLib
+ IohLib
+ ReportStatusCodeLib
+ PciLib
+ PciExpressLib
+ IoLib
+ PciCf8Lib
+ HobLib
+ BaseMemoryLib
+ PeiServicesTablePointerLib
+ PeiServicesLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ MemoryAllocationLib
+ PerformanceLib
+ CacheMaintenanceLib
+ MtrrLib
+ QNCAccessLib
+ SwBpeLib
+ MfhLib
+ PlatformHelperLib
+ PlatformPcieHelperLib
+ PlatformDataLib
+ SecurityAuthenticationLib
+ RedirectPeiServicesLib
+
+[Guids]
+ gEfiMemoryConfigDataGuid # ALWAYS_CONSUMED L"MemoryConfig"
+ gEfiAcpiVariableGuid # ALWAYS_CONSUMED L"AcpiGlobalVariab"
+ gEfiMemoryTypeInformationGuid # ALWAYS_CONSUMED L"MemoryTypeInformation"
+ gEfiFlashMapHobGuid
+ gEfiPlatformMemoryLayoutGuid # ALWAYS_PRODUCED Hob: GUID_EXTENSION
+ gEfiMemoryConfigDataGuid # SOMETIMES_PRODUCED Hob: GUID_EXTENSION
+ gEfiSmmPeiSmramMemoryReserveGuid # ALWAYS_PRODUCED Hob: GUID_EXTENSION
+ gEfiFirmwareFileSystem2Guid # ALWAYS_CONSUMED
+ gEfiCapsuleGuid # ALWAYS_CONSUMED
+ gPeiCapsuleOnDataCDGuid
+ gPeiCapsuleOnFatIdeDiskGuid
+ gPeiCapsuleOnFatUsbDiskGuid
+ gEfiPciGInfoHobGuid
+ gEfiMemoryOverwriteControlDataGuid # SOMETIMES_CONSUMED
+ gEfiPlatformInfoGuid
+ gEfiQuarkCapsuleGuid
+ gEfiQuarkCapsuleSecurityHeaderGuid
+ gEfiCapsuleVendorGuid
+
+[Ppis]
+ gCltMemoryInitPpiGuid # PPI ALWAYS_CONSUMED
+ gEfiPeiMemoryDiscoveredPpiGuid # PPI ALWAYS_PRODUCED
+ gPeiAtaControllerPpiGuid # PPI SOMETIMES_PRODUCED
+ gEfiPeiStallPpiGuid # PPI ALWAYS_PRODUCED
+ gPeiFlashMapPpiGuid
+ gEfiPeiDeviceRecoveryModulePpiGuid # PPI SOMETIMES_CONSUMED
+ gEfiPeiRecoveryModulePpiGuid # PPI SOMETIMES_PRODUCED
+ gEfiPeiResetPpiGuid # PPI ALWAYS_PRODUCED
+ gEfiPeiReadOnlyVariable2PpiGuid # PPI ALWAYS_CONSUMED
+ gEfiPeiBootInRecoveryModePpiGuid # PPI SOMETIMES_PRODUCED
+ gEfiPeiMasterBootModePpiGuid # PPI ALWAYS_PRODUCED
+ gPeiSStateBootModePpiGuid
+ gEfiPeiFirmwareVolumeInfoPpiGuid
+ gEfiEndOfPeiSignalPpiGuid
+ gEfiPeiVirtualBlockIoPpiGuid
+ gPeiCapsulePpiGuid # PPI ALWAYS_CONSUMED
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryOnFatUsbDisk
+ gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryOnDataCD
+ gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryOnFatFloppyDisk
+ gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryOnIdeDisk
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock
+ gQuarkPlatformTokenSpaceGuid.WaitIfResetDueToError
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+ gQuarkPlatformTokenSpaceGuid.PcdEsramStage1Base
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdEccScrubBlkSize
+ gQuarkPlatformTokenSpaceGuid.PcdEccScrubInterval
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecovery2Size
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecovery2Base
+ gQuarkPlatformTokenSpaceGuid.PcdEnableFastBoot
+ gQuarkPlatformTokenSpaceGuid.PcdFlashQNCMicrocodeSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeIoBase
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeIoSize
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartFunctionNumber
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartBusNumber
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartDevNumber
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiQNCUsbControllerMemoryBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory32Base
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory32Size
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory64Base
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory64Size
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciExpressSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkMicrocodeFile
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdTSegSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdESramMemorySize
+
+[Pcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoverySize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoveryBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainBase
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState
+ gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadSize
+
+[Depex]
+ gEfiPeiReadOnlyVariable2PpiGuid AND gCltMemoryInitPpiGuid
diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformErratas.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformErratas.c
new file mode 100644
index 0000000..105230c
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformErratas.c
@@ -0,0 +1,203 @@
+/** @file
+ Platform Erratas performed by early init PEIM driver.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+#include "PlatformEarlyInit.h"
+
+//
+// Constants.
+//
+
+//
+// Platform EHCI Packet Buffer OUT/IN Thresholds, values in number of DWORDs.
+//
+#define EHCI_OUT_THRESHOLD_VALUE (0x7f)
+#define EHCI_IN_THRESHOLD_VALUE (0x7f)
+
+//
+// Platform init USB device interrupt masks.
+//
+#define V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG (0x0000007f)
+#define V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG (B_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG_OUT_EP_MASK | B_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG_IN_EP_MASK)
+
+//
+// Global variables defined within this source module.
+//
+
+UINTN IohEhciPciReg[IOH_MAX_EHCI_USB_CONTROLLERS] = {
+ PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, 0),
+};
+
+UINTN IohUsbDevicePciReg[IOH_MAX_USBDEVICE_USB_CONTROLLERS] = {
+ PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USBDEVICE_DEVICE_NUMBER, IOH_USBDEVICE_FUNCTION_NUMBER, 0),
+};
+
+//
+// Routines local to this source module.
+//
+
+/** Perform USB erratas after MRC init.
+
+**/
+STATIC
+VOID
+PlatformUsbErratasPostMrc (
+ VOID
+ )
+{
+ UINT32 Index;
+ UINT32 TempBar0Addr;
+ UINT16 SaveCmdReg;
+ UINT32 SaveBar0Reg;
+
+ TempBar0Addr = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress);
+
+ //
+ // Apply EHCI controller erratas.
+ //
+ for (Index = 0; Index < IOH_MAX_EHCI_USB_CONTROLLERS; Index++, TempBar0Addr += IOH_USB_CONTROLLER_MMIO_RANGE) {
+
+ if ((PciRead16 (IohEhciPciReg[Index] + R_IOH_USB_VENDOR_ID)) != V_IOH_USB_VENDOR_ID) {
+ continue; // Device not enabled, skip.
+ }
+
+ //
+ // Save current settings for PCI CMD/BAR0 registers
+ //
+ SaveCmdReg = PciRead16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND);
+ SaveBar0Reg = PciRead32 (IohEhciPciReg[Index] + R_IOH_USB_MEMBAR);
+
+ //
+ // Temp. assign base address register, Enable Memory Space.
+ //
+ PciWrite32 ((IohEhciPciReg[Index] + R_IOH_USB_MEMBAR), TempBar0Addr);
+ PciWrite16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg | B_IOH_USB_COMMAND_MSE);
+
+
+ //
+ // Set packet buffer OUT/IN thresholds.
+ //
+ MmioAndThenOr32 (
+ TempBar0Addr + R_IOH_EHCI_INSNREG01,
+ (UINT32) (~(B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_MASK | B_IOH_EHCI_INSNREG01_IN_THRESHOLD_MASK)),
+ (UINT32) ((EHCI_OUT_THRESHOLD_VALUE << B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP) | (EHCI_IN_THRESHOLD_VALUE << B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP))
+ );
+
+ //
+ // Restore settings for PCI CMD/BAR0 registers
+ //
+ PciWrite32 ((IohEhciPciReg[Index] + R_IOH_USB_MEMBAR), SaveBar0Reg);
+ PciWrite16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg);
+ }
+
+ //
+ // Apply USB device controller erratas.
+ //
+ for (Index = 0; Index < IOH_MAX_USBDEVICE_USB_CONTROLLERS; Index++, TempBar0Addr += IOH_USB_CONTROLLER_MMIO_RANGE) {
+
+ if ((PciRead16 (IohUsbDevicePciReg[Index] + R_IOH_USB_VENDOR_ID)) != V_IOH_USB_VENDOR_ID) {
+ continue; // Device not enabled, skip.
+ }
+
+ //
+ // Save current settings for PCI CMD/BAR0 registers
+ //
+ SaveCmdReg = PciRead16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND);
+ SaveBar0Reg = PciRead32 (IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR);
+
+ //
+ // Temp. assign base address register, Enable Memory Space.
+ //
+ PciWrite32 ((IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR), TempBar0Addr);
+ PciWrite16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg | B_IOH_USB_COMMAND_MSE);
+
+ //
+ // Erratas for USB Device interrupt registers.
+ //
+
+ //
+ // 1st Mask interrupts.
+ //
+ MmioWrite32 (
+ TempBar0Addr + R_IOH_USBDEVICE_D_INTR_MSK_UDC_REG,
+ V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG
+ );
+ //
+ // 2nd RW/1C of equivalent status bits.
+ //
+ MmioWrite32 (
+ TempBar0Addr + R_IOH_USBDEVICE_D_INTR_UDC_REG,
+ V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG
+ );
+
+ //
+ // 1st Mask end point interrupts.
+ //
+ MmioWrite32 (
+ TempBar0Addr + R_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG,
+ V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG
+ );
+ //
+ // 2nd RW/1C of equivalent end point status bits.
+ //
+ MmioWrite32 (
+ TempBar0Addr + R_IOH_USBDEVICE_EP_INTR_UDC_REG,
+ V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG
+ );
+
+ //
+ // Restore settings for PCI CMD/BAR0 registers
+ //
+ PciWrite32 ((IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR), SaveBar0Reg);
+ PciWrite16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg);
+ }
+}
+
+//
+// Routines exported by this source module.
+//
+
+/** Perform Platform Erratas after MRC.
+
+ @retval EFI_SUCCESS Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformErratasPostMrc (
+ VOID
+ )
+{
+ PlatformUsbErratasPostMrc ();
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Platform/SpiFvbServices/FvbInfo.c b/QuarkPlatformPkg/Platform/SpiFvbServices/FvbInfo.c
new file mode 100644
index 0000000..2586590
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/SpiFvbServices/FvbInfo.c
@@ -0,0 +1,264 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ FvbInfo.c
+
+Abstract:
+
+ Defines data structure that is the volume header found.These data is intent
+ to decouple FVB driver with FV header.
+
+--*/
+
+#include <PiDxe.h>
+#include "FwBlockService.h"
+
+//
+// Signatures to trigger fixup.
+//
+#define PLATFORM_FVBOOT_SIGNATURE SIGNATURE_32 ('P', 'F', 'V', 'B')
+#define PLATFORM_FVMAIN_SIGNATURE SIGNATURE_32 ('P', 'F', 'V', 'M')
+
+EFI_FVB_MEDIA_INFO mPlatformFvbMediaInfo[] = {
+ //
+ // SECPEI BIOS FVB
+ //
+ {
+ 0,
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ {
+ {
+ 0,
+ }, // ZeroVector[16]
+ EFI_FIRMWARE_FILE_SYSTEM_GUID,
+ 0,
+ PLATFORM_FVBOOT_SIGNATURE,
+ EFI_FVB_READ_ENABLED_CAP | EFI_FVB_READ_STATUS | EFI_FVB_WRITE_ENABLED_CAP | EFI_FVB_WRITE_STATUS,
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),
+ 0, // CheckSum
+ 0, // ExtHeaderOffset
+ {
+ 0,
+ }, // Reserved[3]
+ 1, // Revision
+ {
+ 0,
+ 0,
+ }
+ },
+#else
+ {
+ {
+ 0,
+ }, // ZeroVector[16]
+ EFI_FIRMWARE_FILE_SYSTEM2_GUID,
+ 0,
+ PLATFORM_FVBOOT_SIGNATURE,
+ EFI_FVB_READ_ENABLED_CAP | EFI_FVB_READ_STATUS | EFI_FVB_WRITE_ENABLED_CAP | EFI_FVB_WRITE_STATUS,
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),
+ 0, // CheckSum
+ 0, // ExtHeaderOffset
+ {
+ 0,
+ }, // Reserved[3]
+ 2, // Revision
+ {
+ 0,
+ 0,
+ }
+ },
+#endif
+ {
+ 0,
+ 0
+ }
+ },
+ //
+ // RUNTIME UPDATABLE (NV) FV
+ //
+ {
+ FLASH_REGION_RUNTIME_UPDATABLE_BASE,
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ {
+ {
+ 0,
+ }, // ZeroVector[16]
+ EFI_SYSTEM_NV_DATA_FV_GUID,
+ (FLASH_REGION_RUNTIME_UPDATABLE_SIZE + FLASH_REGION_NV_FTW_SPARE_SIZE),
+ EFI_FVH_SIGNATURE,
+ EFI_FVB_READ_ENABLED_CAP | EFI_FVB_READ_STATUS | EFI_FVB_WRITE_ENABLED_CAP | EFI_FVB_WRITE_STATUS,
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),
+ 0, // CheckSum
+ 0, // ExtHeaderOffset
+ {
+ 0,
+ }, // Reserved[3]
+ 1, // Revision
+ {
+ ((FLASH_REGION_RUNTIME_UPDATABLE_SIZE + FLASH_REGION_NV_FTW_SPARE_SIZE) / FLASH_BLOCK_SIZE),
+ FLASH_BLOCK_SIZE,
+ }
+ },
+#else
+ {
+ {
+ 0,
+ }, // ZeroVector[16]
+ EFI_SYSTEM_NV_DATA_FV_GUID,
+ (FLASH_REGION_RUNTIME_UPDATABLE_SIZE + FLASH_REGION_NV_FTW_SPARE_SIZE),
+ EFI_FVH_SIGNATURE,
+ EFI_FVB_READ_ENABLED_CAP | EFI_FVB_READ_STATUS | EFI_FVB_WRITE_ENABLED_CAP | EFI_FVB_WRITE_STATUS,
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),
+ 0, // CheckSum
+ 0, // ExtHeaderOffset
+ {
+ 0,
+ }, // Reserved[3]
+ 2, // Revision
+ {
+ ((FLASH_REGION_RUNTIME_UPDATABLE_SIZE + FLASH_REGION_NV_FTW_SPARE_SIZE) / FLASH_BLOCK_SIZE),
+ FLASH_BLOCK_SIZE,
+ }
+ },
+#endif
+ {
+ 0,
+ 0
+ }
+ },
+ //
+ // Main BIOS FVB, Dynamic Base/Size values, fixed up at run time.
+ //
+ {
+ 0,
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ {
+ {
+ 0,
+ }, // ZeroVector[16]
+ EFI_FIRMWARE_FILE_SYSTEM_GUID,
+ 0,
+ PLATFORM_FVMAIN_SIGNATURE,
+ EFI_FVB_READ_ENABLED_CAP | EFI_FVB_READ_STATUS | EFI_FVB_WRITE_ENABLED_CAP | EFI_FVB_WRITE_STATUS,
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),
+ 0, // CheckSum
+ 0, // ExtHeaderOffset
+ {
+ 0,
+ }, // Reserved[3]
+ 1, // Revision
+ {
+ 0,
+ 0,
+ }
+ },
+#else
+ {
+ {
+ 0,
+ }, // ZeroVector[16]
+ EFI_FIRMWARE_FILE_SYSTEM2_GUID,
+ 0,
+ PLATFORM_FVMAIN_SIGNATURE,
+ EFI_FVB_READ_ENABLED_CAP | EFI_FVB_READ_STATUS | EFI_FVB_WRITE_ENABLED_CAP | EFI_FVB_WRITE_STATUS,
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),
+ 0, // CheckSum
+ 0, // ExtHeaderOffset
+ {
+ 0,
+ }, // Reserved[3]
+ 2, // Revision
+ {
+ 0,
+ 0,
+ }
+ },
+#endif
+ {
+ 0,
+ 0
+ }
+ },
+ //
+ // End of the FV structure
+ //
+};
+
+EFI_STATUS
+GetFvbInfo (
+ IN EFI_PHYSICAL_ADDRESS FvBaseAddress,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo
+ )
+{
+ UINTN Index;
+ EFI_BOOT_MODE BootMode;
+
+ BootMode = GetBootModeHob ();
+
+ for (Index = 0; Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO); Index += 1) {
+
+ //
+ // Fixup for dynamic values.
+ //
+ if (mPlatformFvbMediaInfo[Index].FvbInfo.Signature == PLATFORM_FVBOOT_SIGNATURE) {
+ mPlatformFvbMediaInfo[Index].BaseAddress = FLASH_REGION_FV_SECPEI_BASE;
+ mPlatformFvbMediaInfo[Index].FvbInfo.FvLength = (UINT64) FLASH_REGION_FV_SECPEI_SIZE;
+ mPlatformFvbMediaInfo[Index].FvbInfo.BlockMap[0].NumBlocks = (UINT64) (FLASH_REGION_FV_SECPEI_SIZE / FLASH_BLOCK_SIZE);
+ mPlatformFvbMediaInfo[Index].FvbInfo.BlockMap[0].Length = FLASH_BLOCK_SIZE;
+ mPlatformFvbMediaInfo[Index].FvbInfo.Signature = EFI_FVH_SIGNATURE; // Only need to do it once.
+ }
+ if (mPlatformFvbMediaInfo[Index].FvbInfo.Signature == PLATFORM_FVMAIN_SIGNATURE) {
+ mPlatformFvbMediaInfo[Index].BaseAddress = FLASH_REGION_FVMAIN_BASE;
+ mPlatformFvbMediaInfo[Index].FvbInfo.FvLength = (UINT64) FLASH_REGION_FVMAIN_SIZE;
+ mPlatformFvbMediaInfo[Index].FvbInfo.BlockMap[0].NumBlocks = (UINT64) (FLASH_REGION_FVMAIN_SIZE / FLASH_BLOCK_SIZE);
+ mPlatformFvbMediaInfo[Index].FvbInfo.BlockMap[0].Length = FLASH_BLOCK_SIZE;
+ mPlatformFvbMediaInfo[Index].FvbInfo.Signature = EFI_FVH_SIGNATURE; // Only need to do it once.
+ }
+
+ if (mPlatformFvbMediaInfo[Index].BaseAddress == FvBaseAddress) {
+ *FvbInfo = &mPlatformFvbMediaInfo[Index].FvbInfo;
+
+ DEBUG ((DEBUG_ERROR, "\nBaseAddr: 0x%lx \n", FvBaseAddress));
+ DEBUG ((DEBUG_ERROR, "FvLength: 0x%lx \n", (*FvbInfo)->FvLength));
+ DEBUG ((DEBUG_ERROR, "HeaderLength: 0x%x \n", (*FvbInfo)->HeaderLength));
+ DEBUG ((DEBUG_ERROR, "FvBlockMap[0].NumBlocks: 0x%x \n", (*FvbInfo)->BlockMap[0].NumBlocks));
+ DEBUG ((DEBUG_ERROR, "FvBlockMap[0].Length: 0x%x \n", (*FvbInfo)->BlockMap[0].Length));
+ DEBUG ((DEBUG_ERROR, "FvBlockMap[1].NumBlocks: 0x%x \n", (*FvbInfo)->BlockMap[1].NumBlocks));
+ DEBUG ((DEBUG_ERROR, "FvBlockMap[1].Length: 0x%x \n\n", (*FvbInfo)->BlockMap[1].Length));
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/QuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.c b/QuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.c
new file mode 100755
index 0000000..f234bc7
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.c
@@ -0,0 +1,2146 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ FWBlockService.c
+
+Abstract:
+
+Revision History
+
+--*/
+
+#include "FwBlockService.h"
+
+ESAL_FWB_GLOBAL *mFvbModuleGlobal;
+EFI_GUID gEfiFvbExtensionProtocolGuid;
+EFI_GUID gEfiAlternateFvBlockGuid;
+EFI_GUID gEfiFirmwareVolumeBlockProtocolGuid;
+EFI_GUID gEfiSmmFirmwareVolumeBlockProtocolGuid;
+
+
+EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {
+ FVB_DEVICE_SIGNATURE,
+ {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_MEMMAP_DP,
+ { sizeof (MEMMAP_DEVICE_PATH), 0 }
+ },
+ EfiMemoryMappedIO,
+ 0,
+ 0,
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ }
+ },
+ 0,
+ {
+ FvbProtocolGetAttributes,
+ FvbProtocolSetAttributes,
+ FvbProtocolGetPhysicalAddress,
+ FvbProtocolGetBlockSize,
+ FvbProtocolRead,
+ FvbProtocolWrite,
+ FvbProtocolEraseBlocks,
+ NULL
+ },
+ {
+ FvbExtendProtocolEraseCustomBlockRange
+ }
+};
+
+UINT32 mInSmmMode = 0;
+EFI_SMM_SYSTEM_TABLE2* mSmst = NULL;
+
+VOID
+PublishFlashDeviceInfo (
+ IN SPI_INIT_TABLE *Found
+ )
+/*++
+
+Routine Description:
+
+ Publish info on found flash device to other drivers via EFI_PLATFORM_TYPE_PROTOCOL.
+ Info published:-
+ 1) Flash Device Byte Size.
+
+Arguments:
+ Found - Pointer to entry in mSpiInitTable for found flash part.
+
+Returns:
+ None
+
+--*/
+{
+ EFI_PLATFORM_TYPE_PROTOCOL *PlatformType;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiPlatformTypeProtocolGuid, NULL, (VOID **) &PlatformType);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish Byte Size of found flash device.
+ //
+ PlatformType->FlashDeviceSize =
+ (UINT32) (Found->BiosStartOffset + Found->BiosSize);
+
+}
+
+VOID
+FvbVirtualddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Fixup internal data so that EFI and SAL can be call in virtual mode.
+ Call the passed in Child Notify event and convert the mFvbModuleGlobal
+ date items to there virtual address.
+
+ mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data
+ mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common
+ instance data.
+
+Arguments:
+
+ (Standard EFI notify event - EFI_EVENT_NOTIFY)
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ UINTN Index;
+
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]);
+
+ //
+ // Convert the base address of all the instances
+ //
+ Index = 0;
+ FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
+ while (Index < mFvbModuleGlobal->NumFv) {
+
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]);
+ //
+ // SpiWrite and SpiErase always use Physical Address instead of
+ // Virtual Address, even in Runtime. So we need not convert pointer
+ // for FvWriteBase[FVB_VIRTUAL]
+ //
+ // EfiConvertPointer (0, (VOID **) &FwhInstance->FvWriteBase[FVB_VIRTUAL]);
+ //
+ FwhInstance = (EFI_FW_VOL_INSTANCE *)
+ (
+ (UINTN) ((UINT8 *) FwhInstance) + FwhInstance->VolumeHeader.HeaderLength +
+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+ );
+ Index++;
+ }
+
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]);
+ //
+ // Convert SPI_PROTOCOL instance for runtime
+ //
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->SpiProtocol);
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal);
+}
+
+VOID
+FvbMemWrite8 (
+ IN UINT64 Dest,
+ IN UINT8 Byte
+ )
+{
+ MmioWrite8 ((UINTN)Dest, Byte);
+
+ return ;
+}
+
+EFI_STATUS
+GetFvbInstance (
+ IN UINTN Instance,
+ IN ESAL_FWB_GLOBAL *Global,
+ OUT EFI_FW_VOL_INSTANCE **FwhInstance,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Retrieves the physical address of a memory mapped FV
+
+Arguments:
+ Instance - The FV instance whose base address is going to be
+ returned
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+{
+ EFI_FW_VOL_INSTANCE *FwhRecord;
+
+ if (Instance >= Global->NumFv) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Find the right instance of the FVB private data
+ //
+ FwhRecord = Global->FvInstance[Virtual];
+ while (Instance > 0) {
+ FwhRecord = (EFI_FW_VOL_INSTANCE *)
+ (
+ (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength +
+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+ );
+ Instance--;
+ }
+
+ *FwhInstance = FwhRecord;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FvbGetPhysicalAddress (
+ IN UINTN Instance,
+ OUT EFI_PHYSICAL_ADDRESS *Address,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Retrieves the physical address of a memory mapped FV
+
+Arguments:
+ Instance - The FV instance whose base address is going to be
+ returned
+ Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
+ that on successful return, contains the base address
+ of the firmware volume.
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+{
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_STATUS Status;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+ ASSERT_EFI_ERROR (Status);
+ *Address = FwhInstance->FvBase[Virtual];
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FvbGetVolumeAttributes (
+ IN UINTN Instance,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Retrieves attributes, insures positive polarity of attribute bits, returns
+ resulting attributes in output parameter
+
+Arguments:
+ Instance - The FV instance whose attributes is going to be
+ returned
+ Attributes - Output buffer which contains attributes
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+{
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_STATUS Status;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+ ASSERT_EFI_ERROR (Status);
+ *Attributes = FwhInstance->VolumeHeader.Attributes;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FvbGetLbaAddress (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ OUT UINTN *LbaAddress,
+ OUT UINTN *LbaWriteAddress,
+ OUT UINTN *LbaLength,
+ OUT UINTN *NumOfBlocks,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Retrieves the starting address of an LBA in an FV
+
+Arguments:
+ Instance - The FV instance which the Lba belongs to
+ Lba - The logical block address
+ LbaAddress - On output, contains the physical starting address
+ of the Lba
+ LbaWriteAddress - On output, contains the physical starting address
+ of the Lba for writing
+ LbaLength - On output, contains the length of the block
+ NumOfBlocks - A pointer to a caller allocated UINTN in which the
+ number of consecutive blocks starting with Lba is
+ returned. All blocks in this range have a size of
+ BlockSize
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+{
+ UINT32 NumBlocks;
+ UINT32 BlockLength;
+ UINTN Offset;
+ EFI_LBA StartLba;
+ EFI_LBA NextLba;
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ EFI_STATUS Status;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+ ASSERT_EFI_ERROR (Status);
+
+ StartLba = 0;
+ Offset = 0;
+ BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]);
+
+ //
+ // Parse the blockmap of the FV to find which map entry the Lba belongs to
+ //
+ while (TRUE) {
+ NumBlocks = BlockMap->NumBlocks;
+ BlockLength = BlockMap->Length;
+
+ if ((NumBlocks == 0) || (BlockLength == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NextLba = StartLba + NumBlocks;
+
+ //
+ // The map entry found
+ //
+ if (Lba >= StartLba && Lba < NextLba) {
+ Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength);
+ if (LbaAddress) {
+ *LbaAddress = FwhInstance->FvBase[Virtual] + Offset;
+ }
+
+ if (LbaWriteAddress) {
+ *LbaWriteAddress = FwhInstance->FvWriteBase[Virtual] + Offset;
+ }
+
+ if (LbaLength) {
+ *LbaLength = BlockLength;
+ }
+
+ if (NumOfBlocks) {
+ *NumOfBlocks = (UINTN) (NextLba - Lba);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ StartLba = NextLba;
+ Offset = Offset + NumBlocks * BlockLength;
+ BlockMap++;
+ }
+}
+
+EFI_STATUS
+FvbReadBlock (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BlockOffset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Reads specified number of bytes into a buffer from the specified block
+
+Arguments:
+ Instance - The FV instance to be read from
+ Lba - The logical block address to be read from
+ BlockOffset - Offset into the block at which to begin reading
+ NumBytes - Pointer that on input contains the total size of
+ the buffer. On output, it contains the total number
+ of bytes read
+ Buffer - Pointer to a caller allocated buffer that will be
+ used to hold the data read
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - The firmware volume was read successfully and
+ contents are in Buffer
+ EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
+ NumBytes contains the total number of bytes returned
+ in Buffer
+ EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be read
+ EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
+
+--*/
+{
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+ UINTN LbaAddress;
+ UINTN LbaLength;
+ EFI_STATUS Status;
+
+ //
+ // Check for invalid conditions
+ //
+ if ((NumBytes == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*NumBytes == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, NULL, &LbaLength, NULL, Global, Virtual);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check if the FV is read enabled
+ //
+ FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
+
+ if ((Attributes & EFI_FVB_READ_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Perform boundary checks and adjust NumBytes
+ //
+ if (BlockOffset > LbaLength) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (LbaLength < (*NumBytes + BlockOffset)) {
+ *NumBytes = (UINT32) (LbaLength - BlockOffset);
+ Status = EFI_BAD_BUFFER_SIZE;
+ }
+
+ MmioReadBuffer8 (LbaAddress + BlockOffset, (UINTN) *NumBytes, Buffer);
+
+ return Status;
+}
+
+EFI_STATUS
+FlashFdWrite (
+ IN UINTN WriteAddress,
+ IN UINTN Address,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer,
+ IN UINTN LbaLength
+ )
+/*++
+
+Routine Description:
+ Writes specified number of bytes from the input buffer to the address
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // TODO: Suggested that this code be "critical section"
+ //
+ WriteAddress -= ( PcdGet32 (PcdFlashAreaBaseAddress) );
+ if (mInSmmMode == 0) { // !(EfiInManagementInterrupt ())) {
+ Status = mFvbModuleGlobal->SpiProtocol->Execute (
+ mFvbModuleGlobal->SpiProtocol,
+ SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
+ 0, // PrefixOpcodeIndex
+ TRUE, // DataCycle
+ TRUE, // Atomic
+ TRUE, // ShiftOut
+ WriteAddress, // Address
+ (UINT32) (*NumBytes), // Data Number
+ Buffer,
+ EnumSpiRegionBios
+ );
+
+ } else {
+ Status = mFvbModuleGlobal->SmmSpiProtocol->Execute (
+ mFvbModuleGlobal->SmmSpiProtocol,
+ SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
+ 0, // PrefixOpcodeIndex
+ TRUE, // DataCycle
+ TRUE, // Atomic
+ TRUE, // ShiftOut
+ WriteAddress, // Address
+ (UINT32) (*NumBytes), // Data Number
+ Buffer,
+ EnumSpiRegionBios
+ );
+ }
+
+ AsmWbinvd ();
+
+ return Status;
+}
+
+EFI_STATUS
+FlashFdErase (
+ IN UINTN WriteAddress,
+ IN UINTN Address,
+ IN UINTN LbaLength
+ )
+/*++
+
+Routine Description:
+ Erase a certain block from address LbaWriteAddress
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN NumBytes;
+
+ NumBytes = LbaLength;
+
+ WriteAddress -= (PcdGet32 (PcdFlashAreaBaseAddress));
+ if (mInSmmMode == 0 ) { // !(EfiInManagementInterrupt ())) {
+ Status = mFvbModuleGlobal->SpiProtocol->Execute (
+ mFvbModuleGlobal->SpiProtocol,
+ SPI_OPCODE_ERASE_INDEX, // OpcodeIndex
+ 0, // PrefixOpcodeIndex
+ FALSE, // DataCycle
+ TRUE, // Atomic
+ FALSE, // ShiftOut
+ WriteAddress, // Address
+ 0, // Data Number
+ NULL,
+ EnumSpiRegionBios // SPI_REGION_TYPE
+ );
+ } else {
+ Status = mFvbModuleGlobal->SmmSpiProtocol->Execute (
+ mFvbModuleGlobal->SmmSpiProtocol,
+ SPI_OPCODE_ERASE_INDEX, // OpcodeIndex
+ 0, // PrefixOpcodeIndex
+ FALSE, // DataCycle
+ TRUE, // Atomic
+ FALSE, // ShiftOut
+ WriteAddress, // Address
+ 0, // Data Number
+ NULL,
+ EnumSpiRegionBios // SPI_REGION_TYPE
+ );
+ }
+
+ AsmWbinvd ();
+
+ return Status;
+}
+
+EFI_STATUS
+FvbWriteBlock (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BlockOffset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Writes specified number of bytes from the input buffer to the block
+
+Arguments:
+ Instance - The FV instance to be written to
+ Lba - The starting logical block index to write to
+ BlockOffset - Offset into the block at which to begin writing
+ NumBytes - Pointer that on input contains the total size of
+ the buffer. On output, it contains the total number
+ of bytes actually written
+ Buffer - Pointer to a caller allocated buffer that contains
+ the source for the write
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - The firmware volume was written successfully
+ EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
+ NumBytes contains the total number of bytes
+ actually written
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be written
+ EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
+
+--*/
+{
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+ UINTN LbaAddress;
+ UINTN LbaWriteAddress;
+ UINTN LbaLength;
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Writes are enabled in the init routine itself
+ //
+ if (!FwhInstance->WriteEnabled) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Check for invalid conditions
+ //
+ if ((NumBytes == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*NumBytes == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check if the FV is write enabled
+ //
+ FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
+
+ if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Perform boundary checks and adjust NumBytes
+ //
+ if (BlockOffset > LbaLength) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (LbaLength < (*NumBytes + BlockOffset)) {
+ *NumBytes = (UINT32) (LbaLength - BlockOffset);
+ Status = EFI_BAD_BUFFER_SIZE;
+ }
+
+ ReturnStatus = FlashFdWrite (
+ LbaWriteAddress + BlockOffset,
+ LbaAddress,
+ NumBytes,
+ Buffer,
+ LbaLength
+ );
+ if (EFI_ERROR (ReturnStatus)) {
+ return ReturnStatus;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FvbEraseBlock (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Erases and initializes a firmware volume block
+
+Arguments:
+ Instance - The FV instance to be erased
+ Lba - The logical block index to be erased
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - The erase request was successfully completed
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be written. Firmware device may have been
+ partially erased
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+{
+
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+ UINTN LbaAddress;
+ UINTN LbaWriteAddress;
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ UINTN LbaLength;
+ EFI_STATUS Status;
+ UINTN SectorNum;
+ UINTN Index;
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Writes are enabled in the init routine itself
+ //
+ if (!FwhInstance->WriteEnabled) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Check if the FV is write enabled
+ //
+ FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
+
+ if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Get the starting address of the block for erase. For debug reasons,
+ // LbaWriteAddress may not be the same as LbaAddress.
+ //
+ Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SectorNum = LbaLength / SPI_ERASE_SECTOR_SIZE;
+ for (Index = 0; Index < SectorNum; Index++){
+ Status = FlashFdErase (
+ LbaWriteAddress + Index * SPI_ERASE_SECTOR_SIZE,
+ LbaAddress,
+ SPI_ERASE_SECTOR_SIZE
+ );
+ if (Status != EFI_SUCCESS){
+ break;
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FvbEraseCustomBlockRange (
+ IN UINTN Instance,
+ IN EFI_LBA StartLba,
+ IN UINTN OffsetStartLba,
+ IN EFI_LBA LastLba,
+ IN UINTN OffsetLastLba,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Erases and initializes a specified range of a firmware volume
+
+Arguments:
+ Instance - The FV instance to be erased
+ StartLba - The starting logical block index to be erased
+ OffsetStartLba - Offset into the starting block at which to
+ begin erasing
+ LastLba - The last logical block index to be erased
+ OffsetStartLba - Offset into the last block at which to end erasing
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - The firmware volume was erased successfully
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be written. Firmware device may have been
+ partially erased
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+{
+ EFI_LBA Index;
+ UINTN LbaSize;
+ UINTN ScratchLbaSizeData;
+
+ //
+ // First LBA.
+ //
+ FvbGetLbaAddress (Instance, StartLba, NULL, NULL, &LbaSize, NULL, Global, Virtual);
+
+ //
+ // Use the scratch space as the intermediate buffer to transfer data
+ // Back up the first LBA in scratch space.
+ //
+ FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);
+
+ //
+ // erase now
+ //
+ FvbEraseBlock (Instance, StartLba, Global, Virtual);
+ ScratchLbaSizeData = OffsetStartLba;
+
+ //
+ // write the data back to the first block
+ //
+ if (ScratchLbaSizeData > 0) {
+ FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual);
+ }
+ //
+ // Middle LBAs
+ //
+ if (LastLba > (StartLba + 1)) {
+ for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) {
+ FvbEraseBlock (Instance, Index, Global, Virtual);
+ }
+ }
+ //
+ // Last LBAs, the same as first LBAs
+ //
+ if (LastLba > StartLba) {
+ FvbGetLbaAddress (Instance, LastLba, NULL, NULL, &LbaSize, NULL, Global, Virtual);
+ FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);
+ FvbEraseBlock (Instance, LastLba, Global, Virtual);
+ }
+
+ ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1);
+
+ return FvbWriteBlock (
+ Instance,
+ LastLba,
+ (OffsetLastLba + 1),
+ &ScratchLbaSizeData,
+ Global->FvbScratchSpace[Virtual],
+ Global,
+ Virtual
+ );
+}
+
+EFI_STATUS
+FvbSetVolumeAttributes (
+ IN UINTN Instance,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+/*++
+
+Routine Description:
+ Modifies the current settings of the firmware volume according to the
+ input parameter, and returns the new setting of the volume
+
+Arguments:
+ Instance - The FV instance whose attributes is going to be
+ modified
+ Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
+ containing the desired firmware volume settings.
+ On successful return, it contains the new settings
+ of the firmware volume
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ Virtual - Whether CPU is in virtual or physical mode
+
+Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
+ EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
+ in conflict with the capabilities as declared in the
+ firmware volume header
+
+--*/
+{
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_FVB_ATTRIBUTES_2 OldAttributes;
+ EFI_FVB_ATTRIBUTES_2 *AttribPtr;
+ UINT32 Capabilities;
+ UINT32 OldStatus;
+ UINT32 NewStatus;
+ EFI_STATUS Status;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+ ASSERT_EFI_ERROR (Status);
+
+ AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes);
+ OldAttributes = *AttribPtr;
+ Capabilities = OldAttributes & EFI_FVB_CAPABILITIES;
+ OldStatus = OldAttributes & EFI_FVB_STATUS;
+ NewStatus = *Attributes & EFI_FVB_STATUS;
+
+ //
+ // If firmware volume is locked, no status bit can be updated
+ //
+ if (OldAttributes & EFI_FVB_LOCK_STATUS) {
+ if (OldStatus ^ NewStatus) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+ //
+ // Test read disable
+ //
+ if ((Capabilities & EFI_FVB_READ_DISABLED_CAP) == 0) {
+ if ((NewStatus & EFI_FVB_READ_STATUS) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Test read enable
+ //
+ if ((Capabilities & EFI_FVB_READ_ENABLED_CAP) == 0) {
+ if (NewStatus & EFI_FVB_READ_STATUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Test write disable
+ //
+ if ((Capabilities & EFI_FVB_WRITE_DISABLED_CAP) == 0) {
+ if ((NewStatus & EFI_FVB_WRITE_STATUS) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Test write enable
+ //
+ if ((Capabilities & EFI_FVB_WRITE_ENABLED_CAP) == 0) {
+ if (NewStatus & EFI_FVB_WRITE_STATUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Test lock
+ //
+ if ((Capabilities & EFI_FVB_LOCK_CAP) == 0) {
+ if (NewStatus & EFI_FVB_LOCK_STATUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB_STATUS));
+ *AttribPtr = (*AttribPtr) | NewStatus;
+ *Attributes = *AttribPtr;
+
+ return EFI_SUCCESS;
+}
+//
+// FVB protocol APIs
+//
+EFI_STATUS
+EFIAPI
+FvbProtocolGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the physical address of the device.
+
+Arguments:
+
+ This - Calling context
+ Address - Output buffer containing the address.
+
+Returns:
+
+Returns:
+ EFI_SUCCESS - Successfully returns
+
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ());
+}
+
+EFI_STATUS
+FvbProtocolGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumOfBlocks
+ )
+/*++
+
+Routine Description:
+ Retrieve the size of a logical block
+
+Arguments:
+ This - Calling context
+ Lba - Indicates which block to return the size for.
+ BlockSize - A pointer to a caller allocated UINTN in which
+ the size of the block is returned
+ NumOfBlocks - a pointer to a caller allocated UINTN in which the
+ number of consecutive blocks starting with Lba is
+ returned. All blocks in this range have a size of
+ BlockSize
+
+Returns:
+ EFI_SUCCESS - The firmware volume was read successfully and
+ contents are in Buffer
+
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbGetLbaAddress (
+ FvbDevice->Instance,
+ Lba,
+ NULL,
+ NULL,
+ BlockSize,
+ NumOfBlocks,
+ mFvbModuleGlobal,
+ EfiGoneVirtual ()
+ );
+}
+
+EFI_STATUS
+EFIAPI
+FvbProtocolGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves Volume attributes. No polarity translations are done.
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - Successfully returns
+
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());
+}
+
+EFI_STATUS
+EFIAPI
+FvbProtocolSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+/*++
+
+Routine Description:
+ Sets Volume attributes. No polarity translations are done.
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - Successfully returns
+
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());
+}
+
+EFI_STATUS
+EFIAPI
+FvbProtocolEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ The EraseBlock() function erases one or more blocks as denoted by the
+ variable argument list. The entire parameter list of blocks must be verified
+ prior to erasing any blocks. If a block is requested that does not exist
+ within the associated firmware volume (it has a larger index than the last
+ block of the firmware volume), the EraseBlock() function must return
+ EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
+
+Arguments:
+ This - Calling context
+ ... - Starting LBA followed by Number of Lba to erase.
+ a -1 to terminate the list.
+
+Returns:
+ EFI_SUCCESS - The erase request was successfully completed
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be written. Firmware device may have been
+ partially erased
+
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ UINTN NumOfBlocks;
+ VA_LIST args;
+ EFI_LBA StartingLba;
+ UINTN NumOfLba;
+ EFI_STATUS Status;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ());
+ ASSERT_EFI_ERROR (Status);
+
+ NumOfBlocks = FwhInstance->NumOfBlocks;
+
+ VA_START (args, This);
+
+ do {
+ StartingLba = VA_ARG (args, EFI_LBA);
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ break;
+ }
+
+ NumOfLba = VA_ARG (args, UINT32);
+
+ //
+ // Check input parameters
+ //
+ if (NumOfLba == 0) {
+ VA_END (args);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((StartingLba + NumOfLba) > NumOfBlocks) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } while (TRUE);
+
+ VA_END (args);
+
+ VA_START (args, This);
+ do {
+ StartingLba = VA_ARG (args, EFI_LBA);
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ break;
+ }
+
+ NumOfLba = VA_ARG (args, UINT32);
+
+ while (NumOfLba > 0) {
+ Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ());
+ if (EFI_ERROR (Status)) {
+ VA_END (args);
+ return Status;
+ }
+
+ StartingLba++;
+ NumOfLba--;
+ }
+
+ } while (TRUE);
+
+ VA_END (args);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+FvbProtocolWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Writes data beginning at Lba:Offset from FV. The write terminates either
+ when *NumBytes of data have been written, or when a block boundary is
+ reached. *NumBytes is updated to reflect the actual number of bytes
+ written. The write opertion does not include erase. This routine will
+ attempt to write only the specified bytes. If the writes do not stick,
+ it will return an error.
+
+Arguments:
+ This - Calling context
+ Lba - Block in which to begin write
+ Offset - Offset in the block at which to begin write
+ NumBytes - On input, indicates the requested write size. On
+ output, indicates the actual number of bytes written
+ Buffer - Buffer containing source data for the write.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was written successfully
+ EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
+ NumBytes contains the total number of bytes
+ actually written
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be written
+ EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
+
+--*/
+{
+
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());
+}
+
+EFI_STATUS
+EFIAPI
+FvbProtocolRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Reads data beginning at Lba:Offset from FV. The Read terminates either
+ when *NumBytes of data have been read, or when a block boundary is
+ reached. *NumBytes is updated to reflect the actual number of bytes
+ written. The write opertion does not include erase. This routine will
+ attempt to write only the specified bytes. If the writes do not stick,
+ it will return an error.
+
+Arguments:
+ This - Calling context
+ Lba - Block in which to begin Read
+ Offset - Offset in the block at which to begin Read
+ NumBytes - On input, indicates the requested write size. On
+ output, indicates the actual number of bytes Read
+ Buffer - Buffer containing source data for the Read.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was read successfully and
+ contents are in Buffer
+ EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
+ NumBytes contains the total number of bytes returned
+ in Buffer
+ EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be read
+ EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
+
+--*/
+{
+
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_STATUS Status;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+ Status = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());
+
+ return Status;
+}
+//
+// FVB Extension Protocols
+//
+EFI_STATUS
+FvbExtendProtocolEraseCustomBlockRange (
+ IN EFI_FVB_EXTENSION_PROTOCOL *This,
+ IN EFI_LBA StartLba,
+ IN UINTN OffsetStartLba,
+ IN EFI_LBA LastLba,
+ IN UINTN OffsetLastLba
+ )
+/*++
+
+Routine Description:
+ Erases and initializes a specified range of a firmware volume
+
+Arguments:
+ This - Calling context
+ StartLba - The starting logical block index to be erased
+ OffsetStartLba - Offset into the starting block at which to
+ begin erasing
+ LastLba - The last logical block index to be erased
+ OffsetStartLba - Offset into the last block at which to end erasing
+
+Returns:
+ EFI_SUCCESS - The firmware volume was erased successfully
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be written. Firmware device may have been
+ partially erased
+
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_EXTEND_DEVICE_FROM_THIS (This);
+
+ return FvbEraseCustomBlockRange (
+ FvbDevice->Instance,
+ StartLba,
+ OffsetStartLba,
+ LastLba,
+ OffsetLastLba,
+ mFvbModuleGlobal,
+ EfiGoneVirtual ()
+ );
+}
+
+STATIC
+EFI_STATUS
+ValidateFvHeader (
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
+ )
+/*++
+
+Routine Description:
+ Check the integrity of firmware volume header
+
+Arguments:
+ FwVolHeader - A pointer to a firmware volume header
+
+Returns:
+ EFI_SUCCESS - The firmware volume is consistent
+ EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV
+
+--*/
+{
+ UINT16 *Ptr;
+ UINT16 HeaderLength;
+ UINT16 Checksum;
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ #ifndef R864_BUILD
+ if (((FwVolHeader->Revision != EFI_FVH_REVISION) && (FwVolHeader->Revision != EFI_FVH_REVISION)) ||
+ #else
+ if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
+ #endif
+ (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
+ (FwVolHeader->FvLength == ((UINTN) -1)) ||
+ ((FwVolHeader->HeaderLength & 0x01) != 0)
+ ) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Verify the header checksum
+ //
+ HeaderLength = (UINT16) (FwVolHeader->HeaderLength / 2);
+ Ptr = (UINT16 *) FwVolHeader;
+ Checksum = 0;
+ while (HeaderLength > 0) {
+ Checksum = Checksum + (*Ptr);
+ Ptr++;
+ HeaderLength--;
+ }
+
+ if (Checksum != 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFvbHeader (
+ VOID **HobList,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader,
+ OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT BOOLEAN *WriteBack
+ )
+{
+ EFI_STATUS Status;
+ VOID *Buffer;
+ EFI_FLASH_MAP_ENTRY_DATA *FlashMapEntry;
+ EFI_FLASH_SUBAREA_ENTRY *FlashMapSubEntry;
+
+
+ Status = EFI_SUCCESS;
+ *FwVolHeader = NULL;
+ *WriteBack = FALSE;
+
+
+ Buffer= GetNextGuidHob (&gEfiFlashMapHobGuid, *HobList);
+ if (Buffer == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ *HobList = GET_NEXT_HOB (Buffer);
+ Buffer = (VOID *) ((UINT8 *) (Buffer) + sizeof (EFI_HOB_GUID_TYPE));
+
+
+ FlashMapEntry = (EFI_FLASH_MAP_ENTRY_DATA *) Buffer;
+ FlashMapSubEntry = &FlashMapEntry->Entries[0];
+ DEBUG((EFI_D_INFO, "Fvb base : %08x Attributes : %08x!\n",FlashMapSubEntry->Base,FlashMapSubEntry->Attributes));
+ //
+ // Check if it is a "FVB" area
+ //
+ if (!CompareGuid (&FlashMapSubEntry->FileSystem, &gEfiFirmwareVolumeBlockProtocolGuid)) {
+ return Status;
+ }
+ //
+ // Check if it is a "real" flash
+ //
+ if (FlashMapSubEntry->Attributes != (EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV)) {
+ return Status;
+ }
+
+ *BaseAddress = FlashMapSubEntry->Base;
+
+ *FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (*BaseAddress);
+ Status = ValidateFvHeader (*FwVolHeader);
+ if (EFI_ERROR (Status)) {
+ //
+ // Get FvbInfo
+ //
+ *WriteBack = TRUE;
+
+ Status = GetFvbInfo (*BaseAddress, FwVolHeader);
+ DEBUG(( DEBUG_ERROR, "Through GetFvbInfo: %08x!\n",*BaseAddress));
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+SmmSpiInit (
+ VOID
+ )
+{
+ UINT8 SpiStatus;
+ UINT8 FlashIndex;
+ UINT8 FlashID[3];
+ EFI_STATUS Status;
+
+ //
+ // Obtain a handle for ICH SPI Protocol
+ //
+ ASSERT(mSmst != NULL);
+ if (mFvbModuleGlobal->SmmSpiProtocol == NULL){
+ Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, &mFvbModuleGlobal->SmmSpiProtocol);
+ ASSERT_EFI_ERROR(Status);
+ }
+ //
+ // attempt to identify flash part and initialize spi table
+ //
+ for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
+ Status = mFvbModuleGlobal->SmmSpiProtocol->Init (
+ mFvbModuleGlobal->SmmSpiProtocol,
+ &(mSpiInitTable[FlashIndex])
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // read vendor/device IDs to check if flash device is supported
+ //
+ Status = mFvbModuleGlobal->SmmSpiProtocol->Execute (
+ mFvbModuleGlobal->SmmSpiProtocol,
+ SPI_OPCODE_JEDEC_ID_INDEX,
+ SPI_WREN_INDEX,
+ TRUE,
+ FALSE,
+ FALSE,
+ 0,
+ 3,
+ FlashID,
+ EnumSpiRegionAll
+ );
+ if (!EFI_ERROR (Status)) {
+ if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
+ (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) ||
+ ((FlashID[0] == SPI_AT26DF321_ID1) &&
+ (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
+ (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) {
+ //
+ // Supported SPI device found
+ //
+ DEBUG (
+ ((EFI_D_INFO),
+ "Smm Mode: Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
+ FlashID[0],
+ FlashID[1],
+ FlashID[2])
+ );
+ break;
+ }
+ }
+ }
+ }
+
+ if (FlashIndex >= EnumSpiFlashMax) {
+ Status = EFI_UNSUPPORTED;
+ DEBUG (
+ (EFI_D_ERROR,
+ "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
+ FlashID[0],
+ FlashID[1],
+ FlashID[2])
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ SpiStatus = 0;
+ Status = mFvbModuleGlobal->SmmSpiProtocol->Execute (
+ mFvbModuleGlobal->SmmSpiProtocol,
+ SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex
+ 1, // PrefixOpcodeIndex
+ TRUE, // DataCycle
+ TRUE, // Atomic
+ TRUE, // ShiftOut
+ 0, // Address
+ 1, // Data Number
+ &SpiStatus,
+ EnumSpiRegionAll // SPI_REGION_TYPE
+ );
+ return Status;
+}
+
+EFI_STATUS
+SmmSpiNotificationFunction (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ return SmmSpiInit();
+}
+
+
+VOID
+EFIAPI
+GetFullDriverPath (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ OUT EFI_DEVICE_PATH_PROTOCOL **CompleteFilePath
+ )
+/*++
+
+Routine Description:
+
+ Function is used to get the full device path for this driver.
+
+Arguments:
+
+ ImageHandle - The loaded image handle of this driver.
+ SystemTable - The pointer of system table.
+ CompleteFilePath - The pointer of returned full file path
+
+Returns:
+
+ none
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
+
+
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ &LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->HandleProtocol (
+ LoadedImage->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID *) &ImageDevicePath
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *CompleteFilePath = AppendDevicePath (
+ ImageDevicePath,
+ LoadedImage->FilePath
+ );
+
+ return ;
+}
+
+
+
+EFI_STATUS
+FvbInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This function does common initialization for FVB services
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ VOID *HobList;
+ VOID *FirmwareVolumeHobList;
+ UINT32 BufferSize;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
+ UINTN LbaAddress;
+ BOOLEAN WriteEnabled;
+ BOOLEAN WriteLocked;
+ EFI_HANDLE FwbHandle;
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;
+ EFI_DEVICE_PATH_PROTOCOL *TempFwbDevicePath;
+ FV_DEVICE_PATH TempFvbDevicePathData;
+ UINT32 MaxLbaSize;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ BOOLEAN WriteBack;
+ UINTN NumOfBlocks;
+ UINTN HeaderLength;
+ UINT8 SpiStatus;
+ UINT8 FlashIndex;
+ UINT8 FlashID[3];
+ EFI_DEVICE_PATH_PROTOCOL *CompleteFilePath;
+ UINT8 PrefixOpcodeIndex;
+ UINT32 MsrIndex;
+ UINT32 VariableMtrrLimit;
+ BOOLEAN InSmm;
+ static EFI_SMM_BASE2_PROTOCOL *mSmmBase2 =NULL;
+ EFI_HANDLE Handle;
+
+ VOID *Registration;
+ EFI_EVENT Event;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64(EFI_IA32_MTRR_CAP) & B_EFI_IA32_MTRR_VARIABLE_SUPPORT);
+
+ CompleteFilePath = NULL;
+ GetFullDriverPath (ImageHandle, SystemTable, &CompleteFilePath);
+
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+
+ //
+ // No FV HOBs found
+ //
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Allocate runtime services data for global variable, which contains
+ // the private data of all firmware volume block instances
+ //
+ mFvbModuleGlobal = (ESAL_FWB_GLOBAL *)AllocateRuntimeZeroPool(sizeof (ESAL_FWB_GLOBAL ));
+ ASSERT(mFvbModuleGlobal);
+ Status = gBS->LocateProtocol (
+ &gEfiSmmBase2ProtocolGuid,
+ NULL,
+ (VOID **) &mSmmBase2
+ );
+
+ if (mSmmBase2 == NULL) {
+ InSmm = FALSE;
+ } else {
+ mSmmBase2->InSmm (mSmmBase2, &InSmm);
+ mSmmBase2->GetSmstLocation (mSmmBase2, &mSmst);
+
+ }
+
+ if (!InSmm) {
+ mInSmmMode = 0;
+ //
+ // Make sure the Flash is not cached in MTRR
+ // For PEI performance issue, we enabled the write protect cache for Flash regions
+ // Here we need to disable it before the SPI intialization
+ //
+ for (MsrIndex = EFI_CACHE_VARIABLE_MTRR_BASE; MsrIndex < (EFI_CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit*2 - 1); MsrIndex+=2) {
+ if ( (AsmReadMsr64 (MsrIndex) & (~0x0FFF)) == (PcdGet32 (PcdFlashAreaBaseAddress))) {
+ AsmWriteMsr64 (MsrIndex, 0);
+ AsmWriteMsr64 (MsrIndex + 1, 0);
+ }
+ }
+
+ //
+ // Obtain a handle for ICH SPI Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiSpiProtocolGuid, NULL, &mFvbModuleGlobal->SpiProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // attempt to identify flash part and initialize spi table
+ //
+ for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
+ Status = mFvbModuleGlobal->SpiProtocol->Init (
+ mFvbModuleGlobal->SpiProtocol,
+ &(mSpiInitTable[FlashIndex])
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // read vendor/device IDs to check if flash device is supported
+ //
+ Status = mFvbModuleGlobal->SpiProtocol->Execute (
+ mFvbModuleGlobal->SpiProtocol,
+ SPI_OPCODE_JEDEC_ID_INDEX,
+ SPI_WREN_INDEX,
+ TRUE,
+ FALSE,
+ FALSE,
+ 0,
+ 3,
+ FlashID,
+ EnumSpiRegionAll
+ );
+ if (!EFI_ERROR (Status)) {
+ if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
+ (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) ||
+ ((FlashID[0] == SPI_AT26DF321_ID1) &&
+ (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
+ (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) {
+ //
+ // Supported SPI device found
+ //
+ DEBUG (
+ ((EFI_D_INFO),
+ "Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
+ FlashID[0],
+ FlashID[1],
+ FlashID[2])
+ );
+
+ PublishFlashDeviceInfo (&mSpiInitTable[FlashIndex]);
+ break;
+ }
+ }
+ }
+ }
+
+ if (FlashIndex >= EnumSpiFlashMax) {
+ Status = EFI_UNSUPPORTED;
+ DEBUG (
+ (DEBUG_ERROR,
+ "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
+ FlashID[0],
+ FlashID[1],
+ FlashID[2])
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Unlock all regions by writing to status register
+ // This could be SPI device specific, need to follow the datasheet
+ // To write to Write Status Register the Spi PrefixOpcode needs to be:
+ // 0 for Atmel parts
+ // 0 for Intel parts
+ // 0 for Macronix parts
+ // 0 for Winbond parts
+ // 1 for SST parts
+ SpiStatus = 0;
+ if (FlashID[0] == SPI_SST25VF016B_ID1) {
+ PrefixOpcodeIndex = 1;
+ } else {
+ PrefixOpcodeIndex = 0;
+ }
+ Status = mFvbModuleGlobal->SpiProtocol->Execute (
+ mFvbModuleGlobal->SpiProtocol,
+ SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex
+ PrefixOpcodeIndex, // PrefixOpcodeIndex
+ TRUE, // DataCycle
+ TRUE, // Atomic
+ TRUE, // ShiftOut
+ 0, // Address
+ 1, // Data Number
+ &SpiStatus,
+ EnumSpiRegionAll // SPI_REGION_TYPE
+ );
+
+
+ } else {
+ mInSmmMode = 1;
+
+ Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, &mFvbModuleGlobal->SmmSpiProtocol);
+ if (EFI_ERROR(Status)) {
+ Registration = NULL;
+ Status = mSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmSpiProtocolGuid,
+ SmmSpiNotificationFunction,
+ &Registration
+ );
+ } else {
+ Status = SmmSpiInit();
+ }
+
+ }
+
+ //
+ // Calculate the total size for all firmware volume block instances
+ //
+ BufferSize = 0;
+ FirmwareVolumeHobList = HobList;
+ do {
+ Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, &BaseAddress, &WriteBack);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (FwVolHeader) {
+ BufferSize += (FwVolHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER));
+ }
+ } while (TRUE);
+
+ //
+ // Only need to allocate once. There is only one copy of physical memory for
+ // the private data of each FV instance. But in virtual mode or in physical
+ // mode, the address of the the physical memory may be different.
+ //
+ mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] = (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize);
+ ASSERT(mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]);
+ //
+ // Make a virtual copy of the FvInstance pointer.
+ //
+ FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
+ mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance;
+
+ mFvbModuleGlobal->NumFv = 0;
+ FirmwareVolumeHobList = HobList;
+
+ MaxLbaSize = 0;
+
+ //
+ // Fill in the private data of each firmware volume block instance
+ //
+ // Foreach Fv HOB in the FirmwareVolumeHobList, loop
+ //
+ do {
+ Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, &BaseAddress, &WriteBack);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (!FwVolHeader) {
+ continue;
+ }
+
+
+ CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength);
+ FwVolHeader = &(FwhInstance->VolumeHeader);
+
+ FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress;
+ FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress;
+
+ //
+ // FwhInstance->FvWriteBase may not be the same as FwhInstance->FvBase
+ //
+ FwhInstance->FvWriteBase[FVB_PHYSICAL] = (UINTN) BaseAddress;
+ WriteEnabled = TRUE;
+
+ //
+ // Every pointer should have a virtual copy.
+ //
+ FwhInstance->FvWriteBase[FVB_VIRTUAL] = FwhInstance->FvWriteBase[FVB_PHYSICAL];
+
+ FwhInstance->WriteEnabled = WriteEnabled;
+ EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL);
+
+ LbaAddress = (UINTN) FwhInstance->FvWriteBase[0];
+ NumOfBlocks = 0;
+ WriteLocked = FALSE;
+
+ if (WriteEnabled) {
+ for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
+ //
+ // Get the maximum size of a block. The size will be used to allocate
+ // buffer for Scratch space, the intermediate buffer for FVB extension
+ // protocol
+ //
+ if (MaxLbaSize < PtrBlockMapEntry->Length) {
+ MaxLbaSize = PtrBlockMapEntry->Length;
+ }
+
+ NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;
+ }
+ //
+ // Write back a healthy FV header
+ //
+ if (WriteBack && (!WriteLocked)) {
+
+ Status = FlashFdErase (
+ (UINTN) FwhInstance->FvWriteBase[0],
+ (UINTN) BaseAddress,
+ FwVolHeader->BlockMap->Length
+ );
+
+ HeaderLength = (UINTN) FwVolHeader->HeaderLength;
+ Status = FlashFdWrite (
+ (UINTN) FwhInstance->FvWriteBase[0],
+ (UINTN) BaseAddress,
+ &HeaderLength,
+ (UINT8 *) FwVolHeader,
+ FwVolHeader->BlockMap->Length
+ );
+
+ }
+ }
+ //
+ // The total number of blocks in the FV.
+ //
+ FwhInstance->NumOfBlocks = NumOfBlocks;
+
+ //
+ // If the FV is write locked, set the appropriate attributes
+ //
+ if (WriteLocked) {
+ //
+ // write disabled
+ //
+ FwhInstance->VolumeHeader.Attributes &= ~EFI_FVB_WRITE_STATUS;
+ //
+ // lock enabled
+ //
+ FwhInstance->VolumeHeader.Attributes |= EFI_FVB_LOCK_STATUS;
+ }
+ //
+ // Add a FVB Protocol Instance
+ //
+
+ FvbDevice = AllocateRuntimeZeroPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE));
+ ASSERT (FvbDevice);
+
+ CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));
+
+ FvbDevice->Instance = mFvbModuleGlobal->NumFv;
+ mFvbModuleGlobal->NumFv++;
+
+ //
+ // Set up the devicepath
+ //
+ FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;
+ FvbDevice->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + (FwVolHeader->FvLength - 1);
+
+ //
+ // Find a handle with a matching device path that has supports FW Block protocol
+ //
+ TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData;
+ CopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH));
+
+ if (!InSmm) {
+
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle);
+ if (EFI_ERROR (Status)) {
+ //
+ // LocateDevicePath fails so install a new interface and device path
+ //
+ FwbHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &FwbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ &FvbDevice->FwVolBlockInstance,
+ &gEfiDevicePathProtocolGuid,
+ &FvbDevice->DevicePath,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) {
+ //
+ // Device allready exists, so reinstall the FVB protocol
+ //
+ Status = gBS->HandleProtocol (
+ FwbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ &OldFwbInterface
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->ReinstallProtocolInterface (
+ FwbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ OldFwbInterface,
+ &FvbDevice->FwVolBlockInstance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ } else {
+ //
+ // There was a FVB protocol on an End Device Path node
+ //
+ ASSERT (FALSE);
+ }
+ //
+ // Install FVB Extension Protocol on the same handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &FwbHandle,
+ &gEfiFvbExtensionProtocolGuid,
+ &FvbDevice->FvbExtension,
+ &gEfiAlternateFvBlockGuid,
+ NULL,
+ NULL
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ } else {
+ FwbHandle = NULL;
+ Status = mSmst->SmmInstallProtocolInterface (
+ &FwbHandle,
+ &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &FvbDevice->FwVolBlockInstance
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ FwhInstance = (EFI_FW_VOL_INSTANCE *)
+ (
+ (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength +
+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+ );
+ } while (TRUE);
+
+ //
+ // Allocate for scratch space, an intermediate buffer for FVB extention
+ //
+
+
+ mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL] = AllocateRuntimeZeroPool (MaxLbaSize);
+
+ ASSERT (mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]);
+
+ mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL];
+
+ if (!InSmm) {
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FvbVirtualddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ //
+ // Inform other platform drivers that SPI device discovered and
+ // SPI interface ready for use.
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiSmmSpiReadyProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ }
+ return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.h b/QuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.h
new file mode 100644
index 0000000..91d2a80
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.h
@@ -0,0 +1,338 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ FwBlockService.h
+
+Abstract:
+
+ Firmware volume block driver for SPI device
+
+--*/
+
+#ifndef _FW_BLOCK_SERVICE_H
+#define _FW_BLOCK_SERVICE_H
+
+
+#include "SpiFlashDevice.h"
+#include "EfiFlashMap.h"
+#include "FlashMap.h"
+#include "FlashLayout.h"
+
+//
+// Statements that include other header files
+
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "Guid/FlashMapHob.h"
+#include <Guid/EventGroup.h>
+#include <Guid/HobList.h>
+#include <Guid/FirmwareFileSystem.h>
+#include <Guid/SystemNvDataGuid.h>
+
+#include <Protocol/SmmBase2.h>
+#include <Protocol/FvbExtension.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/PlatformType.h>
+#include <Protocol/PlatformSmmSpiReady.h>
+
+#include <Framework/FirmwareVolumeHeader.h>
+#include <CpuRegs.h>
+
+
+
+#define EFI_INTERNAL_POINTER 0x00000004
+#define FVB_PHYSICAL 0
+#define FVB_VIRTUAL 1
+
+typedef struct {
+ EFI_LOCK FvbDevLock;
+ UINTN FvBase[2];
+ UINTN FvWriteBase[2];
+ UINTN NumOfBlocks;
+ BOOLEAN WriteEnabled;
+ EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
+} EFI_FW_VOL_INSTANCE;
+
+typedef struct {
+ UINT32 NumFv;
+ EFI_FW_VOL_INSTANCE *FvInstance[2];
+ UINT8 *FvbScratchSpace[2];
+ EFI_SPI_PROTOCOL *SpiProtocol;
+ EFI_SPI_PROTOCOL *SmmSpiProtocol;
+} ESAL_FWB_GLOBAL;
+
+//
+// SPI default opcode slots
+//
+#define SPI_OPCODE_JEDEC_ID_INDEX 0
+#define SPI_OPCODE_READ_ID_INDEX 1
+#define SPI_OPCODE_WRITE_S_INDEX 2
+#define SPI_OPCODE_WRITE_INDEX 3
+#define SPI_OPCODE_READ_INDEX 4
+#define SPI_OPCODE_ERASE_INDEX 5
+#define SPI_OPCODE_READ_S_INDEX 6
+#define SPI_OPCODE_CHIP_ERASE_INDEX 7
+
+#define SPI_ERASE_SECTOR_SIZE FLASH_BLOCK_SIZE //This is the chipset requirement
+
+//
+// Fvb Protocol instance data
+//
+#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)
+#define FVB_EXTEND_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, FvbExtension, FVB_DEVICE_SIGNATURE)
+#define FVB_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'V', 'B', 'C')
+//
+// Device Path
+//
+#define EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
+#define EfiDevicePathType(a) (((a)->Type) & 0x7f)
+#define EfiIsDevicePathEndType(a) (EfiDevicePathType (a) == 0x7f)
+#define EfiIsDevicePathEndSubType(a) ((a)->SubType == EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)
+#define EfiIsDevicePathEnd(a) (EfiIsDevicePathEndType (a) && EfiIsDevicePathEndSubType (a))
+
+typedef struct {
+ MEMMAP_DEVICE_PATH MemMapDevPath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevPath;
+} FV_DEVICE_PATH;
+
+typedef struct {
+ UINTN Signature;
+ FV_DEVICE_PATH DevicePath;
+ UINTN Instance;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance;
+ EFI_FVB_EXTENSION_PROTOCOL FvbExtension;
+} EFI_FW_VOL_BLOCK_DEVICE;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_FIRMWARE_VOLUME_HEADER FvbInfo;
+ //
+ // EFI_FV_BLOCK_MAP_ENTRY ExtraBlockMap[n];//n=0
+ //
+ EFI_FV_BLOCK_MAP_ENTRY End[1];
+} EFI_FVB_MEDIA_INFO;
+
+VOID
+FvbVirtualddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+GetFvbInfo (
+ IN EFI_PHYSICAL_ADDRESS FvBaseAddress,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo
+ );
+
+BOOLEAN
+SetPlatformFvbLock (
+ IN UINTN LbaAddress
+ );
+
+EFI_STATUS
+FvbReadBlock (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BlockOffset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+EFI_STATUS
+FvbWriteBlock (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BlockOffset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+EFI_STATUS
+FvbEraseBlock (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+EFI_STATUS
+FvbSetVolumeAttributes (
+ IN UINTN Instance,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+EFI_STATUS
+FvbGetVolumeAttributes (
+ IN UINTN Instance,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+EFI_STATUS
+FvbGetPhysicalAddress (
+ IN UINTN Instance,
+ OUT EFI_PHYSICAL_ADDRESS *Address,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+EFI_STATUS
+FvbInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+VOID
+FvbClassAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+FvbSpecificInitialize (
+ IN ESAL_FWB_GLOBAL *mFvbModuleGlobal
+ );
+
+EFI_STATUS
+FvbGetLbaAddress (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ OUT UINTN *LbaAddress,
+ OUT UINTN *LbaWriteAddress,
+ OUT UINTN *LbaLength,
+ OUT UINTN *NumOfBlocks,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+EFI_STATUS
+FvbEraseCustomBlockRange (
+ IN UINTN Instance,
+ IN EFI_LBA StartLba,
+ IN UINTN OffsetStartLba,
+ IN EFI_LBA LastLba,
+ IN UINTN OffsetLastLba,
+ IN ESAL_FWB_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+//
+// Protocol APIs
+//
+EFI_STATUS
+EFIAPI
+FvbProtocolGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ );
+
+EFI_STATUS
+FvbProtocolGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumOfBlocks
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ );
+
+EFI_STATUS
+FvbExtendProtocolEraseCustomBlockRange (
+ IN EFI_FVB_EXTENSION_PROTOCOL *This,
+ IN EFI_LBA StartLba,
+ IN UINTN OffsetStartLba,
+ IN EFI_LBA LastLba,
+ IN UINTN OffsetLastLba
+ );
+
+extern EFI_GUID gEfiAlternateFvBlockGuid;
+extern SPI_INIT_TABLE mSpiInitTable[];
+
+#endif
diff --git a/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.c b/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.c
new file mode 100644
index 0000000..323cc0d
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.c
@@ -0,0 +1,63 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PlatformSmmSpi.c
+
+Abstract:
+
+Revision History
+
+--*/
+
+#include "FwBlockService.h"
+
+
+/**
+ This function allows the caller to determine if UEFI SetVirtualAddressMap() has been called.
+
+ This function returns TRUE after all the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE functions have
+ executed as a result of the OS calling SetVirtualAddressMap(). Prior to this time FALSE
+ is returned. This function is used by runtime code to decide it is legal to access services
+ that go away after SetVirtualAddressMap().
+
+ @retval TRUE The system has finished executing the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+ @retval FALSE The system has not finished executing the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+
+**/
+BOOLEAN
+EfiGoneVirtual (
+ VOID
+ )
+{
+ return FALSE; //Hard coded to FALSE for SMM driver.
+}
diff --git a/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.inf b/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.inf
new file mode 100644
index 0000000..ed3076f
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.inf
@@ -0,0 +1,116 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Module Name:
+#
+# PlatformSmmSpi.inf
+#
+# Abstract:
+#
+# Component description file for SpiFvbServices Module
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FwBlockServiceSmm
+ FILE_GUID = A469DDBD-16D0-4535-BAE3-77274BD70B4C
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = FvbInitialize
+
+[Sources]
+ FwBlockService.c
+ FwBlockService.h
+ FvbInfo.c
+ SpiFlashDevice.c
+ SpiFlashDevice.h
+ PlatformSmmSpi.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ IoLib
+ PcdLib
+ HobLib
+ UefiLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ MemoryAllocationLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+
+[Guids]
+ gEfiFlashMapHobGuid
+ gEfiEventVirtualAddressChangeGuid
+ gEfiHobListGuid
+
+ [Protocols]
+ gEfiPciRootBridgeIoProtocolGuid ##Consumes
+ gEfiFirmwareVolumeBlockProtocolGuid ##Produces
+ gEfiFvbExtensionProtocolGuid ##Produces
+ gEfiAlternateFvBlockGuid ##Produces
+ gEfiSpiProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiLoadedImageProtocolGuid
+ gEfiSmmBase2ProtocolGuid
+ gEfiSmmSpiProtocolGuid
+ gEfiSmmFirmwareVolumeBlockProtocolGuid
+ gEfiPlatformTypeProtocolGuid
+ gEfiSmmSpiReadyProtocolGuid
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize
+
+[Pcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoveryBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoverySize
+
+[Depex]
+ gEfiPciRootBridgeIoProtocolGuid AND
+ gEfiSpiProtocolGuid AND
+ gEfiSmmRuntimeProtocolGuid
+
diff --git a/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSpi.inf b/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSpi.inf
new file mode 100644
index 0000000..6506965
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSpi.inf
@@ -0,0 +1,113 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Module Name:
+#
+# PlatformSpi.inf
+#
+# Abstract:
+#
+# Component description file for SpiFvbServices Module
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FwBlockService
+ FILE_GUID = 4D35A5A7-622E-4955-A5D2-CDA812940D74
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FvbInitialize
+
+[Sources]
+ FwBlockService.c
+ FwBlockService.h
+ FvbInfo.c
+ SpiFlashDevice.c
+ SpiFlashDevice.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ IoLib
+ PcdLib
+ HobLib
+ UefiLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ MemoryAllocationLib
+ UefiRuntimeLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+
+[Guids]
+ gEfiFlashMapHobGuid
+ gEfiEventVirtualAddressChangeGuid
+ gEfiHobListGuid
+
+ [Protocols]
+ gEfiPciRootBridgeIoProtocolGuid ##Consumes
+ gEfiFirmwareVolumeBlockProtocolGuid ##Produces
+ gEfiFvbExtensionProtocolGuid ##Produces
+ gEfiAlternateFvBlockGuid ##Produces
+ gEfiSpiProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiLoadedImageProtocolGuid
+ gEfiSmmBase2ProtocolGuid
+ gEfiSmmSpiProtocolGuid
+ gEfiSmmFirmwareVolumeBlockProtocolGuid
+ gEfiPlatformTypeProtocolGuid
+ gEfiSmmSpiReadyProtocolGuid
+
+[FixedPcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize
+
+[Pcd]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainSize
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoveryBase
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoverySize
+
+[Depex]
+ gEfiSpiProtocolGuid AND
+ gEfiPlatformTypeProtocolGuid
diff --git a/QuarkPlatformPkg/Platform/SpiFvbServices/SpiFlashDevice.c b/QuarkPlatformPkg/Platform/SpiFvbServices/SpiFlashDevice.c
new file mode 100755
index 0000000..809cb6e
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/SpiFvbServices/SpiFlashDevice.c
@@ -0,0 +1,360 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SpiFlashDevice.c
+
+Abstract:
+
+Initializes Platform Specific Drivers.
+
+--*/
+
+#include "SpiFlashDevice.h"
+
+SPI_INIT_TABLE mSpiInitTable[] = {
+ //
+ // Macronix 32Mbit part
+ //
+ {
+ SPI_MX25L3205_ID1,
+ SPI_MX25L3205_ID2,
+ SPI_MX25L3205_ID3,
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle33MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle20MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x400000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // Winbond 32Mbit part
+ //
+ {
+ SPI_W25X32_ID1,
+ SF_DEVICE_ID0_W25QXX,
+ SF_DEVICE_ID1_W25Q32,
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x400000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // Winbond 32Mbit part
+ //
+ {
+ SPI_W25X32_ID1,
+ SPI_W25X32_ID2,
+ SPI_W25X32_ID3,
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle33MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_4K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x400000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // Atmel 32Mbit part
+ //
+ {
+ SPI_AT26DF321_ID1,
+ SPI_AT26DF321_ID2, // issue: byte 2 identifies family/density for Atmel
+ SPI_AT26DF321_ID3,
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle33MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x400000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+
+ //
+ // Intel 32Mbit part bottom boot
+ //
+ {
+ SPI_QH25F320_ID1,
+ SPI_QH25F320_ID2,
+ SPI_QH25F320_ID3,
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_ENABLE
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle33MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+ },
+ 0, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // SST 64Mbit part
+ //
+ {
+ SPI_SST25VF080B_ID1, // VendorId
+ SF_DEVICE_ID0_25VF064C, // DeviceId 0
+ SF_DEVICE_ID1_25VF064C, // DeviceId 1
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x800000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // NUMONYX 64Mbit part
+ //
+ {
+ SF_VENDOR_ID_NUMONYX, // VendorId
+ SF_DEVICE_ID0_M25PX64, // DeviceId 0
+ SF_DEVICE_ID1_M25PX64, // DeviceId 1
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x800000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // Atmel 64Mbit part
+ //
+ {
+ SF_VENDOR_ID_ATMEL, // VendorId
+ SF_DEVICE_ID0_AT25DF641, // DeviceId 0
+ SF_DEVICE_ID1_AT25DF641, // DeviceId 1
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x800000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+
+ //
+ // Spansion 64Mbit part
+ //
+ {
+ SF_VENDOR_ID_SPANSION, // VendorId
+ SF_DEVICE_ID0_S25FL064K, // DeviceId 0
+ SF_DEVICE_ID1_S25FL064K, // DeviceId 1
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x800000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+
+ //
+ // Macronix 64Mbit part bottom boot
+ //
+ {
+ SF_VENDOR_ID_MX, // VendorId
+ SF_DEVICE_ID0_25L6405D, // DeviceId 0
+ SF_DEVICE_ID1_25L6405D, // DeviceId 1
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x800000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // Winbond 64Mbit part bottom boot
+ //
+ {
+ SPI_W25X64_ID1,
+ SF_DEVICE_ID0_W25QXX,
+ SF_DEVICE_ID1_W25Q64,
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x800000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // Winbond 64Mbit part bottom boot
+ //
+ {
+ SPI_W25X64_ID1,
+ SPI_W25X64_ID2,
+ SPI_W25X64_ID3,
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x800000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ },
+ //
+ // Intel 64Mbit part bottom boot
+ //
+ {
+ SPI_QH25F640_ID1,
+ SPI_QH25F640_ID2,
+ SPI_QH25F640_ID3,
+ {
+ SPI_COMMAND_WRITE_ENABLE,
+ SPI_COMMAND_WRITE_S_EN
+ },
+ {
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_JEDEC_ID, EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ_ID, EnumSpiCycle33MHz, EnumSpiOperationOther},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S, EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_WRITE, EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+ {EnumSpiOpcodeRead, SPI_COMMAND_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData},
+ {EnumSpiOpcodeWrite, SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+ {EnumSpiOpcodeReadNoAddr, SPI_COMMAND_READ_S, EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+ {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE, EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+ },
+ 0x800000 - FLASH_SIZE, // BIOS Start Offset
+ FLASH_SIZE // BIOS image size in flash
+ }
+};
diff --git a/QuarkPlatformPkg/Platform/SpiFvbServices/SpiFlashDevice.h b/QuarkPlatformPkg/Platform/SpiFvbServices/SpiFlashDevice.h
new file mode 100644
index 0000000..f6cf3e0
--- /dev/null
+++ b/QuarkPlatformPkg/Platform/SpiFvbServices/SpiFlashDevice.h
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SpiFlashDevice.h
+
+Abstract:
+
+
+
+--*/
+
+#ifndef _SPI_FLASH_DEVICE_H_
+#define _SPI_FLASH_DEVICE_H_
+
+#include "FlashLayout.h"
+
+#include <PiDxe.h>
+#include <Protocol/Spi.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+//
+// Supported SPI Flash Devices
+//
+typedef enum {
+ EnumSpiFlash25L3205D, // Macronix 32Mbit part
+ EnumSpiFlashW25Q32, // Winbond 32Mbit part
+ EnumSpiFlashW25X32, // Winbond 32Mbit part
+ EnumSpiFlashAT25DF321, // Atmel 32Mbit part
+ EnumSpiFlashQH25F320, // Intel 32Mbit part
+ EnumSpiFlash25VF064C, // SST 64Mbit part
+ EnumSpiFlashM25PX64, // NUMONYX 64Mbit part
+ EnumSpiFlashAT25DF641, // Atmel 64Mbit part
+ EnumSpiFlashS25FL064K, // Spansion 64Mbit part
+ EnumSpiFlash25L6405D, // Macronix 64Mbit part
+ EnumSpiFlashW25Q64, // Winbond 64Mbit part
+ EnumSpiFlashW25X64, // Winbond 64Mbit part
+ EnumSpiFlashQH25F640, // Intel 64Mbit part
+ EnumSpiFlashMax
+} SPI_FLASH_TYPES_SUPPORTED;
+
+//
+// Flash Device commands
+//
+// If a supported device uses a command different from the list below, a device specific command
+// will be defined just below it's JEDEC id section.
+//
+#define SPI_COMMAND_WRITE 0x02
+#define SPI_COMMAND_WRITE_AAI 0xAD
+#define SPI_COMMAND_READ 0x03
+#define SPI_COMMAND_ERASE 0x20
+#define SPI_COMMAND_WRITE_DISABLE 0x04
+#define SPI_COMMAND_READ_S 0x05
+#define SPI_COMMAND_WRITE_ENABLE 0x06
+#define SPI_COMMAND_READ_ID 0xAB
+#define SPI_COMMAND_JEDEC_ID 0x9F
+#define SPI_COMMAND_WRITE_S_EN 0x50
+#define SPI_COMMAND_WRITE_S 0x01
+#define SPI_COMMAND_CHIP_ERASE 0xC7
+#define SPI_COMMAND_BLOCK_ERASE 0xD8
+
+//
+// Flash JEDEC device ids
+//
+// SST 8Mbit part
+//
+#define SPI_SST25VF080B_ID1 0xBF
+#define SPI_SST25VF080B_ID2 0x25
+#define SPI_SST25VF080B_ID3 0x8E
+//
+// SST 16Mbit part
+//
+#define SPI_SST25VF016B_ID1 0xBF
+#define SPI_SST25VF016B_ID2 0x25
+#define SPI_SST25V016BF_ID3 0x41
+//
+// Macronix 32Mbit part
+//
+// MX25 part does not support WRITE_AAI comand (0xAD)
+//
+#define SPI_MX25L3205_ID1 0xC2
+#define SPI_MX25L3205_ID2 0x20
+#define SPI_MX25L3205_ID3 0x16
+//
+// Intel 32Mbit part bottom boot
+//
+#define SPI_QH25F320_ID1 0x89
+#define SPI_QH25F320_ID2 0x89
+#define SPI_QH25F320_ID3 0x12 // 32Mbit bottom boot
+//
+// Intel 64Mbit part bottom boot
+//
+#define SPI_QH25F640_ID1 0x89
+#define SPI_QH25F640_ID2 0x89
+#define SPI_QH25F640_ID3 0x13 // 64Mbit bottom boot
+//
+// QH part does not support command 0x20 for erase; only 0xD8 (sector erase)
+// QH part has 0x40 command for erase of parameter block (8 x 8K blocks at bottom of part)
+// 0x40 command ignored if address outside of parameter block range
+//
+#define SPI_QH25F320_COMMAND_PBLOCK_ERASE 0x40
+//
+// Winbond 32Mbit part
+//
+#define SPI_W25X32_ID1 0xEF
+#define SPI_W25X32_ID2 0x30 // Memory Type
+#define SPI_W25X32_ID3 0x16 // Capacity
+#define SF_DEVICE_ID1_W25Q32 0x16
+
+//
+// Winbond 64Mbit part
+//
+#define SPI_W25X64_ID1 0xEF
+#define SPI_W25X64_ID2 0x30 // Memory Type
+#define SPI_W25X64_ID3 0x17 // Capacity
+#define SF_DEVICE_ID0_W25QXX 0x40
+#define SF_DEVICE_ID1_W25Q64 0x17
+//
+// Winbond 128Mbit part
+//
+#define SF_DEVICE_ID0_W25Q128 0x40
+#define SF_DEVICE_ID1_W25Q128 0x18
+
+//
+// Atmel 32Mbit part
+//
+#define SPI_AT26DF321_ID1 0x1F
+#define SPI_AT26DF321_ID2 0x47 // [7:5]=Family, [4:0]=Density
+#define SPI_AT26DF321_ID3 0x00
+
+#define SF_VENDOR_ID_ATMEL 0x1F
+#define SF_DEVICE_ID0_AT25DF641 0x48
+#define SF_DEVICE_ID1_AT25DF641 0x00
+
+//
+// SST 8Mbit part
+//
+#define SPI_SST25VF080B_ID1 0xBF
+#define SPI_SST25VF080B_ID2 0x25
+#define SPI_SST25VF080B_ID3 0x8E
+#define SF_DEVICE_ID0_25VF064C 0x25
+#define SF_DEVICE_ID1_25VF064C 0x4B
+
+//
+// SST 16Mbit part
+//
+#define SPI_SST25VF016B_ID1 0xBF
+#define SPI_SST25VF016B_ID2 0x25
+#define SPI_SST25V016BF_ID3 0x41
+
+//
+// Winbond 32Mbit part
+//
+#define SPI_W25X32_ID1 0xEF
+#define SPI_W25X32_ID2 0x30 // Memory Type
+#define SPI_W25X32_ID3 0x16 // Capacity
+
+#define SF_VENDOR_ID_MX 0xC2
+#define SF_DEVICE_ID0_25L6405D 0x20
+#define SF_DEVICE_ID1_25L6405D 0x17
+
+#define SF_VENDOR_ID_NUMONYX 0x20
+#define SF_DEVICE_ID0_M25PX64 0x71
+#define SF_DEVICE_ID1_M25PX64 0x17
+
+//
+// Spansion 64Mbit part
+//
+#define SF_VENDOR_ID_SPANSION 0xEF
+#define SF_DEVICE_ID0_S25FL064K 0x40
+#define SF_DEVICE_ID1_S25FL064K 0x00
+
+//
+// index for prefix opcodes
+//
+#define SPI_WREN_INDEX 0 // Prefix Opcode 0: SPI_COMMAND_WRITE_ENABLE
+#define SPI_EWSR_INDEX 1 // Prefix Opcode 1: SPI_COMMAND_WRITE_S_EN
+#define BIOS_CTRL 0xDC
+
+#define PFAB_CARD_DEVICE_ID 0x5150
+#define PFAB_CARD_VENDOR_ID 0x8086
+#define PFAB_CARD_SETUP_REGISTER 0x40
+#define PFAB_CARD_SETUP_BYTE 0x0d
+
+
+#endif
diff --git a/QuarkPlatformPkg/QuarkPlatformPkg.dec b/QuarkPlatformPkg/QuarkPlatformPkg.dec
new file mode 100755
index 0000000..30eacab
--- /dev/null
+++ b/QuarkPlatformPkg/QuarkPlatformPkg.dec
@@ -0,0 +1,949 @@
+## @file
+# Package for support of Clanton Peak CRB platform
+#
+# This package provides QuarkNcSocId platform specific modules.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = QuarkPlatformPkg
+ PACKAGE_GUID = 46C1F476-A85E-49a8-B258-DD4396B87FEF
+ PACKAGE_VERSION = 0.1
+
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+# Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+# SEC PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER
+#
+################################################################################
+[Includes]
+ Include # SEC
+ Include/Cpu
+ Include/Iio
+
+################################################################################
+#
+# Library Class Header section - list of Library Class header files that are
+# provided by this package.
+#
+################################################################################
+[LibraryClasses]
+
+################################################################################
+#
+# Global Guid Definition section - list of Global Guid C Name Data Structures
+# that are provided by this package.
+#
+################################################################################
+[Guids]
+ gQuarkPlatformTokenSpaceGuid = { 0x199c1ef0, 0x6400, 0x41c5, { 0xb0, 0xa4, 0xff, 0xbf, 0x21, 0x9d, 0xcb, 0xae }}
+ gEfiPlatformInfoGuid = { 0x1e2acc41, 0xe26a, 0x483d, { 0xaf, 0xc7, 0xa0, 0x56, 0xc3, 0x4e, 0x8, 0x7b }}
+ gEfiUuidVariableGuid = { 0xD357C710, 0x0ADA, 0x4717, { 0x8D, 0xBA, 0xC6, 0xAD, 0xC7, 0xCD, 0x2B, 0x2A }}
+ gEfiFirmwareIdGuid = { 0xEFC071AE, 0x41B8, 0x4018, { 0xAF, 0xA7, 0x31, 0x4B, 0x18, 0x5E, 0x57, 0x8B }}
+ gSysConfigGuid = { 0xec87d643, 0xeba4, 0x4bb5, { 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0x0d, 0xa9 }}
+ gEfiPlatformMemoryLayoutGuid = { 0x41C7B74E, 0xB839, 0x40D9, { 0xA0, 0x56, 0xE3, 0xCA, 0xFC, 0x98, 0x0A, 0xAC }}
+ gEfiMemoryConfigDataGuid = { 0x80dbd530, 0xb74c, 0x4f11, { 0x8c, 0x03, 0x41, 0x86, 0x65, 0x53, 0x28, 0x31 }}
+ gPowerManagementAcpiTableStorageGuid = { 0xc0cc43bd, 0xc920, 0x4064, { 0x93, 0x5b, 0x93, 0xb4, 0x47, 0x37, 0x94, 0x70 }}
+ gSignalBeforeEnterSetupGuid = { 0xd9f1669a, 0xf505, 0x48bd, { 0xa8, 0x92, 0x94, 0xb7, 0xca, 0x90, 0x30, 0x31 }}
+ gEfiSetupVariableGuid = {0xec87d643, 0xeba4, 0x4bb5, {0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0xd, 0xa9 }}
+ gEfiFlashMapHobGuid = {0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59}}
+ gPeiCapsuleOnFatFloppyDiskGuid = {0x2e3d2e75, 0x9b2e, 0x412d, {0xb4, 0xb1, 0x70, 0x41, 0x6b, 0x87, 0x0, 0xff }}
+ gPeiCapsuleOnFatIdeDiskGuid = {0xb38573b6, 0x6200, 0x4ac5, {0xb5, 0x1d, 0x82, 0xe6, 0x59, 0x38, 0xd7, 0x83 }}
+ gPeiCapsuleOnFatUsbDiskGuid = {0x0ffbce19, 0x324c, 0x4690, {0xa0, 0x09, 0x98, 0xc6, 0xae, 0x2e, 0xb1, 0x86 }}
+ gPeiCapsuleOnDataCDGuid = {0x5cac0099, 0x0dc9, 0x48e5, {0x80, 0x68, 0xbb, 0x95, 0xf5, 0x40, 0x0a, 0x9f }}
+ gEfiQuarkCapsuleGuid = { 0xd400d1e4, 0xa314, 0x442b, { 0x89, 0xed, 0xa9, 0x2e, 0x4c, 0x81, 0x97, 0xcb } }
+ gEfiQuarkCapsuleSecurityHeaderGuid = { 0xc3cdd08c, 0x796d, 0x491c, { 0x93, 0x54, 0x5d, 0x59, 0xc2, 0x89, 0xf2, 0xd6 }}
+ gQuarkVariableLockGuid = { 0xeef749c2, 0xc047, 0x4d6e, { 0xb1, 0xbc, 0xd3, 0x6e, 0xb3, 0xa5, 0x55, 0x9c }}
+
+################################################################################
+#
+# Global Protocols Definition section - list of Global Protocols C Name Data
+# Structures that are provided by this package.
+#
+################################################################################
+[Protocols]
+ gEfiGlobalNvsAreaProtocolGuid = { 0x074E1E48, 0x8132, 0x47A1, { 0x8C, 0x2C, 0x3F, 0x14, 0xAD, 0x9A, 0x66, 0xDC }}
+ gEfiFvbExtensionProtocolGuid = { 0x53a4c71b, 0xb581, 0x4170, {0x91, 0xb3, 0x8d, 0xb8, 0x7a, 0x4b, 0x5c, 0x46}}
+ gEfiAlternateFvBlockGuid = { 0xf496922d, 0x172f, 0x4bbc, {0xa1, 0xeb, 0xe, 0xeb, 0x94, 0x9c, 0x34, 0x86}}
+ gEfiSmmSpiReadyProtocolGuid = { 0x7a5dbc75, 0x5b2b, 0x4e67, { 0xbd, 0xe1, 0xd4, 0x8e, 0xee, 0x76, 0x15, 0x62 }}
+ gEfiSmmRuntimeProtocolGuid = { 0xa56897a1, 0xa77f, 0x4600, { 0x84, 0xdb, 0x22, 0xb0, 0xa8, 0x1, 0xfa, 0x9a } }
+ gEfiIioUdsProtocolGuid = { 0xa7ced760, 0xc71c, 0x4e1a, { 0xac, 0xb1, 0x89, 0x60, 0x4d, 0x52, 0x16, 0xcb }}
+ gEfiPlatformTypeProtocolGuid = { 0x171e9398, 0x269c, 0x4081, { 0x90, 0x99, 0x38, 0x44, 0xe2, 0x60, 0x46, 0x6c }}
+ gSecureBootHelperProtocolGuid = { 0x122b109b, 0xdb9b, 0x4f03, { 0x96, 0x9c, 0x17, 0xf1, 0x4e, 0x10, 0xfe, 0xcd }}
+ gFirmwareVolumeBlockSecurityGuid = { 0x41c7f059, 0x81a, 0x4f45, { 0xb1, 0xf0, 0xc5, 0xa9, 0x88, 0x91, 0x52, 0x21 }}
+
+################################################################################
+#
+# Global Ppis Definition section - list of Global Ppis C Name Data Structures
+# that are provided by this package.
+#
+################################################################################
+[Ppis]
+ gPeiSStateBootModePpiGuid = { 0x9c44db3d, 0xf434, 0x4b91, { 0x8e, 0xb3, 0x30, 0x38, 0xb1, 0x84, 0xab, 0xfc }}
+ gPeiFlashMapPpiGuid = {0xf34c2fa0, 0xde88, 0x4270, {0x84, 0x14, 0x96, 0x12, 0x22, 0xf4, 0x52, 0x1c}}
+
+################################################################################
+#
+# PCD Declarations section - list of all PCDs Declared by this Package
+# Only this package should be providing the
+# declaration, other packages should not.
+#
+################################################################################
+
+[PcdsFeatureFlag]
+ gQuarkPlatformTokenSpaceGuid.PcdMultipleFlashSupportLibDoSystemInitialization|TRUE|BOOLEAN|0x2000000D
+ gQuarkPlatformTokenSpaceGuid.PcdEnableNetworkBoot|FALSE|BOOLEAN|0x2000001A
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock|FALSE|BOOLEAN|0x2000000E
+ gQuarkPlatformTokenSpaceGuid.WaitIfResetDueToError|FALSE|BOOLEAN|0x2000000F
+ gQuarkPlatformTokenSpaceGuid.PcdSupportSecureBoot|FALSE|BOOLEAN|0x20000010
+
+ ## This PCD controls whether to force local display
+ # Virtual platform may not care the local display for fast boot
+ gQuarkPlatformTokenSpaceGuid.PcdBdsFindDisplay|FALSE|BOOLEAN|0x00000001
+
+ gQuarkPlatformTokenSpaceGuid.PcdShortformBootSupport|TRUE|BOOLEAN|0x00000002
+
+[PcdsFixedAtBuild]
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress|0xFFC00000|UINT32|0x20000001
+ gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize|0x400000|UINT32|0x20000002
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageBase|0xFFF30000|UINT32|0x20000003
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageSize|0x00020000|UINT32|0x20000004
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecovery2Base|0xFFEF0400|UINT32|0x2000001C
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecovery2Size|0x00007000|UINT32|0x2000001D
+ gQuarkPlatformTokenSpaceGuid.PcdFlashQNCMicrocodeSize|0x00004000|UINT32|0x2000000C
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformDataBaseAddress|0xFFF10000|UINT32|0x2000001E
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformDataMaxLen|0x20000|UINT32|0x2000001F
+ gQuarkPlatformTokenSpaceGuid.PcdHpetEnable|TRUE|BOOLEAN|0x20000018
+ gQuarkPlatformTokenSpaceGuid.PcdMemorySize|0x80000000|UINT32|0x20000032
+ gQuarkPlatformTokenSpaceGuid.PcdFvSecurityHeaderSize|0x400|UINT32|0x20000036
+ # ECC scrub interval in miliseconds 1..255 (0 works as feature disable)
+ gQuarkPlatformTokenSpaceGuid.PcdEccScrubInterval|0x00|UINT8|0x20000037
+ # Number of 32B blocks read for ECC scrub 2..16
+ gQuarkPlatformTokenSpaceGuid.PcdEccScrubBlkSize|0x02|UINT8|0x20000038
+ gQuarkPlatformTokenSpaceGuid.PcdFlashNvMfh|0xFFF08000|UINT32|0x20000039
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaBase|0xFFF90000|UINT32|0x2000003A
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvFixedStage1AreaSize|0x00040000|UINT32|0x2000003B
+ gQuarkPlatformTokenSpaceGuid.PcdEsramStage1Base|0x80000000|UINT32|0x2000003C
+
+ # Legacy Bridge protected BIOS range register configs, if == 0 then do nothing since register default.
+ gQuarkPlatformTokenSpaceGuid.PcdLegacyProtectedBIOSRange0Pei|0x00000000|UINT32|0x2000003D
+ gQuarkPlatformTokenSpaceGuid.PcdLegacyProtectedBIOSRange1Pei|0x00000000|UINT32|0x2000003E
+ gQuarkPlatformTokenSpaceGuid.PcdLegacyProtectedBIOSRange2Pei|0x00000000|UINT32|0x2000004F
+
+ # If true, enable fast boot feature. the behaviour is totally difference to normal boot.
+ gQuarkPlatformTokenSpaceGuid.PcdEnableFastBoot|TRUE|BOOLEAN|0x20000050
+
+ # FFS filename to find the Payload application.
+ # The FFS filename is B43BD3E1-64D1-4744-9394-D0E1C4DE8C87.
+ gQuarkPlatformTokenSpaceGuid.PcdPayloadFile|{ 0xe1, 0xd3, 0x3b, 0xb4, 0xd1, 0x64, 0x44, 0x47, 0x93, 0x94, 0xd0, 0xe1, 0xc4, 0xde, 0x8c, 0x87 }|VOID*|0xA0000030
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table0,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table0
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0Enable|0x01|UINT8|0xA0000100
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0SourceIrq|0x00|UINT8|0xA0000101
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0Polarity|0x00|UINT8|0xA0000102
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0TrigerMode|0x00|UINT8|0xA0000103
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0GlobalIrq|0x02|UINT32|0xA0000104
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table1,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table1
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1Enable|0x01|UINT8|0xA0000105
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1SourceIrq|0x09|UINT8|0xA0000106
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1Polarity|0x01|UINT8|0xA0000107
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1TrigerMode|0x03|UINT8|0xA0000108
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1GlobalIrq|0x09|UINT32|0xA0000109
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table2,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table2
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2Enable|0x0|UINT8|0xA000010F
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2SourceIrq|0x0|UINT8|0xA0000110
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2Polarity|0x0|UINT8|0xA0000111
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2TrigerMode|0x0|UINT8|0xA0000112
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2GlobalIrq|0x0|UINT32|0xA0000113
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table3,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table3
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3Enable|0x0|UINT8|0xA0000114
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3SourceIrq|0x0|UINT8|0xA0000115
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3Polarity|0x0|UINT8|0xA0000116
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3TrigerMode|0x0|UINT8|0xA0000117
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3GlobalIrq|0x0|UINT32|0xA0000118
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table4,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table4
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4Enable|0x0|UINT8|0xA0000119
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4SourceIrq|0x0|UINT8|0xA000011A
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4Polarity|0x0|UINT8|0xA0000120
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4TrigerMode|0x0|UINT8|0xA0000121
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4GlobalIrq|0x0|UINT32|0xA0000122
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table5,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table5
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5Enable|0x0|UINT8|0xA0000123
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5SourceIrq|0x0|UINT8|0xA0000124
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5Polarity|0x0|UINT8|0xA0000125
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5TrigerMode|0x0|UINT8|0xA0000126
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5GlobalIrq|0x0|UINT32|0xA0000127
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table6,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table6
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6Enable|0x0|UINT8|0xA0000128
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6SourceIrq|0x0|UINT8|0xA0000129
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6Polarity|0x0|UINT8|0xA000012A
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6TrigerMode|0x0|UINT8|0xA000012B
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6GlobalIrq|0x0|UINT32|0xA000012C
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table7,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table7
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7Enable|0x0|UINT8|0xA000012D
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7SourceIrq|0x0|UINT8|0xA000012E
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7Polarity|0x0|UINT8|0xA000012F
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7TrigerMode|0x0|UINT8|0xA0000130
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7GlobalIrq|0x0|UINT32|0xA0000131
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table8,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table8
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8Enable|0x0|UINT8|0xA0000132
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8SourceIrq|0x0|UINT8|0xA0000133
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8Polarity|0x0|UINT8|0xA0000134
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8TrigerMode|0x0|UINT8|0xA0000135
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8GlobalIrq|0x0|UINT32|0xA0000136
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table9,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table9
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9Enable|0x0|UINT8|0xA0000137
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9SourceIrq|0x0|UINT8|0xA0000138
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9Polarity|0x0|UINT8|0xA0000139
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9TrigerMode|0x0|UINT8|0xA000013A
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9GlobalIrq|0x0|UINT32|0xA000013B
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table10,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table10
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10Enable|0x0|UINT8|0xA000013C
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10SourceIrq|0x0|UINT8|0xA000013D
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10Polarity|0x0|UINT8|0xA000013E
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10TrigerMode|0x0|UINT8|0xA000013F
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10GlobalIrq|0x0|UINT32|0xA0000140
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table11,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table11
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11Enable|0x0|UINT8|0xA0000141
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11SourceIrq|0x0|UINT8|0xA0000142
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11Polarity|0x0|UINT8|0xA0000143
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11TrigerMode|0x0|UINT8|0xA0000144
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11GlobalIrq|0x0|UINT32|0xA0000145
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table12,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table12
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12Enable|0x0|UINT8|0xA0000146
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12SourceIrq|0x0|UINT8|0xA0000147
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12Polarity|0x0|UINT8|0xA0000148
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12TrigerMode|0x0|UINT8|0xA0000149
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12GlobalIrq|0x0|UINT32|0xA000014A
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table13,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table13
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13Enable|0x0|UINT8|0xA000014B
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13SourceIrq|0x0|UINT8|0xA000014C
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13Polarity|0x0|UINT8|0xA000014D
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13TrigerMode|0x0|UINT8|0xA000014E
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13GlobalIrq|0x0|UINT32|0xA000014F
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table14,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table14
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14Enable|0x0|UINT8|0xA0000150
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14SourceIrq|0x0|UINT8|0xA0000151
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14Polarity|0x0|UINT8|0xA0000152
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14TrigerMode|0x0|UINT8|0xA0000153
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14GlobalIrq|0x0|UINT32|0xA0000154
+
+ # Madt Table Initialize settings.
+ # Defines a flag to Enable/Disable interrupt override setting table15,
+ # and the source Irq, Polarity, Triger Mode and global Irq of interrupt override setting table15
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15Enable|0x0|UINT8|0xA0000155
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15SourceIrq|0x0|UINT8|0xA0000156
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15Polarity|0x0|UINT8|0xA0000157
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15TrigerMode|0x0|UINT8|0xA0000158
+ gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15GlobalIrq|0x0|UINT32|0xA0000159
+
+ # Madt Table Initialize settings.
+ # Defines a bunch of Pcds for IO APIC setting:
+ # IoApicAddress, GlobalInterruptBase, IoApicId, NmiEnable, NmiSource, Polarity and TrigerMode
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingIoApicAddress|0xFEC00000|UINT32|0xA0000170
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingGlobalInterruptBase|0x0|UINT32|0xA0000171
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingIoApicId|0x01|UINT8|0xA0000172
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingNmiEnable|0x0|UINT8|0xA0000173
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingNmiSource|0x0|UINT8|0xA0000174
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingPolarity|0x0|UINT8|0xA0000175
+ gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingTrigerMode|0x0|UINT8|0xA0000176
+
+ # Madt Table Initialize settings.
+ # Defines a bunch of Pcds for Local APIC setting:
+ # NmiEnabelApicIdMask, AddressOverrideEnable, Polarity, TrigerMode, LocalApicLint, LocalApicAddress and LocalApicAddressOverride
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingNmiEnabelApicIdMask|0x03|UINT8|0xA0000177
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingAddressOverrideEnable|0x00|UINT8|0xA0000178
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingPolarity|0x01|UINT8|0xA0000179
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingTrigerMode|0x01|UINT8|0xA000017A
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingLocalApicLint|0x01|UINT8|0xA000017B
+ gQuarkPlatformTokenSpaceGuid.PcdLocalApicAddressOverride|0x00|UINT64|0xA000017C
+
+ # PCDs for auto provisioning of UEFI 2.3.1 SecureBoot.
+ gQuarkPlatformTokenSpaceGuid.PcdPkX509File |{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }|VOID*|0xA000017D
+ gQuarkPlatformTokenSpaceGuid.PcdKekX509File |{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }|VOID*|0xA000017E
+ gQuarkPlatformTokenSpaceGuid.PcdKekRsa2048File |{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }|VOID*|0xA000017F
+
+[PcdsPatchableInModule]
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+ ## This PCD points to the file name GUID of the BootManagerMenuApp
+ # Platform can customize the PCD to point to different application for Boot Manager Menu
+ gQuarkPlatformTokenSpaceGuid.PcdBootManagerMenuFile|{ 0xdc, 0x5b, 0xc2, 0xee, 0xf2, 0x67, 0x95, 0x4d, 0xb1, 0xd5, 0xf8, 0x1b, 0x20, 0x39, 0xd1, 0x1d }|VOID*|0x00000003
+
+ #BIOS Information (Type 0), please refer spec SMBIOS 2.4, section 3.3.1 ,for following SMBIOS relates comments.
+
+ # String number of the BIOS Vendors Name
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosVendor|"Intel Corp."|VOID*|0xA0000033
+ # String number of the BIOS Release Data
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosReleaseDate|"01/01/2014"|VOID*|0xA0000035
+ # Segment location of BIOS starting address.
+ # Note: The size of the runtime BIOS image can be computed by subtracting the Starting Address Segment from 10000h and multiplying the result by 16.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosStartAddress|0xE000|UINT16|0xA0000036
+ #Defines which functions the BIOS supports. PCI, PCMCIA, Flash, etc. See 3.3.1.1.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosChar|0x03037C099880|UINT64|0xA0000037
+ #Defines which functions the BIOS supports. etc.See 3.3.1.2.1.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosCharEx1|0x03|UINT8|0xA0000038
+ #Defines which functions the BIOS supports. etc.See 3.3.1.2.2.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBiosCharEx2|0x03|UINT8|0xA0000039
+
+ # System Information (Type 1), Section 3.3.2
+ # System Manufacturer String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemManufacturer|"Intel Corp."|VOID*|0xA000003A
+ # System Product String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemProductName|"QUARK"|VOID*|0xA000003B
+ # System Version
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemVersion|"1.0"|VOID*|0xA000003C
+ # System SerialNumber String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSerialNumber|"Unknown"|VOID*|0xA000003D
+ # System UUID
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemUuid|{0x23, 0xef, 0xff, 0x13,0x54, 0x86, 0xda, 0x46, 0xa4, 0x7, 0x39, 0xc9, 0x12, 0x2, 0xd3, 0x56}|VOID*|0xA000003E
+ # Manufacturer String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSKUNumber|"System SKUNumber"|VOID*|0xA000003F
+ # System Family String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemFamily|"X1000"|VOID*|0xA0000040
+
+ # Base Board (or Module) Information (Type 2), Section 3.3.3
+ # Board Manufacturer String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBoardManufacturer|"Intel Corp."|VOID*|0xA0000041
+ # Board Product Name| String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBoardProductName|"QUARK"|VOID*|0xA0000042
+ # Board Version String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBoardVersion|"FAB-D"|VOID*|0xA0000043
+ # Board Serial Number
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSBoardSerialNumber|"3"|VOID*|0xA0000044
+ # System Enclosure or Chassis(Type 3) Section 3.3.4
+ # Chassis Manufacturer String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisManufacturer|"Chassis Manufacturer"|VOID*|0xA0000045
+ # ChassisVersion
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisVersion|"Chassis Version"|VOID*|0xA0000046
+ # Chassis SerialNumber String
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisSerialNumber|"Chassis Serial Number"|VOID*|0xA0000047
+ # Chassis Asset Tag
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisAssetTag|"Chassis Asset Tag"|VOID*|0xA0000051
+ # Chassis Type
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisType|0x00000003|UINT8|0xA0000048
+ # Identifies the state of the enclosure when it was last booted. See 3.3.4.2 for definitions.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisBootupState|0x03|UINT8|0xA0000049
+ # Identifies the state of the enclosures power supply (or supplies) when last booted. See 3.3.4.2 for definitions.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisPowerSupplyState|0x03|UINT8|0xA000004A
+ # Identifies the enclosures physical security status when last booted. See 3.3.4.3 for definitions.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisSecurityState|0x01|UINT8|0xA000004B
+ # Contains OEM- or BIOS vendor-specific information.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisOemDefined|0x0|UINT32|0xA000004C
+ # The height of the enclosure, in 'U's. A U is a standard unit of measure for the height of a rack or rack-mountable component
+ # and is equal to 1.75 inches or 4.445 cm. A value of 00h indicates that the enclosure height is unspecified.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisHeight|0x0|UINT8|0xA000004D
+ # Identifies the number of power cords associated with the enclosure or chassis. A value of 00h indicates that the number is unspecified.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisNumberPowerCords|0x0|UINT8|0xA000004E
+ # Identifies the number of Contained Element records that follow, in the range 0 to 255.
+ # Each Contained Element group comprises m bytes, as specified by the Contained Element Record Length field that follows.
+ # If no Contained Elements are included, this field is set to 0.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisElementCount|0x0|UINT8|0xA000004F
+ # Identifies the byte length of each Contained Element record that follow, in the range 0 to 255.
+ # If no Contained Elements are included, this field is set to 0. For v2.3.2 and later of this specification,
+ # this field is set to at least 03h when Contained Elements are specified.
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSChassisElementRecordLength|0x0|UINT8|0xA0000050
+
+ # Defines the number of connectors existent on the board
+ # The valid range is between 0 and 16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSConnectorNumber|16|UINT8|0xA0000060
+
+ # Defines the designator of port1 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1InternalConnectorDesignator|"X14 "|VOID*|0xA0000061
+ # Defines the designator of port1 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1ExternalConnectorDesignator|"Keyboard"|VOID*|0xA0000062
+ # Defines the type of port1 internal connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1InternalConnectorType|0x0F|UINT8|0xA0000063
+ # Defines the type of port1 external connector
+ # The valid range is between 0 to 0xFF, and 0x0F here means EfiPortConnectorTypePS2
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1ExternalConnectorType|0x0F|UINT8|0xA0000064
+ # Defines the type of port1
+ # The valid range is between 0 to 0xFF, and 0x0D here means EfiPortTypeKeyboard
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort1Type|0x0D|UINT8|0xA0000065
+
+ # Defines the designator of port2 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2InternalConnectorDesignator|"X15 "|VOID*|0xA0000066
+ # Defines the designator of port2 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2ExternalConnectorDesignator|"Mouse"|VOID*|0xA0000067
+ # Defines the type of port2 internal connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2InternalConnectorType|0x0F|UINT8|0xA0000068
+ # Defines the type of port2 external connector
+ # The valid range is between 0 to 0xFF, and 0x0F here means EfiPortConnectorTypePS2
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2ExternalConnectorType|0x0F|UINT8|0xA0000069
+ # Defines the type of port2
+ # The valid range is between 0 to 0xFF, and 0x0E here means EfiPortTypeMouse
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort2Type|0x0E|UINT8|0xA000006A
+
+ # Defines the designator of port3 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3InternalConnectorDesignator|"X16 "|VOID*|0xA000006B
+ # Defines the designator of port3 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3ExternalConnectorDesignator|"COM 1"|VOID*|0xA000006C
+ # Defines the type of port3 internal connector
+ # The valid range is between 0 to 0xFF, and 0xFF here means EfiPortConnectorTypeOther
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3InternalConnectorType|0xFF|UINT8|0xA000006D
+ # Defines the type of port3 external connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3ExternalConnectorType|0x0|UINT8|0xA000006E
+ # Defines the type of port3
+ # The valid range is between 0 to 0xFF, and 0x09 here means EfiPortTypeSerial16550ACompatible
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort3Type|0x09|UINT8|0xA000006F
+
+ # Defines the designator of port4 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4InternalConnectorDesignator|"X17 "|VOID*|0xA0000070
+ # Defines the designator of port4 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4ExternalConnectorDesignator|"COM 2"|VOID*|0xA0000071
+ # Defines the type of port4 internal connector
+ # The valid range is between 0 to 0xFF, and 0xFF here means EfiPortConnectorTypeOther
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4InternalConnectorType|0xFF|UINT8|0xA0000072
+ # Defines the type of port4 external connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4ExternalConnectorType|0x0|UINT8|0xA0000073
+ # Defines the type of port4
+ # The valid range is between 0 to 0xFF, and 0x09 here means EfiPortTypeSerial16550ACompatible
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort4Type|0x09|UINT8|0xA0000074
+
+ # Defines the designator of port5 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5InternalConnectorDesignator|"X18 "|VOID*|0xA0000075
+ # Defines the designator of port5 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5ExternalConnectorDesignator|"COM 3"|VOID*|0xA0000076
+ # Defines the type of port5 internal connector
+ # The valid range is between 0 to 0xFF, and 0xFF here means EfiPortConnectorTypeOther
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5InternalConnectorType|0xFF|UINT8|0xA0000077
+ # Defines the type of port5 external connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5ExternalConnectorType|0x0|UINT8|0xA0000078
+ # Defines the type of port5
+ # The valid range is between 0 to 0xFF, and 0x09 here means EfiPortTypeSerial16550ACompatible
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort5Type|0x09|UINT8|0xA0000079
+
+ # Defines the designator of port6 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6InternalConnectorDesignator|"X19 "|VOID*|0xA000007A
+ # Defines the designator of port6 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6ExternalConnectorDesignator|"COM 4"|VOID*|0xA000007B
+ # Defines the type of port6 internal connector
+ # The valid range is between 0 to 0xFF, and 0xFF here means EfiPortConnectorTypeOther
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6InternalConnectorType|0xFF|UINT8|0xA000007C
+ # Defines the type of port6 external connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6ExternalConnectorType|0x0|UINT8|0xA000007D
+ # Defines the type of port6
+ # The valid range is between 0 to 0xFF, and 0x09 here means EfiPortTypeSerial16550ACompatible
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort6Type|0x09|UINT8|0xA000007E
+
+ # Defines the designator of port7 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7InternalConnectorDesignator|"J4A2"|VOID*|0xA000007F
+ # Defines the designator of port7 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7ExternalConnectorDesignator|"LPT 1"|VOID*|0xA0000080
+ # Defines the type of port7 internal connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7InternalConnectorType|0x0|UINT8|0xA0000081
+ # Defines the type of port7 external connector
+ # The valid range is between 0 to 0xFF, and 0x12 here means EfiPortConnectorTypeDB25Male
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7ExternalConnectorType|0x04|UINT8|0xA0000082
+ # Defines the type of port7
+ # The valid range is between 0 to 0xFF, and 0x10 here means EfiPortTypeEcpEpp
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort7Type|0x05|UINT8|0xA0000083
+
+ # Defines the designator of port8 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8InternalConnectorDesignator|"X20 "|VOID*|0xA0000084
+ # Defines the designator of port8 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8ExternalConnectorDesignator|"USB1"|VOID*|0xA0000085
+ # Defines the type of port8 internal connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8InternalConnectorType|0x0|UINT8|0xA0000086
+ # Defines the type of port8 external connector
+ # The valid range is between 0 to 0xFF, and 0x12 here means EfiPortConnectorTypeUsb
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8ExternalConnectorType|0x12|UINT8|0xA0000087
+ # Defines the type of port8
+ # The valid range is between 0 to 0xFF, and 0x10 here means EfiPortTypeUsb
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort8Type|0x10|UINT8|0xA0000088
+
+ # Defines the designator of port9 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9InternalConnectorDesignator|"X21 "|VOID*|0xA0000089
+ # Defines the designator of port9 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9ExternalConnectorDesignator|"USB2"|VOID*|0xA000008A
+ # Defines the type of port9 internal connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9InternalConnectorType|0x0|UINT8|0xA000008B
+ # Defines the type of port9 external connector
+ # The valid range is between 0 to 0xFF, and 0x12 here means EfiPortConnectorTypeUsb
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9ExternalConnectorType|0x12|UINT8|0xA000008C
+ # Defines the type of port9
+ # The valid range is between 0 to 0xFF, and 0x10 here means EfiPortTypeUsb
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort9Type|0x10|UINT8|0xA000008D
+
+ # Defines the designator of port10 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10InternalConnectorDesignator|"X22 "|VOID*|0xA000008E
+ # Defines the designator of port10 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10ExternalConnectorDesignator|"USB3"|VOID*|0xA000008F
+ # Defines the type of port10 internal connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10InternalConnectorType|0x0|UINT8|0xA0000090
+ # Defines the type of port10 external connector
+ # The valid range is between 0 to 0xFF, and 0x12 here means EfiPortConnectorTypeUsb
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10ExternalConnectorType|0x12|UINT8|0xA0000091
+ # Defines the type of port10
+ # The valid range is between 0 to 0xFF, and 0x10 here means EfiPortTypeUsb
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort10Type|0x10|UINT8|0xA0000092
+
+ # Defines the designator of port11 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11InternalConnectorDesignator|"X23 "|VOID*|0xA0000093
+ # Defines the designator of port11 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11ExternalConnectorDesignator|"USB4"|VOID*|0xA0000094
+ # Defines the type of port11 internal connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11InternalConnectorType|0x0|UINT8|0xA0000095
+ # Defines the type of port11 external connector
+ # The valid range is between 0 to 0xFF, and 0x12 here means EfiPortConnectorTypeUsb
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11ExternalConnectorType|0x12|UINT8|0xA0000096
+ # Defines the type of port11
+ # The valid range is between 0 to 0xFF, and 0x10 here means EfiPortTypeUsb
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort11Type|0x10|UINT8|0xA0000097
+
+ # Defines the designator of port12 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12InternalConnectorDesignator|"X28 "|VOID*|0xA0000098
+ # Defines the designator of port12 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12ExternalConnectorDesignator|"RJ-45 Type"|VOID*|0xA0000099
+ # Defines the type of port12 internal connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12InternalConnectorType|0x0|UINT8|0xA000009A
+ # Defines the type of port12 external connector
+ # The valid range is between 0 to 0xFF, and 0x0B here means EfiPortConnectorTypeRJ45
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12ExternalConnectorType|0x0B|UINT8|0xA000009B
+ # Defines the type of port12
+ # The valid range is between 0 to 0xFF, and 0x1F here means EfiPortTypeNetworkPort
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort12Type|0x1F|UINT8|0xA000009C
+
+ # Defines the designator of port13 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13InternalConnectorDesignator|"J1G1"|VOID*|0xA000009D
+ # Defines the designator of port13 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13ExternalConnectorDesignator|"Floppy"|VOID*|0xA000009E
+ # Defines the type of port13 internal connector
+ # The valid range is between 0 to 0xFF, and 0x16 here means EfiPortConnectorTypeOnboardFloppy
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13InternalConnectorType|0x17|UINT8|0xA000009F
+ # Defines the type of port13 external connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13ExternalConnectorType|0x0|UINT8|0xA00000A0
+ # Defines the type of port13
+ # The valid range is between 0 to 0xFF, and 0xFF here means EfiPortTypeOther
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort13Type|0xFF|UINT8|0xA00000A1
+
+ # Defines the designator of port14 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14InternalConnectorDesignator|"J2H2"|VOID*|0xA00000A2
+ # Defines the designator of port14 external connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14ExternalConnectorDesignator|"IDE"|VOID*|0xA00000A3
+ # Defines the type of port14 internal connector
+ # The valid range is between 0 to 0xFF, and 0x16 here means EfiPortConnectorTypeOnboardIde
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14InternalConnectorType|0x16|UINT8|0xA00000A4
+ # Defines the type of port14 external connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14ExternalConnectorType|0x0|UINT8|0xA00000A5
+ # Defines the type of port14
+ # The valid range is between 0 to 0xFF, and 0xFF here means EfiPortTypeOther
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort14Type|0xFF|UINT8|0xA00000A6
+
+ # Defines the designator of port15 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort15InternalConnectorDesignator|"X29 "|VOID*|0xA00000A7
+ # Defines the designator of port15 external connector
+
+ # Defines the type of port15 internal connector
+ # The valid range is between 0 to 0xFF, and 0x16 here means EfiPortConnectorTypeOnboardIde
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort15InternalConnectorType|0x16|UINT8|0xA00000A9
+ # Defines the type of port15 external connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort15ExternalConnectorType|0x0|UINT8|0xA00000AA
+ # Defines the type of port15
+ # The valid range is between 0 to 0xFF, and 0xFF here means EfiPortTypeOther
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort15Type|0xFF|UINT8|0xA00000AB
+
+ # Defines the designator of port16 internal connector
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort16InternalConnectorDesignator|"X30 "|VOID*|0xA00000AC
+ # Defines the designator of port16 external connector
+
+ # Defines the type of port16 internal connector
+ # The valid range is between 0 to 0xFF, and 0x16 here means EfiPortConnectorTypeOnboardIde
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort16InternalConnectorType|0x16|UINT8|0xA00000AE
+ # Defines the type of port16 external connector
+ # The valid range is between 0 to 0xFF, and 0 here means EfiPortConnectorTypeNone
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort16ExternalConnectorType|0x0|UINT8|0xA00000AF
+ # Defines the type of port16
+ # The valid range is between 0 to 0xFF, and 0xFF here means EfiPortTypeOther
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSPort16Type|0xFF|UINT8|0xA00000B0
+
+ # Defines the number of the slots existent on board
+ # The valid range is between 0 and 14
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlotNumber|5|UINT8|0xA000023F
+ # Defines the designation of system slot1
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Designation|"PCI SLOT1"|VOID*|0xA0000240
+ # Defines the type of system slot1
+ # The valid range is between 0x01 to 0xA5, and 0x06 here means EfiSlotTypePci
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Type|0x6|UINT8|0xA0000241
+ # Defines the data bus width of system slot1
+ # The valid range is between 0x01 to 0x07, and 0x05 here means EfiSlotDataBusWidth32Bit
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1DataBusWidth|0x5|UINT8|0xA0000242
+ # Defines the usage of system slot1
+ # The valid range is between 0x01 to 0x04, and 0x03 here means EfiSlotUsageAvailable
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Usage|0x3|UINT8|0xA0000243
+ # Defines the length of system slot1
+ # The valid range is between 0x01 to 0x04, and 0x04 here means EfiSlotLengthLong
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Length|0x4|UINT8|0xA0000244
+ # Defines the ID of system slot1, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Id|0x01|UINT16|0xA0000245
+ # Defines the characteristics of system slot1 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ # typedef struct {
+ # UINT32 CharacteristicsUnknown :1;
+ # UINT32 Provides50Volts :1;
+ # UINT32 Provides33Volts :1;
+ # UINT32 SharedSlot :1;
+ # UINT32 PcCard16Supported :1;
+ # UINT32 CardBusSupported :1;
+ # UINT32 ZoomVideoSupported :1;
+ # UINT32 ModemRingResumeSupported:1;
+ # UINT32 PmeSignalSupported :1;
+ # UINT32 HotPlugDevicesSupported :1;
+ # UINT32 SmbusSignalSupported :1;
+ # UINT32 Reserved :21;
+ # } EFI_MISC_SLOT_CHARACTERISTICS;
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot1Characteristics|0x504|UINT32|0xA0000246
+
+ # Defines the designation of system slot2
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Designation|"PCI-Express 1"|VOID*|0xA0000247
+
+ # Defines the type of system slot2
+ # The valid range is between 0x01 to 0xA5, and 0x06 here means EfiSlotTypePci
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Type|0xA5|UINT8|0xA0000248
+ # Defines the data bus width of system slot2
+ # The valid range is between 0x01 to 0x07, and 0x05 here means EfiSlotDataBusWidth32Bit
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2DataBusWidth|0x5|UINT8|0xA0000249
+ # Defines the usage of system slot2
+ # The valid range is between 0x01 to 0x04, and 0x03 here means EfiSlotUsageAvailable
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Usage|0x3|UINT8|0xA000024A
+ # Defines the length of system slot2
+ # The valid range is between 0x01 to 0x04, and 0x04 here means EfiSlotLengthLong
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Length|0x4|UINT8|0xA000024B
+ # Defines the ID of system slot2, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Id|0x02|UINT16|0xA000024C
+ # Defines the characteristics of system slot2 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot2Characteristics|0x504|UINT32|0xA000024D
+
+ # Defines the designation of system slot3
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Designation|"PCI-Express 2"|VOID*|0xA000024E
+ # Defines the type of system slot3
+ # The valid range is between 0x01 to 0xA5, and 0x06 here means EfiSlotTypePci
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Type|0xA5|UINT8|0xA000024F
+ # Defines the data bus width of system slot3
+ # The valid range is between 0x01 to 0x07, and 0x05 here means EfiSlotDataBusWidth32Bit
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3DataBusWidth|0x5|UINT8|0xA0000250
+ # Defines the usage of system slot3
+ # The valid range is between 0x01 to 0x04, and 0x03 here means EfiSlotUsageAvailable
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Usage|0x3|UINT8|0xA0000251
+ # Defines the length of system slot3
+ # The valid range is between 0x01 to 0x04, and 0x04 here means EfiSlotLengthLong
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Length|0x4|UINT8|0xA0000252
+ # Defines the ID of system slot3, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Id|0x03|UINT16|0xA0000253
+ # Defines the characteristics of system slot3 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot3Characteristics|0x504|UINT32|0xA000254
+
+ # Defines the designation of system slot4
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Designation|"PCI-Express 3"|VOID*|0xA0000255
+ # Defines the type of system slot4
+ # The valid range is between 0x01 to 0xA5, and 0xA5 here means EfiSlotTypePciExpress
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Type|0xA5|UINT8|0xA0000256
+ # Defines the data bus width of system slot4
+ # The valid range is between 0x01 to 0x07, and 0x05 here means EfiSlotDataBusWidth32Bit
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4DataBusWidth|0x5|UINT8|0xA0000257
+ # Defines the usage of system slot4
+ # The valid range is between 0x01 to 0x04, and 0x03 here means EfiSlotUsageAvailable
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Usage|0x3|UINT8|0xA0000258
+ # Defines the length of system slot4
+ # The valid range is between 0x01 to 0x04, and 0x04 here means EfiSlotLengthLong
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Length|0x4|UINT8|0xA0000259
+ # Defines the ID of system slot4, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Id|0x04|UINT16|0xA0000260
+ # Defines the characteristics of system slot4 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot4Characteristics|0x504|UINT32|0xA0000261
+
+ # Defines the designation of system slot5
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Designation|"Mini PCI-E"|VOID*|0xA0000262
+ # Defines the type of system slot5
+ # The valid range is between 0x01 to 0xA5, and 0xA5 here means EfiSlotTypePciExpress
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Type|0xA5|UINT8|0xA0000263
+ # Defines the data bus width of system slot5
+ # The valid range is between 0x01 to 0x07, and 0x05 here means EfiSlotDataBusWidth32Bit
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5DataBusWidth|0x5|UINT8|0xA0000264
+ # Defines the usage of system slot5
+ # The valid range is between 0x01 to 0x04, and 0x03 here means EfiSlotUsageAvailable
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Usage|0x3|UINT8|0xA0000265
+ # Defines the length of system slot5
+ # The valid range is between 0x01 to 0x04, and 0x04 here means EfiSlotLengthLong
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Length|0x4|UINT8|0xA0000266
+ # Defines the ID of system slot5, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Id|0x05|UINT16|0xA0000267
+ # Defines the characteristics of system slot5 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot5Characteristics|0x504|UINT32|0xA0000268
+
+ # Defines the designation of system slot6
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Designation|"NONE"|VOID*|0xA0000269
+ # Defines the type of system slot6
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Type|0x2|UINT8|0xA000026A
+ # Defines the data bus width of system slot6
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6DataBusWidth|0x2|UINT8|0xA000026B
+ # Defines the usage of system slot6
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Usage|0x2|UINT8|0xA000026C
+ # Defines the length of system slot6
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Length|0x2|UINT8|0xA000026D
+ # Defines the ID of system slot6, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Id|0x0|UINT16|0xA000026E
+ # Defines the characteristics of system slot6 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot6Characteristics|0x0|UINT32|0xA000026F
+
+ # Defines the designation of system slot7
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Designation|"NONE"|VOID*|0xA0000270
+ # Defines the type of system slot7
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Type|0x2|UINT8|0xA0000271
+ # Defines the data bus width of system slot7
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7DataBusWidth|0x2|UINT8|0xA0000272
+ # Defines the usage of system slot7
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Usage|0x2|UINT8|0xA0000273
+ # Defines the length of system slot7
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Length|0x2|UINT8|0xA0000274
+ # Defines the ID of system slot7, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Id|0x0|UINT16|0xA0000275
+ # Defines the characteristics of system slot7 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot7Characteristics|0x0|UINT32|0xA0000276
+
+ # Defines the designation of system slot8
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Designation|"NONE"|VOID*|0xA0000277
+ # Defines the type of system slot8
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Type|0x2|UINT8|0xA0000278
+ # Defines the data bus width of system slot8
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8DataBusWidth|0x2|UINT8|0xA0000279
+ # Defines the usage of system slot8
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Usage|0x2|UINT8|0xA000027A
+ # Defines the length of system slot8
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Length|0x2|UINT8|0xA000027B
+ # Defines the ID of system slot8, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Id|0x0|UINT16|0xA000027C
+ # Defines the characteristics of system slot8 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot8Characteristics|0x0|UINT32|0xA000027D
+
+ # Defines the designation of system slot9
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Designation|"NONE"|VOID*|0xA000027E
+ # Defines the type of system slot9
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Type|0x2|UINT8|0xA000027F
+ # Defines the data bus width of system slot9
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9DataBusWidth|0x2|UINT8|0xA0000280
+ # Defines the usage of system slot9
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Usage|0x2|UINT8|0xA0000281
+ # Defines the length of system slot9
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Length|0x2|UINT8|0xA0000282
+ # Defines the ID of system slot9, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Id|0x0|UINT16|0xA0000283
+ # Defines the characteristics of system slot9 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot9Characteristics|0x0|UINT32|0xA0000284
+
+ # Defines the designation of system slot10
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Designation|"None"|VOID*|0xA0000285
+ # Defines the type of system slot10
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Type|0x2|UINT8|0xA0000286
+ # Defines the data bus width of system slot10
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10DataBusWidth|0x2|UINT8|0xA0000287
+ # Defines the usage of system slot10
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Usage|0x2|UINT8|0xA0000288
+ # Defines the length of system slot10
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Length|0x2|UINT8|0xA0000289
+ # Defines the ID of system slot10, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Id|0x0|UINT16|0xA000028A
+ # Defines the characteristics of system slot10 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot10Characteristics|0x0|UINT32|0xA000028B
+
+ # Defines the designation of system slot11
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Designation|"None"|VOID*|0xA000028C
+ # Defines the type of system slot11
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Type|0x2|UINT8|0xA000028D
+ # Defines the data bus width of system slot11
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11DataBusWidth|0x2|UINT8|0xA000028E
+ # Defines the usage of system slot11
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Usage|0x2|UINT8|0xA000028F
+ # Defines the length of system slot11
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Length|0x2|UINT8|0xA0000290
+ # Defines the ID of system slot11, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Id|0x0|UINT16|0xA00000EE
+ # Defines the characteristics of system slot11 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot11Characteristics|0x0|UINT32|0xA0000291
+
+ # Defines the designation of system slot12
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Designation|"None"|VOID*|0xA0000292
+ # Defines the type of system slot12
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Type|0x2|UINT8|0xA0000293
+ # Defines the data bus width of system slot12
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12DataBusWidth|0x2|UINT8|0xA0000294
+ # Defines the usage of system slot12
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Usage|0x2|UINT8|0xA0000295
+ # Defines the length of system slot12
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Length|0x2|UINT8|0xA0000296
+ # Defines the ID of system slot12, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Id|0x0|UINT16|0xA0000297
+ # Defines the characteristics of system slot12 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot12Characteristics|0x0|UINT32|0xA0000298
+
+ # Defines the designation of system slot13
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Designation|"None"|VOID*|0xA0000299
+ # Defines the type of system slot13
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Type|0x2|UINT8|0xA000029A
+ # Defines the data bus width of system slot13
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13DataBusWidth|0x2|UINT8|0xA000029B
+ # Defines the usage of system slot13
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Usage|0x2|UINT8|0xA000029C
+ # Defines the length of system slot13
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Length|0x2|UINT8|0xA000029D
+ # Defines the ID of system slot13, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Id|0x0|UINT16|0xA000029E
+ # Defines the characteristics of system slot13 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot13Characteristics|0x0|UINT32|0xA000029F
+
+ # Defines the designation of system slot14
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Designation|"None"|VOID*|0xA00002A0
+ # Defines the type of system slot14
+ # The valid range is between 0x01 to 0xA5, and 0x02 here means EfiSlotTypeUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Type|0x2|UINT8|0xA00002A1
+ # Defines the data bus width of system slot14
+ # The valid range is between 0x01 to 0x07, and 0x02 here means EfiSlotDataBusWidthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14DataBusWidth|0x2|UINT8|0xA00002A2
+ # Defines the usage of system slot14
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotUsageUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Usage|0x2|UINT8|0xA00002A3
+ # Defines the length of system slot14
+ # The valid range is between 0x01 to 0x04, and 0x02 here means EfiSlotLengthUnknown
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Length|0x2|UINT8|0xA00002A4
+ # Defines the ID of system slot14, a number of UINT16
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Id|0x0|UINT16|0xA00002A5
+ # Defines the characteristics of system slot14 , a bit mask of EFI_MISC_SLOT_CHARACTERISTICS
+ gQuarkPlatformTokenSpaceGuid.PcdSMBIOSSystemSlot14Characteristics|0x0|UINT32|0xA00002A6
+
+[PcdsDynamic, PcdsDynamicEx]
+
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadBase|0xFFC00400|UINT32|0xA00002A7
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadSize|0x000F0000|UINT32|0xA00002A8
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainBase|0xFFD00400|UINT32|0xA00002A9
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainSize|0x000D0000|UINT32|0xA00002AA
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoveryBase|0xFFEC0400|UINT32|0xA00002AB
+ gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoverySize|0x0003F000|UINT32|0xA00002AC
diff --git a/QuarkPlatformPkg/QuarkPlatformPkg.dsc b/QuarkPlatformPkg/QuarkPlatformPkg.dsc
new file mode 100755
index 0000000..215231b
--- /dev/null
+++ b/QuarkPlatformPkg/QuarkPlatformPkg.dsc
@@ -0,0 +1,736 @@
+## @file
+# Clanton Peak CRB platform with 32-bit DXE for 4MB/8MB flash devices.
+#
+# This package provides Clanton Peak CRB platform specific modules.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = QuarkPlatformPkg
+ PLATFORM_GUID = 1BEDB57A-7904-406e-8486-C89FC7FB39EE
+ VPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E08
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/QuarkPlatform
+ SUPPORTED_ARCHITECTURES = IA32
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+
+ #
+ # Set the global variables
+ #
+ EDK_GLOBAL PLATFORM_PKG = QuarkPlatformPkg
+
+ #
+ # Platform On/Off features are defined here
+ #
+ !include $(PLATFORM_PKG)/QuarkPlatformPkgConfig.dsc
+
+ FLASH_DEFINITION = $(PLATFORM_PKG)/QuarkPlatformPkg.fdf
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this
+# Platform.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+[LibraryClasses]
+ #
+ # Entry point
+ #
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ #
+ # Basic
+ #
+ BaseLib|QuarkSocPkg/Override/MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+!else
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+!endif
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ #
+ # UEFI & PI
+ #
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+ #
+ # Framework
+ #
+ S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+ S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf
+ S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf
+ #
+ # Generic Modules
+ #
+ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+ NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
+ IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
+ UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
+ DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+ SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
+ #
+ # CPU
+ #
+ MtrrLib|QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+ CpuConfigLib|IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf
+ CpuOnlyResetLib|IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf
+ #
+ # Quark North Cluster
+ #
+ SmmLib|QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf
+ SmbusLib|QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf
+ TimerLib|QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.inf
+ ResetSystemLib|QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf
+ IntelQNCLib|QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf
+ QNCAccessLib|QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf
+ RedirectPeiServicesLib|QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServicesLib.inf
+ #
+ # Quark South Cluster
+ #
+ IohLib|QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf
+ SerialPortLib|QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.inf
+ #
+ # Platform
+ #
+ PlatformSecServicesLib|QuarkPlatformPkg/Library/PlatformSecServicesLib/PlatformSecServicesLib.inf
+ UefiBootManagerLib|QuarkPlatformPkg/Bds/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ LogoLib|QuarkPlatformPkg/Library/LogoLib/LogoLib.inf
+ PlatformBootManagerLib|QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+ RecoveryOemHookLib|QuarkPlatformPkg/Library/RecoveryOemHookLib/RecoveryOemHookLib.inf
+ PlatformSecLib|QuarkPlatformPkg/Library/QuarkSecLib/QuarkSecLib.inf
+ SecurityAuthenticationLib|QuarkPlatformPkg/Library/QuarkBootRomLib/QuarkBootRomLib.inf
+ SmmScriptLib|QuarkPlatformPkg/Library/SmmScriptLib/SmmScriptLib.inf
+ CapsuleLib|QuarkPlatformPkg/Library/PlatformCapsuleLib/PlatformCapsuleLib.inf
+ MfhLib|QuarkPlatformPkg/Library/MfhLib/MfhLib.inf
+ PlatformDataLib|QuarkPlatformPkg/Library/PlatformDataLib/PlatformDataLib.inf
+ SmmCpuPlatformHookLib|QuarkPlatformPkg/Library/SmmCpuPlatformHookLib/SmmCpuPlatformHookLib.inf
+ PlatformSecureLib|QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
+ #
+ # Misc
+ #
+ DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
+!else
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+!endif
+ #
+ # Crypto
+ #
+ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+
+[LibraryClasses.IA32.PEIM,LibraryClasses.IA32.PEI_CORE]
+ #
+ # SEC and PEI phase common
+ #
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+ PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+ SwBpeLib|QuarkPlatformPkg/Library/SwBpeLib/SwBpeLib.inf
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+
+ #
+ # Platform SEC and PEI phase common.
+ #
+ PlatformHelperLib|QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf
+ PlatformPcieHelperLib|QuarkPlatformPkg/Library/PlatformPcieHelperLib/PeiPlatformPcieHelperLib.inf
+
+[LibraryClasses.IA32.SEC]
+ #
+ # SEC specific phase
+ #
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+
+[LibraryClasses.IA32]
+ #
+ # DXE phase common
+ #
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+
+ #
+ # Platform DXE phase common.
+ #
+ PlatformHelperLib|QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf
+ PlatformPcieHelperLib|QuarkPlatformPkg/Library/PlatformPcieHelperLib/DxePlatformPcieHelperLib.inf
+
+[LibraryClasses.IA32.DXE_CORE]
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+ PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
+
+[LibraryClasses.IA32.DXE_SMM_DRIVER]
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
+!endif
+!if $(PERFORMANCE_ENABLE) == TRUE
+ PerformanceLib|MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
+!endif
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+
+[LibraryClasses.IA32.SMM_CORE]
+ SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
+ MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
+!if $(PERFORMANCE_ENABLE) == TRUE
+ PerformanceLib|MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
+!endif
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+
+[LibraryClasses.IA32.DXE_RUNTIME_DRIVER]
+ ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+ QNCAccessLib|QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeQNCAccessLib.inf
+
+[LibraryClasses.IA32.UEFI_DRIVER,LibraryClasses.IA32.UEFI_APPLICATION]
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+!if $(PERFORMANCE_ENABLE) == TRUE
+ PerformanceLib|MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.inf
+!endif
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+[PcdsFeatureFlag]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformCsmSupport|FALSE
+ gEfiCpuTokenSpaceGuid.PcdCpuMaxCpuIDValueLimitFlag|FALSE
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE
+ !ifdef SECURE_LD
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock|TRUE
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRmuDmaLock|TRUE
+ !else
+ gQuarkPlatformTokenSpaceGuid.PcdEnableSecureLock|FALSE
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRmuDmaLock|FALSE
+ !endif
+
+ !ifdef SECURE_BOOT
+ gQuarkPlatformTokenSpaceGuid.PcdSupportSecureBoot|TRUE
+ !else
+ gQuarkPlatformTokenSpaceGuid.PcdSupportSecureBoot|FALSE
+ !endif
+
+ !if $(TARGET) == "RELEASE"
+ gQuarkPlatformTokenSpaceGuid.WaitIfResetDueToError|FALSE
+ !else
+ gQuarkPlatformTokenSpaceGuid.WaitIfResetDueToError|TRUE
+ !endif
+
+[PcdsFixedAtBuild]
+
+!ifdef DEBUG_PROPERTY_MASK
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|$(DEBUG_PROPERTY_MASK)
+!endif
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision| 0x00010000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|"EDK II"
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
+ gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0x18
+ gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x00
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1
+ gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|0
+!if $(PERFORMANCE_ENABLE) == TRUE
+ gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x1
+!endif
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|40
+ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize|0x00002000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x1000
+ ## RTC Update Timeout Value, need to increase timeout since also
+ # waiting for RTC to be busy.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdRealTimeClockUpdateTimeout|500000
+
+ gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x4000
+ gEfiCpuTokenSpaceGuid.PcdPlatformType|1
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxCoreFrequency|3800
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxFsbFrequency|1066
+
+ gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0000
+ gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeMask|0xFFFF
+
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion|FALSE
+!ifdef SECURE_BOOT
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x01|UINT32|0x00000001
+ gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04|UINT32|0x00000002
+ gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04|UINT32|0x00000003
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPhysicalPresence|FALSE|BOOLEAN|0x00010001
+!endif
+
+[PcdsPatchableInModule]
+!ifdef DEBUG_PRINT_ERROR_LEVEL
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|$(DEBUG_PRINT_ERROR_LEVEL)
+!endif
+
+[PcdsDynamicExHii.common.DEFAULT]
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|L"BootState"|gQuarkPlatformTokenSpaceGuid|0x0|TRUE
+
+[PcdsDynamicExDefault.common.DEFAULT]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateDataPtr|0x0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|FALSE
+
+ # IntelFrameworkModulePkg.dec
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|0
+
+ # IA32FamilyCpuBasePkg
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfiguration|0xffffffff
+ gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset|FALSE
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags|0x0
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames|0x0
+ gEfiCpuTokenSpaceGuid.PcdPlatformCpuFrequencyLists|0x0
+ gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer|0x0
+ gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress|0x0
+ gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress|0x0
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSetting|0x0
+ gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapability|0x0
+ gEfiCpuTokenSpaceGuid.PcdCpuCallbackSignal|0x0
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+# into firmware volume images. This section is just a list of modules to compile from
+# source into UEFI-compliant binaries.
+# It is the FDF file that contains information on combining binary files into firmware
+# volume images, whose concept is beyond UEFI and is described in PI specification.
+# Binary modules do not need to be listed in this section, as they should be
+# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
+# Logo (Logo.bmp), and etc.
+# There may also be modules listed in this section that are not required in the FDF file,
+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+# generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
+
+[Components.IA32]
+ #
+ # SEC Core
+ #
+ IA32FamilyCpuBasePkg/SecCore/SecCore.inf
+ QuarkPlatformPkg/Cpu/Sec/ResetVector/QuarkResetVector.inf
+
+ #
+ # PEI Core
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+
+ #
+ # PEIM
+ #
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ !ifdef SECURE_BOOT
+ SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf
+ !else
+ MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+ !endif
+ MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+ IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
+ MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+
+ QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
+ QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf {
+ <LibraryClasses>
+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+ }
+ QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+ QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+
+ IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf
+
+ QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
+ <LibraryClasses>
+ NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ }
+
+ #
+ # S3
+ #
+ QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf
+ QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf {
+ <LibraryClasses>
+ !if $(PERFORMANCE_ENABLE) == TRUE
+ PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
+ TimerLib|IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.inf
+ !endif
+ }
+
+ #
+ # Recovery
+ #
+ QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf
+ MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+ QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf
+ MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+ MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+ FatPkg/FatPei/FatPei.inf
+ MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+
+[Components.IA32]
+ #
+ # DXE Core
+ #
+ MdeModulePkg/Core/Dxe/DxeMain.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
+ }
+ QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.inf
+
+ #
+ # Components that produce the architectural protocols
+ #
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
+ <LibraryClasses>
+ NULL|QuarkPlatformPkg/Library/PlatformUnProvisionedHandlerLib/PlatformUnProvisionedHandlerLib.inf
+ !ifdef SECURE_BOOT
+ NULL|QuarkPlatformPkg/Library/SecureBootHelperLib/SecureBootHelperLib.inf
+ NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+ !endif
+
+ }
+ IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf
+ IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf
+ MdeModulePkg/Universal/Metronome/Metronome.inf
+ MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+ QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+ MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+
+ !ifdef SECURE_BOOT
+ SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf
+ SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
+ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+ !else
+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+ QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+ !endif
+ MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+ MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+ MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+ QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+
+ #
+ # Following are the DXE drivers (alphabetical order)
+ #
+ MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+ MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ $(PLATFORM_PKG)/Pci/Dxe/PciHostBridge/PciHostBridge.inf
+ $(PLATFORM_PKG)/Platform/SpiFvbServices/PlatformSpi.inf
+ $(PLATFORM_PKG)/Platform/SpiFvbServices/PlatformSmmSpi.inf
+
+ IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf
+ UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf {
+ <LibraryClasses>
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ }
+
+ #
+ # Platform
+ #
+ QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuApp.inf
+ QuarkPlatformPkg/Bds/BdsDxe/BdsDxe.inf
+
+ QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf
+ QuarkPlatformPkg/Platform/Dxe/Setup/DxePlatform.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ }
+ QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpiRuntime.inf {
+ <LibraryClasses>
+ PciExpressLib|MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf
+ }
+ QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpiSmm.inf
+ QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf
+ IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf
+ IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf
+ MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+ MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+ MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+ MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
+ MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
+ #
+ # ACPI
+ #
+ QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.inf
+ MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+ QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ }
+ MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf
+ QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf
+ QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf
+
+ #
+ # SMM
+ #
+ MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+ MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ }
+ IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ }
+ UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf
+ QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf {
+ <LibraryClasses>
+ IoLib|MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf
+ }
+ QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf
+ QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
+ IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
+
+ #
+ # SMBIOS
+ #
+ MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+ QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDxe.inf
+ QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.inf
+ #
+ # PCI
+ #
+ QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.inf
+ MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/SerialDxe.inf
+
+ #
+ # USB
+ #
+ QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf
+ QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+ MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+ MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
+ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+ #
+ # SDIO
+ #
+ QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf
+
+ #
+ # I2C
+ #
+ QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2CDxe.inf
+
+ #
+ # IDE/SCSI
+ #
+ MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+ MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+
+
+ #
+ # Console
+ #
+ MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+
+ #
+ # Legacy Modules
+ #
+ PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf
+
+ #
+ # File System Modules
+ #
+ FatPkg/EnhancedFatDxe/Fat.inf
+
+ #
+ # Capsule related drivers
+ #
+ IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf
+ IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf
+ QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.inf
+
+ #
+ # Capsule Application
+ #
+ QuarkPlatformPkg/Applications/CapsuleApp/CapsuleApp.inf {
+ <LibraryClasses>
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf
+ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
+ }
+
+ #
+ # TPM DXE Driver.
+ #
+ !ifdef TPM_SUPPORT
+ QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf {
+ <LibraryClasses>
+ TpmCommLib|QuarkPlatformPkg/Override/SecurityPkg/Library/TpmCommLib/TpmCommLib.inf
+ }
+ !endif
+
+ #
+ # Performance Application
+ #
+!if $(PERFORMANCE_ENABLE) == TRUE
+ PerformancePkg/Dp_App/Dp.inf {
+ <LibraryClasses>
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf
+ PerformanceLib|MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.inf
+ }
+!endif
+
+###################################################################################################
+#
+# BuildOptions Section - Define the module specific tool chain flags that should be used as
+# the default flags for a module. These flags are appended to any
+# standard flags that are defined by the build process. They can be
+# applied for any modules or only those modules with the specific
+# module style (EDK or EDKII) specified in [Components] section.
+#
+###################################################################################################
+#BugID31643 - Start
+[BuildOptions.Common.EDKII]
+GCC:*_*_IA32_CC_FLAGS = -include $(WORKSPACE)/QuarkPlatformPkg/Override/MdePkg/Include/Library/DebugLib.h
+#BugID31643 - End
+
diff --git a/QuarkPlatformPkg/QuarkPlatformPkg.fdf b/QuarkPlatformPkg/QuarkPlatformPkg.fdf
new file mode 100755
index 0000000..cb6985b
--- /dev/null
+++ b/QuarkPlatformPkg/QuarkPlatformPkg.fdf
@@ -0,0 +1,1485 @@
+## @file
+# FDF file of Clanton Peak CRB platform with 32-bit DXE
+#
+# This package provides QuarkNcSocId platform specific modules.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+################################################################################
+#
+# FD Section
+# The [FD] Section is made up of the definition statements and a
+# description of what goes into the Flash Device Image. Each FD section
+# defines one flash "device" image. A flash device image may be one of
+# the following: Removable media bootable image (like a boot floppy
+# image,) an Option ROM image (that would be "flashed" into an add-in
+# card,) a System "Flash" image (that would be burned into a system's
+# flash) or an Update ("Capsule") image that will be used to update and
+# existing system flash.
+#
+################################################################################
+[FD.Quark]
+BaseAddress = 0xFFC00000 #The base address of the 4MB FLASH Device.
+Size = 0x400000 #The size in bytes of the 4MB FLASH Device.
+ErasePolarity = 1
+BlockSize = 0x1000
+NumBlocks = 0x400 #The number of blocks for 4MB FLASH Device.
+
+#
+#Flash location override based on actual flash map
+#
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress = 0xFFC00000
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize = 0x400000
+
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageBase = 0xFFF30000
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashNvStorageSize = 0x20000
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecovery2Base = 0x80038400
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecovery2Size = 0x00007000
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashQNCMicrocodeSize = 0x00004000
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainBase = 0xFFD00400
+SET gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainSize = 0x00120000
+
+################################################################################
+#
+# Following are lists of FD Region layout which correspond to the locations of different
+# images within the flash device.
+#
+# Regions must be defined in ascending order and may not overlap.
+#
+# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by
+# the pipe "|" character, followed by the size of the region, also in hex with the leading
+# "0x" characters. Like:
+# Offset|Size
+# PcdOffsetCName|PcdSizeCName
+# RegionType <FV, DATA, or FILE>
+#
+################################################################################
+
+########################################################
+# Quark EDKII Payload Image.
+########################################################
+0x00000400|0x000F0000
+gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadBase|gQuarkPlatformTokenSpaceGuid.PcdFlashFvPayloadSize
+FV = EDKII_PAYLOAD_IMAGE
+
+########################################################
+# Quark EDKII Stage2 Image (Compressed)
+########################################################
+0x00100400|0x00120000
+gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainBase|gQuarkPlatformTokenSpaceGuid.PcdFlashFvMainSize
+FV = EDKII_BOOT_STAGE2_COMPACT
+
+#########################################################
+# Quark EDKII Stage1 Backup Image
+# Quark EDKII Stage1 contains: Stage1 FV + Remote Management Unit Binary
+#########################################################
+0x00280400|0x0003f000
+FV = EDKII_BOOT_STAGE1_IMAGE2
+
+#########################################################
+# Quark EDKII Stage1 Primary Image
+# Quark EDKII Stage1 contains: Stage1 FV + Remote Management Unit Binary
+#########################################################
+0x002C0400|0x0003f000
+FV = EDKII_BOOT_STAGE1_IMAGE1
+
+#########################################################
+# Quark Remote Management Unit Binary
+#########################################################
+0x00300000|0x00008000
+!ifdef QUARK2
+ FILE = QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin
+!else
+ FILE = QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
+!endif
+
+#########################################################
+# Master Flash Header Data.
+#########################################################
+0x00308000|0x00001000
+DATA = {
+ ## This is the MFH_HEADER struct.
+ # MFH_HEADER.QuarkMFHIdentifier.
+ 0x48, 0x46, 0x4D, 0x5F,
+ # MFH_HEADER.Version, MFH_HEADER.RsvdFlags & MFH_HEADER.NextHeaderBlock.
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # MFH_HEADER.FlashItemCount UINT32 LSB - MSB.
+ 0x07, 0x00, 0x00, 0x00,
+ # MFH_HEADER.BootPriorityListCount UINT32 LSB - MSB.
+ 0x03, 0x00, 0x00, 0x00,
+ ## This is the BootPriorityList.
+ # 1st , 2nd , 3rd.
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ ## This is Flash Item [0] desc. 4xUINT32 LSB - MSB.
+ # Type , FlashAddress , LengthBytes, ,Reserved.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is Flash Item [1] desc. 4xUINT32 LSB - MSB.
+ # Type , FlashAddress , LengthBytes, ,Reserved.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is Flash Item [2] desc. 4xUINT32 LSB - MSB.
+ # Type , FlashAddress , LengthBytes, ,Reserved.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is Flash Item [3] desc. 4xUINT32 LSB - MSB.
+ # Type , FlashAddress , LengthBytes, ,Reserved.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is Flash Item [4] desc. 4xUINT32 LSB - MSB.
+ # Type , FlashAddress , LengthBytes, ,Reserved.
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFF, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is Flash Item [5] desc. 4xUINT32 LSB - MSB.
+ # Type , FlashAddress , LengthBytes, ,Reserved.
+ 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is Flash Item [6] desc. 4xUINT32 LSB - MSB.
+ # Type , FlashAddress , LengthBytes, ,Reserved.
+ 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x00
+}
+
+#########################################################
+# PlatformData Binary, default for standalone is none built-in so user selects.
+#########################################################
+#0x00310000|0x00001000
+#FILE = QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.bin
+#FILE = QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin
+#FILE = QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.bin
+#FILE = QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.bin
+#FILE = QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.bin
+
+#############################################################################
+# Quark EDKII NVRAM Area
+# Quark EDKII NVRAM Area contains: Variable + FTW Working + FTW Spare
+#############################################################################
+0x00330000|0x0000E000
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+#NV_VARIABLE_STORE
+DATA = {
+ ## This is the EFI_FIRMWARE_VOLUME_HEADER
+ # ZeroVector []
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # FileSystemGuid: gEfiSystemNvDataFvGuid =
+ # { 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+ 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+ 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+ # FvLength: 0x20000
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ #Signature "_FVH" #Attributes
+ 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
+ #HeaderLength #CheckSum #ExtHeaderOffset #Reserved #Revision
+ 0x48, 0x00, 0x19, 0xF9, 0x00, 0x00, 0x00, 0x02,
+ #Blockmap[0]: 32 Blocks * 0x1000 Bytes / Block
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ #Blockmap[1]: End
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is the VARIABLE_STORE_HEADER
+ !ifdef SECURE_BOOT
+ # Signature: gEfiAuthenticatedVariableGuid = { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }
+ 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
+ 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
+ !else
+ # Signature: gEfiVariableGuid = { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
+ 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41,
+ 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d,
+ !endif
+ #Size: 0x0E000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x0DFB8
+ # This can speed up the Variable Dispatch a bit.
+ 0xB8, 0xDF, 0x00, 0x00,
+ #FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+ 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+0x0033E000|0x00002000
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+#NV_FTW_WORKING
+DATA = {
+ # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEfiSystemNvDataFvGuid =
+ # { 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+ 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+ 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+ # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
+ 0x77, 0x13, 0x9B, 0xD7, 0xFE, 0xFF, 0xFF, 0xFF,
+ # WriteQueueSize: UINT64 #Size: 0x2000 - 0x20 (FTW_WORKING_HEADER) = 0x1FE0
+ 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+0x00340000|0x00010000
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+#NV_FTW_SPARE
+
+#########################################################################################
+# Quark EDKII Recovery Backup Image
+# Quark EDKII Recovery contains: Recovery Stage1 FV + Recovery Stage2 FV + Remote Management Unit Binary
+#########################################################################################
+0x00350400|0x00038000
+FV = EDKII_RECOVERY_STAGE1_IMAGE2
+
+0x00388400|0x00007000
+FV = EDKII_RECOVERY_STAGE2_IMAGE2
+
+#########################################################################################
+# Quark EDKII Recovery Primary Image
+# Quark EDKII Recovery contains: Recovery Stage1 FV + Recovery Stage2 FV + Remote Management Unit Binary
+#########################################################################################
+0x00390400|0x00038000
+FV = EDKII_RECOVERY_STAGE1_IMAGE1
+
+0x003C8400|0x00007000
+FV = EDKII_RECOVERY_STAGE2_IMAGE1
+
+#######################
+# Quark BootRom Image
+#######################
+0x003E0000|0x00020000
+FV = EDKII_BOOTROM_OVERRIDE
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_BOOTROM_OVERRIDE]
+BlockSize = 0x1000
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 18D6D9F4-2EEF-4913-AEE6-BE61C6DA6CC8
+
+################################################################################
+#
+# The INF statements point to EDK component and EDK II module INF files, which will be placed into this FV image.
+# Parsing tools will scan the INF file to determine the type of component or module.
+# The component or module type is used to reference the standard rules
+# defined elsewhere in the FDF file.
+#
+# The format for INF statements is:
+# INF $(PathAndInfFileName)
+#
+################################################################################
+
+ ##
+ # Fixup area for function pointers to NOP ROM routines.
+ # This File must be the first in the FV.
+ ##
+FILE FREEFORM = 5331914A-52A4-472c-B4BD-E223E48C24B0 {
+ SECTION RAW = QuarkPlatformPkg/Binary/SIZE_8KB.bin
+ }
+
+ ##
+ # SEC Phase modules
+ ##
+INF QuarkPlatformPkg/Cpu/Sec/ResetVector/QuarkResetVector.inf
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_RECOVERY_STAGE1_IMAGE1]
+BlockSize = 0x1000
+FvBaseAddress = 0x80000400
+FvForceRebase = TRUE
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 18D6D9F4-2EEF-4913-AEE6-BE61C6DA6CC8
+
+################################################################################
+#
+# The INF statements point to EDK component and EDK II module INF files, which will be placed into this FV image.
+# Parsing tools will scan the INF file to determine the type of component or module.
+# The component or module type is used to reference the standard rules
+# defined elsewhere in the FDF file.
+#
+# The format for INF statements is:
+# INF $(PathAndInfFileName)
+#
+################################################################################
+ ##
+ # PEI Apriori file example, more PEIM module added later.
+ ##
+APRIORI PEI {
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+ # PlatformConfigPei should be immediately after Pcd driver.
+ INF QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+ INF MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+ INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ INF QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+ }
+
+ ##
+ # PEI Phase RAW Data files.
+ ##
+FILE FREEFORM = PCD(gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkMicrocodeFile) {
+!ifdef QUARK2
+ SECTION RAW = QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin
+!else
+ SECTION RAW = QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
+!endif
+ }
+
+ ##
+ # Platform data files see QuarkPlatformPkg/Include/Guid/PlatformDataFileNameGuids.h
+ # for steps to add new platform.
+ ##
+FILE FREEFORM = 0A975562-DF47-4dc3-8AB0-3BA2C3522302 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.bin
+ }
+FILE FREEFORM = 956EDAD3-8440-45cb-89AC-D1930C004E34 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin
+ }
+FILE FREEFORM = 095B3C16-6D67-4c85-B528-339D9FF6222C {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.bin
+ }
+FILE FREEFORM = EE84C5E7-9412-42cc-B755-A915A7B68536 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.bin
+ }
+FILE FREEFORM = E4AD87C8-D20E-40ce-97F5-9756FD0E81D4 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.bin
+ }
+FILE FREEFORM = E27ADA6A-9F8A-4f2e-B09E-4CCDD82C2F54 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-fabe-platform-data.bin
+ }
+FILE FREEFORM = 23B3C10D-46E3-4a78-8AAA-217B6A39EF04 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-gen2-platform-data.bin
+ }
+
+ ##
+ # PEI Phase modules
+ ##
+INF IA32FamilyCpuBasePkg/SecCore/SecCore.inf
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+# PlatformConfigPei should be immediately after Pcd driver.
+INF QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+!ifdef SECURE_BOOT
+ INF RuleOverride = NORELOC SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf
+!else
+ INF RuleOverride = NORELOC MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+!endif
+INF RuleOverride = NORELOC IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
+INF QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf
+INF QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+INF MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_RECOVERY_STAGE2_IMAGE1]
+BlockSize = 0x1000
+FvBaseAddress = 0x80030000
+FvForceRebase = TRUE
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ INF QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+!endif
+FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
+ SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
+ SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF {
+ SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
+ }
+ }
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_RECOVERY_STAGE1_IMAGE2]
+BlockSize = 0x1000
+FvBaseAddress = 0x80000400
+FvForceRebase = TRUE
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 18D6D9F4-2EEF-4913-AEE6-BE61C6DA6CC8
+
+################################################################################
+#
+# The INF statements point to EDK component and EDK II module INF files, which will be placed into this FV image.
+# Parsing tools will scan the INF file to determine the type of component or module.
+# The component or module type is used to reference the standard rules
+# defined elsewhere in the FDF file.
+#
+# The format for INF statements is:
+# INF $(PathAndInfFileName)
+#
+################################################################################
+ ##
+ # PEI Apriori file example, more PEIM module added later.
+ ##
+APRIORI PEI {
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+ # PlatformConfigPei should be immediately after Pcd driver.
+ INF QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+ INF MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+ INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ INF QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+ }
+
+ ##
+ # PEI Phase RAW Data files.
+ ##
+FILE FREEFORM = PCD(gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkMicrocodeFile) {
+!ifdef QUARK2
+ SECTION RAW = QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin
+!else
+ SECTION RAW = QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
+!endif
+ }
+
+ ##
+ # Platform data files see QuarkPlatformPkg/Include/Guid/PlatformDataFileNameGuids.h
+ # for steps to add new platform.
+ ##
+FILE FREEFORM = 0A975562-DF47-4dc3-8AB0-3BA2C3522302 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.bin
+ }
+FILE FREEFORM = 956EDAD3-8440-45cb-89AC-D1930C004E34 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin
+ }
+FILE FREEFORM = 095B3C16-6D67-4c85-B528-339D9FF6222C {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.bin
+ }
+FILE FREEFORM = EE84C5E7-9412-42cc-B755-A915A7B68536 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.bin
+ }
+FILE FREEFORM = E4AD87C8-D20E-40ce-97F5-9756FD0E81D4 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.bin
+ }
+FILE FREEFORM = E27ADA6A-9F8A-4f2e-B09E-4CCDD82C2F54 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-fabe-platform-data.bin
+ }
+FILE FREEFORM = 23B3C10D-46E3-4a78-8AAA-217B6A39EF04 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-gen2-platform-data.bin
+ }
+
+
+ ##
+ # PEI Phase modules
+ ##
+INF IA32FamilyCpuBasePkg/SecCore/SecCore.inf
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+# PlatformConfigPei should be immediately after Pcd driver.
+INF QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+!ifdef SECURE_BOOT
+ INF RuleOverride = NORELOC SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf
+!else
+ INF RuleOverride = NORELOC MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+!endif
+INF RuleOverride = NORELOC IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
+INF QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf
+INF QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+INF MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_RECOVERY_STAGE2_IMAGE2]
+BlockSize = 0x1000
+FvBaseAddress = 0x80030000
+FvForceRebase = TRUE
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ INF QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+!endif
+FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
+ SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
+ SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF {
+ SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
+ }
+ }
+
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.FVRECOVERY_COMPONENTS]
+BlockSize = 0x1000
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+INF QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf
+INF MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+INF QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf
+INF MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+INF MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+INF FatPkg/FatPei/FatPei.inf
+INF MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_BOOT_STAGE1_IMAGE1]
+BlockSize = 0x1000
+FvBaseAddress = 0x80000400
+FvForceRebase = TRUE
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 18D6D9F4-2EEF-4913-AEE6-BE61C6DA6CC8
+
+################################################################################
+#
+# The INF statements point to EDK component and EDK II module INF files, which will be placed into this FV image.
+# Parsing tools will scan the INF file to determine the type of component or module.
+# The component or module type is used to reference the standard rules
+# defined elsewhere in the FDF file.
+#
+# The format for INF statements is:
+# INF $(PathAndInfFileName)
+#
+################################################################################
+ ##
+ # PEI Apriori file example, more PEIM module added later.
+ ##
+APRIORI PEI {
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+ # PlatformConfigPei should be immediately after Pcd driver.
+ INF QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+ INF MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+ INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ INF QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+ }
+
+ ##
+ # PEI Phase RAW Data files.
+ ##
+FILE FREEFORM = PCD(gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkMicrocodeFile) {
+!ifdef QUARK2
+ SECTION RAW = QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin
+!else
+ SECTION RAW = QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
+!endif
+ }
+
+ ##
+ # Platform data files see QuarkPlatformPkg/Include/Guid/PlatformDataFileNameGuids.h
+ # for steps to add new platform.
+ ##
+FILE FREEFORM = 0A975562-DF47-4dc3-8AB0-3BA2C3522302 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.bin
+ }
+FILE FREEFORM = 956EDAD3-8440-45cb-89AC-D1930C004E34 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin
+ }
+FILE FREEFORM = 095B3C16-6D67-4c85-B528-339D9FF6222C {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.bin
+ }
+FILE FREEFORM = EE84C5E7-9412-42cc-B755-A915A7B68536 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.bin
+ }
+FILE FREEFORM = E4AD87C8-D20E-40ce-97F5-9756FD0E81D4 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.bin
+ }
+FILE FREEFORM = E27ADA6A-9F8A-4f2e-B09E-4CCDD82C2F54 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-fabe-platform-data.bin
+ }
+FILE FREEFORM = 23B3C10D-46E3-4a78-8AAA-217B6A39EF04 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-gen2-platform-data.bin
+ }
+
+
+ ##
+ # PEI Phase modules
+ ##
+INF IA32FamilyCpuBasePkg/SecCore/SecCore.inf
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+# PlatformConfigPei should be immediately after Pcd driver.
+INF QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+!ifdef SECURE_BOOT
+ INF RuleOverride = NORELOC SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf
+!else
+ INF RuleOverride = NORELOC MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+!endif
+INF RuleOverride = NORELOC IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf
+INF QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf
+INF QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+INF MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+INF IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+# nothing
+!else
+ INF QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+!endif
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_BOOT_STAGE1_IMAGE2]
+BlockSize = 0x1000
+FvBaseAddress = 0x80000400
+FvForceRebase = TRUE
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 18D6D9F4-2EEF-4913-AEE6-BE61C6DA6CC8
+
+################################################################################
+#
+# The INF statements point to EDK component and EDK II module INF files, which will be placed into this FV image.
+# Parsing tools will scan the INF file to determine the type of component or module.
+# The component or module type is used to reference the standard rules
+# defined elsewhere in the FDF file.
+#
+# The format for INF statements is:
+# INF $(PathAndInfFileName)
+#
+################################################################################
+ ##
+ # PEI Apriori file example, more PEIM module added later.
+ ##
+APRIORI PEI {
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+ # PlatformConfigPei should be immediately after Pcd driver.
+ INF QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+ INF MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+ INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ INF QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+ }
+
+ ##
+ # PEI Phase RAW Data files.
+ ##
+FILE FREEFORM = PCD(gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkMicrocodeFile) {
+!ifdef QUARK2
+ SECTION RAW = QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin
+!else
+ SECTION RAW = QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
+!endif
+ }
+
+ ##
+ # Platform data files see QuarkPlatformPkg/Include/Guid/PlatformDataFileNameGuids.h
+ # for steps to add new platform.
+ ##
+FILE FREEFORM = 0A975562-DF47-4dc3-8AB0-3BA2C3522302 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/svp-platform-data.bin
+ }
+FILE FREEFORM = 956EDAD3-8440-45cb-89AC-D1930C004E34 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/kipsbay-platform-data.bin
+ }
+FILE FREEFORM = 095B3C16-6D67-4c85-B528-339D9FF6222C {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/crosshill-platform-data.bin
+ }
+FILE FREEFORM = EE84C5E7-9412-42cc-B755-A915A7B68536 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/clantonhill-platform-data.bin
+ }
+FILE FREEFORM = E4AD87C8-D20E-40ce-97F5-9756FD0E81D4 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-platform-data.bin
+ }
+FILE FREEFORM = E27ADA6A-9F8A-4f2e-B09E-4CCDD82C2F54 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-fabe-platform-data.bin
+ }
+FILE FREEFORM = 23B3C10D-46E3-4a78-8AAA-217B6A39EF04 {
+ SECTION RAW = QuarkPlatformPkg/Binary/PlatformData/galileo-gen2-platform-data.bin
+ }
+
+
+ ##
+ # PEI Phase modules
+ ##
+INF IA32FamilyCpuBasePkg/SecCore/SecCore.inf
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+# PlatformConfigPei should be immediately after Pcd driver.
+INF QuarkPlatformPkg/Platform/Pei/PlatformConfig/PlatformConfigPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+!ifdef SECURE_BOOT
+ INF RuleOverride = NORELOC SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf
+!else
+ INF RuleOverride = NORELOC MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+!endif
+INF RuleOverride = NORELOC IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
+INF RuleOverride = NORELOC MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
+INF RuleOverride = NORELOC QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf
+INF QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.inf
+INF QuarkPlatformPkg/Platform/Pei/PlatformInfo/PlatformInfo.inf
+INF MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+INF IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+# nothing
+!else
+ INF QuarkPlatformPkg/Override/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+!endif
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_BOOT_STAGE2]
+BlockSize = 0x1000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 30D9ED01-38D2-418a-90D5-C561750BF80F
+
+ ##
+ # DXE Phase modules
+ ##
+INF MdeModulePkg/Core/Dxe/DxeMain.inf
+INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+#
+# Early SoC / Platform modules. I2C must be loaded before platform init.
+#
+INF QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2CDxe.inf
+INF QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.inf
+
+#
+# EDK Core modules.
+#
+
+INF IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf
+INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
+INF IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf
+
+INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+INF IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf
+INF IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf
+INF MdeModulePkg/Universal/Metronome/Metronome.inf
+INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+!ifdef SECURE_BOOT
+INF SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf
+INF SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
+INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!else
+INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+!endif
+INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+INF QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+INF IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf
+INF IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf
+INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+#
+# Platform
+#
+INF QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuApp.inf
+INF QuarkPlatformPkg/Bds/BdsDxe/BdsDxe.inf
+
+INF QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.inf
+INF QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSpi.inf
+INF QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.inf
+INF QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf
+INF QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf
+INF QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf
+INF QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpiRuntime.inf
+INF QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpiSmm.inf
+INF QuarkPlatformPkg/Platform/Dxe/Setup/DxePlatform.inf
+
+#
+# ACPI
+#
+INF QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.inf
+INF MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+INF QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+INF IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf
+INF QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf
+INF RuleOverride = ACPITABLE QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf
+
+#
+# SMM
+#
+INF MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+INF MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+INF IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+INF UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
+INF QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf
+INF QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.inf
+INF QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf
+INF QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf
+INF QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
+INF IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
+
+#
+# SMBIOS
+#
+INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+INF QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDxe.inf
+INF QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.inf
+#
+# PCI
+#
+INF QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.inf
+INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+INF QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf
+INF QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/SerialDxe.inf
+#
+# USB
+#
+INF QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+INF QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+#
+# SDIO
+#
+INF QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf
+INF QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf
+
+#
+# IDE
+#
+INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+
+#
+# Console
+#
+INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+
+INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+
+#
+# TPM DXE Driver.
+#
+!ifdef TPM_SUPPORT
+INF QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
+!endif
+
+#
+# Shell and Applications
+#
+FILE APPLICATION = c57ad6b7-0515-40a8-9d21-551652854e37 {
+ SECTION PE32 = EdkShellBinPkg/FullShell/Ia32/Shell_Full.efi
+}
+#!endif
+
+#
+# Legacy Modules
+#
+INF PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf
+
+#
+# File System Modules
+#
+INF FatPkg/EnhancedFatDxe/Fat.inf
+INF QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.inf
+
+################################################################################
+#
+# FILE statements are provided so that a platform integrator can include
+# complete EFI FFS files, as well as a method for constructing FFS files
+# using curly "{}" brace scoping. The following three FILEs are
+# for binary shell, binary fat and logo module.
+#
+################################################################################
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+
+[FV.EDKII_BOOT_STAGE2_RECOVERY]
+BlockSize = 0x1000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 30D9ED01-38D2-418a-90D5-C561750BF80F
+
+ ##
+ # DXE Phase modules
+ ##
+INF MdeModulePkg/Core/Dxe/DxeMain.inf
+
+INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+INF IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf
+INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
+INF IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf
+
+INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+INF IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf
+INF IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf
+INF MdeModulePkg/Universal/Metronome/Metronome.inf
+INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+
+#
+# For recovery use Emulated variable store with need of NV storage.
+#
+INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+
+INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+INF QuarkPlatformPkg/Override/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+INF IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf
+INF IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf
+INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+#
+# Platform
+#
+INF QuarkPlatformPkg/Bds/BootManagerMenuApp/BootManagerMenuApp.inf
+INF QuarkPlatformPkg/Bds/BdsDxe/BdsDxe.inf
+
+INF QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.inf
+INF QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSpi.inf
+INF QuarkPlatformPkg/Platform/SpiFvbServices/PlatformSmmSpi.inf
+INF QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf
+INF QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf
+INF QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf
+INF QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpiRuntime.inf
+INF QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpiSmm.inf
+INF QuarkPlatformPkg/Platform/Dxe/PlatformInit/PlatformInitDxe.inf
+INF QuarkPlatformPkg/Platform/Dxe/Setup/DxePlatform.inf
+
+#
+# ACPI
+#
+INF QuarkPlatformPkg/Platform/Dxe/SaveMemoryConfig/SaveMemoryConfig.inf
+INF MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+INF QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+INF IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf
+INF QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf
+INF RuleOverride = ACPITABLE QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf
+
+#
+# SMM
+#
+INF MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+INF MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+INF IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+INF UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
+INF QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf
+INF QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.inf
+INF QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf
+INF QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf
+INF QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
+INF IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
+
+#
+# SMBIOS
+#
+INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+INF QuarkPlatformPkg/Platform/Dxe/SmbiosMiscDxe/SmbiosMiscDxe.inf
+INF QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.inf
+#
+# PCI
+#
+INF QuarkPlatformPkg/Pci/Dxe/PciPlatform/PciPlatform.inf
+INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+INF QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf
+INF QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/SerialDxe.inf
+#
+# USB
+#
+INF QuarkPlatformPkg/Override/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+INF QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf
+INF QuarkPlatformPkg/Override/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+#
+# SDIO
+#
+INF QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf
+INF QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf
+
+#
+# IDE
+#
+INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+
+#
+# Console
+#
+INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+
+INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+
+#
+# TPM DXE Driver.
+#
+!ifdef TPM_SUPPORT
+INF QuarkPlatformPkg/Override/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
+!endif
+
+#
+# Shell and Applications
+#
+FILE APPLICATION = c57ad6b7-0515-40a8-9d21-551652854e37 {
+ SECTION PE32 = EdkShellBinPkg/FullShell/Ia32/Shell_Full.efi
+}
+#!endif
+
+#
+# Legacy Modules
+#
+INF PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf
+
+#
+# File System Modules
+#
+INF FatPkg/EnhancedFatDxe/Fat.inf
+INF QuarkPlatformPkg/Platform/DxeSmm/SMIFlashDxe/SMIFlashDxe.inf
+
+################################################################################
+#
+# FILE statements are provided so that a platform integrator can include
+# complete EFI FFS files, as well as a method for constructing FFS files
+# using curly "{}" brace scoping. The following three FILEs are
+# for binary shell, binary fat and logo module.
+#
+################################################################################
+
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_BOOT_STAGE2_COMPACT]
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+ SECTION GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
+ SECTION FV_IMAGE = EDKII_BOOT_STAGE2
+ }
+ }
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.EDKII_PAYLOAD_IMAGE]
+BlockSize = 0x1000
+FvBaseAddress = 0xFFC00000
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+FILE APPLICATION = PCD(gQuarkPlatformTokenSpaceGuid.PcdPayloadFile) {
+ SECTION PE32 = QuarkPlatformPkg/Binary/Payload/PayloadSample.efi
+ }
+
+################################################################################
+#
+# Rules are use with the [FV] section's module INF type to define
+# how an FFS file is created for a given INF file. The following Rule are the default
+# rules for the different module type. User can add the customized rules to define the
+# content of the FFS file.
+#
+################################################################################
+[Rule.Common.SEC]
+ FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
+ TE TE Align = 8 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ RAW BIN Align = 16 |.com
+ }
+
+[Rule.Common.PEI_CORE]
+ FILE PEI_CORE = $(NAMED_GUID) {
+ TE TE $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEIM.NORELOC]
+ FILE PEIM = $(NAMED_GUID) RELOCS_STRIPPED {
+ PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ TE TE $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEIM]
+ FILE PEIM = $(NAMED_GUID) {
+ PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ TE TE $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_CORE]
+ FILE DXE_CORE = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_SMM_DRIVER]
+ FILE SMM = $(NAMED_GUID) {
+ SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.SMM_CORE]
+ FILE SMM_CORE = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION.UI]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="Enter Setup"
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+ FILE FREEFORM = $(NAMED_GUID) {
+ RAW ACPI |.acpi
+ RAW ASL |.aml
+ }
+
diff --git a/QuarkPlatformPkg/QuarkPlatformPkgConfig.dsc b/QuarkPlatformPkg/QuarkPlatformPkgConfig.dsc
new file mode 100755
index 0000000..9a26236
--- /dev/null
+++ b/QuarkPlatformPkg/QuarkPlatformPkgConfig.dsc
@@ -0,0 +1,39 @@
+#/** @file
+# platform configuration file.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#**/
+
+#
+# TRUE is ENABLE. FALSE is DISABLE.
+#
+DEFINE PERFORMANCE_ENABLE = FALSE
+DEFINE CFG_SOURCE_DEBUG = FALSE
+
diff --git a/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.c b/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.c
new file mode 100755
index 0000000..7b9f8a1
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.c
@@ -0,0 +1,464 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ CapsuleCreate.c
+
+Abstract:
+
+ Definitions for the CapsuleCreate utility.
+
+--*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Common/UefiBaseTypes.h>
+
+#include "CommonLib.h"
+#include "ParseInf.h"
+#include "EfiUtilityMsgs.h"
+
+#define UTILITY_NAME "CapsuleCreate"
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 3
+
+#define BEGIN_STRING "BEGIN"
+#define END_STRING "END"
+#define FILE_NAME_STRING "FILE_NAME="
+#define START_ADDRESS_STRING "START_ADDRESS="
+
+#define MAX_CAPSULE_PAYLOAD_SIZE 0xA00000
+#define MAX_IMAGES_PER_CAPSULE 20
+
+//
+// 4KB SPI block size (sector erase size)
+//
+#define SPI_BLOCK_SIZE 0x1000
+#define PAD_BYTE 0x00
+
+CHAR8 *gCapsuleGuid;
+
+#pragma pack(1)
+typedef struct {
+ EFI_GUID CapsuleGuid;
+ UINT32 HeaderSize;
+ UINT32 Flags;
+ UINT32 CapsuleImageSize;
+ UINT8 Reserved[52];
+} CAPSULE_HEADER;
+
+typedef struct {
+ UINT32 TargetAddr;
+ UINT32 Size;
+ UINT32 SourceOffset;
+ UINT32 Reserved;
+} UPDATE_HINT;
+#pragma pack()
+
+
+STATIC
+VOID
+Version (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print out version information for this utility.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ fprintf (stdout, "%s Version %d.%d \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
+}
+
+STATIC
+VOID
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print Error / Help message.
+
+Arguments:
+
+ VOID
+
+Returns:
+
+ None
+
+--*/
+{
+ //
+ // Summary usage
+ //
+ fprintf (stdout, "\nUsage: %s InputConfigFileName OutputCapsuleFileName\n\n", UTILITY_NAME);
+
+ //
+ // Copyright declaration
+ //
+ fprintf (stdout, "Copyright (c) 2011, Intel Corporation. All rights reserved.\n\n");
+}
+
+int
+main (
+ int argc,
+ CHAR8 *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ EFI_STATUS Status;
+ CHAR8 *ImageBuffer;
+ CHAR8 *InputConfigFileName;
+ CHAR8 *InputCapsuleModulesDir;
+ CHAR8 *OutputCapsuleFileName;
+ CHAR8 *CapsuleFlagsString;
+ CHAR8 *ValueString;
+ FILE *InputConfigFile;
+ FILE *OutputCapsuleFile;
+ FILE *InputCapsuleImage;
+ CHAR8 LineString[_MAX_PATH];
+ UINTN LineLen;
+ CHAR8 FileName[_MAX_PATH];
+ CAPSULE_HEADER CapsuleHeader;
+ UPDATE_HINT HintData[MAX_IMAGES_PER_CAPSULE];
+ UINT8 ImageNumber;
+ UINT64 Value64;
+ UINT32 InputCapsuleImageSize;
+ UINT32 InputCapsuleImagePadSize;
+ UINT32 TotalPayloadImageSize;
+ UINT32 ReadFileSize;
+ UINT32 SourceOffset;
+ UINT64 CapsuleFlags;
+
+ SetUtilityName (UTILITY_NAME);
+
+ if (argc == 1) {
+ Error (NULL, 0, 1001, "Missing options", "no options input");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ //
+ // Parse command line
+ //
+ argc --;
+ argv ++;
+
+ if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
+ Version ();
+ Usage ();
+ return STATUS_SUCCESS;
+ }
+
+ if (stricmp (argv[0], "--version") == 0) {
+ Version ();
+ return STATUS_SUCCESS;
+ }
+
+ InputConfigFileName = NULL;
+ InputCapsuleModulesDir = NULL;
+ OutputCapsuleFileName = NULL;
+ CapsuleFlagsString = NULL;
+ if (argc > 0) {
+ InputConfigFileName = argv[0];
+ argv ++;
+ argc --;
+ }
+
+ if (argc > 0) {
+ InputCapsuleModulesDir = argv[0];
+ argv ++;
+ argc --;
+ }
+
+ if (argc > 0) {
+ OutputCapsuleFileName = argv[0];
+ argv ++;
+ argc --;
+ }
+
+ if (argc > 0) {
+ CapsuleFlagsString = argv[0];
+ argv ++;
+ argc --;
+ }
+
+ VerboseMsg ("%s tool start.", UTILITY_NAME);
+
+ InputConfigFile = NULL;
+ OutputCapsuleFile = NULL;
+ InputCapsuleImage = NULL;
+ ImageBuffer = NULL;
+
+ if (CapsuleFlagsString == NULL) {
+ Error (NULL, 0, 1003, "Missing option", "CapsuleFlags parameter");
+ goto Finish;
+ }
+
+ Status = AsciiStringToUint64 (CapsuleFlagsString, TRUE, &CapsuleFlags);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 1002, "Invalid CapsuleFlags parameter", "%s", CapsuleFlagsString);
+ goto Finish;
+ }
+
+ //
+ // Open input config file
+ //
+ FileName[0] = '\0';
+ if (InputConfigFileName == NULL) {
+ Error (NULL, 0, 1003, "Missing option", "Input Config file");
+ goto Finish;
+ }
+ strcpy (FileName, InputConfigFileName);
+ InputConfigFile = fopen (FileName, "r");
+ if (InputConfigFile == NULL) {
+ Error (NULL, 0, 1004, "Error opening file", FileName);
+ goto Finish;
+ }
+
+ //
+ // Open output capsule file
+ //
+ FileName[0] = '\0';
+ if (OutputCapsuleFileName == NULL) {
+ Error (NULL, 0, 1005, "Missing option", "Output Capsule file");
+ goto Finish;
+ }
+ strcpy (FileName, OutputCapsuleFileName);
+ OutputCapsuleFile = fopen (FileName, "wb");
+ if (OutputCapsuleFile == NULL) {
+ Error (NULL, 0, 1006, "Error opening file", FileName);
+ goto Finish;
+ }
+
+ //
+ // Allocate a buffer to read the input images into
+ //
+ ImageBuffer = (CHAR8*) malloc (sizeof(CHAR8)*MAX_CAPSULE_PAYLOAD_SIZE);
+ if (ImageBuffer == NULL) {
+ goto Finish;
+ }
+
+ //
+ // Initialise data
+ //
+ SourceOffset = (sizeof (CapsuleHeader)) + ((sizeof (UPDATE_HINT)) * MAX_IMAGES_PER_CAPSULE);
+ ImageNumber = 0;
+ TotalPayloadImageSize = 0;
+ memset (&HintData, 0xFF, sizeof (HintData));
+ ZeroMem (ImageBuffer, sizeof(CHAR8)*MAX_CAPSULE_PAYLOAD_SIZE);
+
+ //
+ // Fill in the Hint Data
+ //
+ while(!feof(InputConfigFile) && ImageNumber < (MAX_IMAGES_PER_CAPSULE-1)) {
+ ReadLineInStream (InputConfigFile, LineString);
+ if (strstr (LineString, BEGIN_STRING) != NULL) {
+ do {
+ ReadLineInStream (InputConfigFile, LineString);
+ //
+ // Remove line break
+ //
+ LineLen = strlen (LineString);
+ if (LineLen != 0) {
+ if (LineString[LineLen - 1] == '\n') {
+ if (LineString[LineLen - 2] == '\r') {
+ LineString[LineLen - 2] = '\0';
+ }
+ LineString[LineLen - 1] = '\0';
+ }
+ }
+
+ if ((ValueString = strstr (LineString, FILE_NAME_STRING)) != NULL) {
+ //
+ // Get the input capsule image file name
+ //
+ ValueString = ValueString + strlen (FILE_NAME_STRING);
+ FileName[0] = '\0';
+ if (InputCapsuleModulesDir != NULL) {
+ strcpy (FileName, InputCapsuleModulesDir);
+ if (FileName[strlen (FileName) - 1] != '/') {
+ strcat (FileName, "/");
+ }
+ }
+ strcat (FileName, ValueString);
+
+ //
+ // Open the input capsule image file
+ //
+ InputCapsuleImage = fopen (FileName, "rb");
+ if (InputCapsuleImage == NULL) {
+ Error (NULL, 0, 1007, "Error opening file", FileName);
+ goto Finish;
+ }
+
+ //
+ // Get size of input image
+ //
+ fseek(InputCapsuleImage, 0, SEEK_END);
+ InputCapsuleImageSize = (UINT32) ftell(InputCapsuleImage);
+ rewind(InputCapsuleImage);
+
+ //
+ // Calculate any padding required to align image to SPI_BLOCK_SIZE
+ //
+ if ((InputCapsuleImageSize & (SPI_BLOCK_SIZE - 1)) != 0) {
+ InputCapsuleImagePadSize = SPI_BLOCK_SIZE - (InputCapsuleImageSize & (SPI_BLOCK_SIZE - 1));
+ } else {
+ InputCapsuleImagePadSize = 0;
+ }
+
+ //
+ // Read input image into buffer
+ //
+ if ((TotalPayloadImageSize + InputCapsuleImageSize) >= MAX_CAPSULE_PAYLOAD_SIZE) {
+ Error (NULL, 0, 1008, "Capsule Payload size is", " > MAX_CAPSULE_PAYLOAD_SIZE");
+ goto Finish;
+ }
+ ReadFileSize = (UINT32) fread((CHAR8 *)(ImageBuffer+TotalPayloadImageSize), 1, InputCapsuleImageSize, InputCapsuleImage);
+ if (ReadFileSize != InputCapsuleImageSize) {
+ Error (NULL, 0, 1009, "Error reading input file", ".");
+ goto Finish;
+ }
+
+ HintData[ImageNumber].Size = (UINT32) (InputCapsuleImageSize + InputCapsuleImagePadSize);
+ TotalPayloadImageSize += (InputCapsuleImageSize + InputCapsuleImagePadSize);
+ } else if ((ValueString = strstr (LineString, START_ADDRESS_STRING)) != NULL) {
+ //
+ // Get the Start address value
+ //
+ ValueString = ValueString + strlen (START_ADDRESS_STRING);
+ Status = AsciiStringToUint64 (ValueString, TRUE, &Value64);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 1010, "Invalid parameter", "%s%s", START_ADDRESS_STRING, ValueString);
+ goto Finish;
+ }
+ HintData[ImageNumber].TargetAddr = (UINT32) Value64;
+ }
+ } while ((strstr (LineString, END_STRING) == NULL) && !feof(InputConfigFile));
+
+ if (strstr (LineString, END_STRING) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ Error (NULL, 0, 1011, "Invalid parameter", "no %s match %s", END_STRING, BEGIN_STRING);
+ goto Finish;
+ }
+
+ if ((HintData[ImageNumber].Size == 0) || ((HintData[ImageNumber].Size & 0xFFF) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ Error (NULL, 0, 1012, "Invalid parameter", "%s is missing or is not block (4KB) aligned", FILE_NAME_STRING);
+ goto Finish;
+ }
+ if (HintData[ImageNumber].TargetAddr == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ Error (NULL, 0, 1013, "Invalid parameter", "%s is missing", START_ADDRESS_STRING);
+ goto Finish;
+ }
+ HintData[ImageNumber].SourceOffset = SourceOffset;
+ SourceOffset += HintData[ImageNumber].Size;
+ ImageNumber++;
+ }
+ }
+ ZeroMem (&HintData[ImageNumber], sizeof (UPDATE_HINT));
+ ImageNumber++;
+
+ //
+ // Fill in the Capsule Header
+ //
+ gCapsuleGuid = "D400D1E4-A314-442B-89ED-A92E4C8197CB";
+ ZeroMem (&CapsuleHeader, sizeof (CapsuleHeader));
+ Status = StringToGuid (gCapsuleGuid, &CapsuleHeader.CapsuleGuid);
+ CapsuleHeader.HeaderSize = (UINT32) sizeof (CapsuleHeader);
+ CapsuleHeader.Flags = (UINT32)CapsuleFlags;
+ CapsuleHeader.CapsuleImageSize = (UINT32) SourceOffset;
+
+ //
+ // Write to output file
+ //
+ fwrite (&CapsuleHeader, 1, sizeof (CapsuleHeader), OutputCapsuleFile);
+ fwrite (&HintData, 1, (sizeof (UPDATE_HINT)) * MAX_IMAGES_PER_CAPSULE, OutputCapsuleFile);
+ fwrite (ImageBuffer, 1, TotalPayloadImageSize, OutputCapsuleFile);
+
+Finish:
+ if (InputConfigFile != NULL) {
+ fclose (InputConfigFile);
+ }
+
+ if (OutputCapsuleFile != NULL) {
+ fclose (OutputCapsuleFile);
+ }
+
+ if (InputCapsuleImage != NULL) {
+ fclose (InputCapsuleImage);
+ }
+
+ if (ImageBuffer != NULL) {
+ free (ImageBuffer);
+ }
+
+ //
+ // If any errors were reported via the standard error reporting
+ // routines, then the status has been saved. Get the value and
+ // return it to the caller.
+ //
+ VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
+
+ return GetUtilityStatus ();
+}
diff --git a/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.exe b/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.exe
new file mode 100755
index 0000000..7000fec
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.exe
Binary files differ
diff --git a/QuarkPlatformPkg/Tools/CapsuleCreate/GNUmakefile b/QuarkPlatformPkg/Tools/CapsuleCreate/GNUmakefile
new file mode 100755
index 0000000..485e565
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/CapsuleCreate/GNUmakefile
@@ -0,0 +1,55 @@
+## @file
+# Makefile for 'CapsuleCreate' module build.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ARCH = IA32
+MAKEROOT = ../../../BaseTools/Source/C
+LIBS = -lCommon
+
+include $(MAKEROOT)/Makefiles/header.makefile
+
+APPNAME = CapsuleCreate
+
+OBJECTS = CapsuleCreate.o
+
+
+APPLICATION = $(APPNAME)
+
+.PHONY:all
+all: $(APPLICATION)
+
+$(APPLICATION): $(OBJECTS)
+ $(LINKER) -o $(APPLICATION) $(LFLAGS) $(OBJECTS) -L$(MAKEROOT)/libs $(LIBS)
+
+$(OBJECTS): $(MAKEROOT)/Include/Common/BuildVersion.h
+
+#include $(MAKEROOT)/Makefiles/footer.makefile
+
+
+
diff --git a/QuarkPlatformPkg/Tools/CapsuleCreate/Makefile b/QuarkPlatformPkg/Tools/CapsuleCreate/Makefile
new file mode 100644
index 0000000..9f9eb2d
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/CapsuleCreate/Makefile
@@ -0,0 +1,42 @@
+## @file
+# Windows makefile for 'CapsuleCreate' module build.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+!INCLUDE ..\Makefiles\ms.common
+
+APPNAME = CapsuleCreate
+
+LIBS = $(LIB_PATH)\Common.lib
+
+OBJECTS = CapsuleCreate.obj
+
+!INCLUDE ..\Makefiles\ms.app
diff --git a/QuarkPlatformPkg/Tools/CapsuleCreate/QuarkPlatformPkgCapsuleComponents.inf b/QuarkPlatformPkg/Tools/CapsuleCreate/QuarkPlatformPkgCapsuleComponents.inf
new file mode 100755
index 0000000..a5cd3dc
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/CapsuleCreate/QuarkPlatformPkgCapsuleComponents.inf
@@ -0,0 +1,98 @@
+## @file
+# Capsule Components description files.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+#-----------------------------------------------------------
+# Capsule Components.inf
+#
+#
+# Description:
+#
+# This file contains all the information including the list
+# of components included to produce required capsule.
+#
+#-----------------------------------------------------------
+
+#
+# Any component can be added
+# or removed by inserting BEGIN and END block or deleting BEGIN and END Block
+# 1) A maximum of MAX_IMAGES_PER_CAPSULE is allowed (currently 20)
+# 2) The maximum capsule size is MAX_CAPSULE_PAYLOAD_SIZE (currently 10MB)
+#
+
+[Components]
+
+#BEGIN
+# FILE_NAME=CLANTONPEAKCRB.fd
+# START_ADDRESS=0xFFC00000
+#END
+
+#BEGIN
+# FILE_NAME=EDKII_BOOTROM_OVERRIDE.Fv
+# START_ADDRESS=0xFFFE0000
+#END
+
+#BEGIN
+# FILE_NAME=EDKII_RECOVERY_IMAGE1.Fv.signed
+# START_ADDRESS=0xFFF90000
+#END
+
+#BEGIN
+# FILE_NAME=EDKII_RECOVERY_IMAGE2.Fv.signed
+# START_ADDRESS=0xFFF50000
+#END
+
+BEGIN
+ FILE_NAME=FlashModules/EDKII_NVRAM.bin
+ START_ADDRESS=0xFFF30000
+END
+
+BEGIN
+ FILE_NAME=FlashModules/RMU.bin
+ START_ADDRESS=0xFFF00000
+END
+
+BEGIN
+ FILE_NAME=EDKII_BOOT_STAGE1_IMAGE1.Fv.signed
+ START_ADDRESS=0xFFEC0000
+END
+
+BEGIN
+ FILE_NAME=EDKII_BOOT_STAGE1_IMAGE2.Fv.signed
+ START_ADDRESS=0xFFE80000
+END
+
+BEGIN
+ FILE_NAME=EDKII_BOOT_STAGE2_COMPACT.Fv.signed
+ START_ADDRESS=0xFFD00000
+END
diff --git a/QuarkPlatformPkg/Tools/QuarkSpiFixup/QuarkSpiFixup.py b/QuarkPlatformPkg/Tools/QuarkSpiFixup/QuarkSpiFixup.py
new file mode 100755
index 0000000..33db8c1
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/QuarkSpiFixup/QuarkSpiFixup.py
@@ -0,0 +1,432 @@
+#!/usr/bin/env python
+## @file
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+import glob
+import os
+import subprocess
+import sys
+import struct
+import re
+import shutil
+
+#
+# Input arguments:
+# platform name, build type
+#
+platformName = sys.argv[1]
+buildType = sys.argv[2]
+buildTools = sys.argv[3]
+
+# Build Name Options
+buildOptionDebug = "DEBUG"
+buildOptionRelease = "RELEASE"
+
+# BootROM definitions
+QuarkRomBaseAddress = 4294836224
+
+#NVRAM definitions
+nvramLocation = 0x330000
+nvramSize = 0x20000
+
+# Root Directory
+curr_dir = os.getcwd()
+
+buildType = buildType.upper()
+
+#check if valid build option supplied
+if re.match(buildOptionDebug, buildType) or re.match(buildOptionRelease, buildType):
+ capsule_app_file = curr_dir+"/"+platformName+"Pkg"+"/Applications/CapsuleApp.efi"
+ build_dir = curr_dir+"/Build/" + platformName + "/"+ buildType + "_" + buildTools + "/FV"
+ output_dir = curr_dir+"/Build/" + platformName + "/"+ buildType +"_" + buildTools + "/FV/FlashModules"
+ if not os.path.exists(output_dir):
+ os.makedirs(output_dir)
+
+ #copy RMU binaries to the output_dir
+ rmu_binary_file = curr_dir+"/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin"
+ shutil.copyfileobj(open(rmu_binary_file,'rb'), open(output_dir+"/RMU.bin",'wb'))
+ rmu_binary_file = curr_dir+"/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin"
+ shutil.copyfileobj(open(rmu_binary_file,'rb'), open(output_dir+"/RMU2.bin",'wb'))
+
+ # Check build directory really exists
+ if os.path.exists(build_dir):
+ os.chdir(build_dir)
+ currdir = os.getcwd()
+ listing = sorted(os.listdir(currdir))
+
+ # Stage1 images use Index 0x00 - 0x0F
+ # Recovery images use Index 0x10 - 0x1F
+ stage1_index = 0
+ recovery_index = 16
+
+ #check files for fvs that are stage1 or recovery only
+ for infile in listing:
+ if infile.endswith(".Fv"):
+ if re.search("EDKII_BOOT_STAGE1_", infile) or re.search("EDKII_RECOVERY_STAGE1_", infile):
+
+ # open current file, then update the offset and index
+ currentBin = open(infile, 'rb+')
+ currentBinLength = len(currentBin.read())
+
+ #
+ # Search for Spi Entry Offset:
+ #
+ currentBin.seek(0, os.SEEK_SET)
+ currCount = 0
+ for currCount in range(currentBinLength):
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'S':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'P':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'I':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == ' ':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'E':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'n':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 't':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'r':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'y':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == ' ':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'P':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'o':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'i':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'n':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 't':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == ' ':
+ break
+ mySpiLocation = currentBin.tell()
+ currentBin.seek(0, os.SEEK_SET)
+ SpiOffSet = mySpiLocation
+
+ # Add spi offset to first 4 bytes of images
+ currentBin.write(struct.pack('I', SpiOffSet))
+
+ # Add index as unique identifier for the image to byte 5 offset
+ if re.search("EDKII_BOOT_STAGE1_", infile):
+ currentBin.write(struct.pack('I', stage1_index))
+
+ # Print out Software Module fixup information
+ print '%(File_Name)s (Entry point:%(Entry_Offset)s Index:%(Module_Index)02d) \n' %{"File_Name": infile, "Entry_Offset": hex(mySpiLocation), "Module_Index": stage1_index}
+
+ stage1_index += 1
+
+ else:
+ currentBin.write(struct.pack('I', recovery_index))
+
+ # Print out Software Module fixup information
+ print '%(File_Name)s (Entry point:%(Entry_Offset)s Index:%(Module_Index)02d) \n' %{"File_Name": infile, "Entry_Offset": hex(mySpiLocation), "Module_Index": recovery_index}
+
+ recovery_index += 1
+
+ # Fixup the Firmware Volume Header Checksum
+ currentBin.seek(50, os.SEEK_SET)
+ currentBin.write(struct.pack('H', 0x0000))
+
+ currentBin.seek(48, os.SEEK_SET)
+ low_byte = ord(currentBin.read(1))
+ high_byte = ord(currentBin.read(1))
+ headerLength = ((high_byte << 8) | low_byte) / 2
+
+ currentBin.seek(0, os.SEEK_SET)
+ headerChecksum = 0
+ for index in range(0,headerLength):
+ low_byte = ord(currentBin.read(1))
+ high_byte = ord(currentBin.read(1))
+ temp = (high_byte << 8) | low_byte
+ headerChecksum = (headerChecksum + temp) & 0xFFFF
+
+ headerChecksum = (0x10000 - headerChecksum) & 0xFFFF
+ currentBin.seek(50, os.SEEK_SET)
+ currentBin.write(struct.pack('B', (headerChecksum & 0x00FF)))
+ currentBin.write(struct.pack('B', (headerChecksum >> 8) & 0x00FF))
+
+ currentBin.close()
+
+ elif (re.search("EDKII_BOOTROM_OVERRIDE", infile)):
+ # open current file, then update the offset and index
+ currentBin = open(infile, 'rb+')
+ currentBinLength = len(currentBin.read())
+
+ #
+ # Search for 'ValidateModuleCallBack':
+ #
+ currentBin.seek(0, os.SEEK_SET)
+ currCount = 0
+ for currCount in range(currentBinLength):
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'V':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'a':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'l':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'i':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'd':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'a':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 't':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'e':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'M':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'o':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'd':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'u':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'l':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'e':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'C':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'a':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'l':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'l':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'B':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'a':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'c':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'k':
+ break
+ mySpiLocation = currentBin.tell()
+ mySpiLocation = mySpiLocation + QuarkRomBaseAddress
+
+ #
+ # Patch the validate callback address address of the 32-bit code entry point
+ #
+ currentBin.seek(-32, os.SEEK_END)
+ currentBin.write(struct.pack('L', mySpiLocation))
+
+ currentBin.seek(0, os.SEEK_SET)
+ currCount = 0
+ for currCount in range(currentBinLength):
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'V':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'a':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'l':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'i':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'd':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'a':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 't':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'e':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'K':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'e':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'y':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'M':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'o':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'd':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'C':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'a':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'l':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'l':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'B':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'a':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'c':
+ currByte = currentBin.read(1)
+ currCount = currCount+1
+ if currByte == 'k':
+ break
+ mySpiLocation = currentBin.tell()
+ mySpiLocation = mySpiLocation + QuarkRomBaseAddress
+
+ #
+ # Patch the validate key callback address address of the 32-bit code entry point
+ #
+ currentBin.seek(-123590, os.SEEK_END)
+ currentBin.write(struct.pack('L', mySpiLocation))
+
+ currentBin.close()
+
+ index1 = 1
+ index2 = 1
+ #check files for fvs that are recovery only combine stage1 and stage2 to create 1 recovery image, plus any additional images
+ for infile in listing:
+ if infile.endswith(".Fv"):
+ pattern1 = "EDKII_RECOVERY_STAGE1_IMAGE"+ str(index1)
+ if re.search(pattern1, infile):
+ file1 = infile
+ for infile in listing:
+ pattern2 = "EDKII_RECOVERY_STAGE2_IMAGE"+ str(index1)
+ if infile.endswith(".Fv") and re.search(pattern2, infile):
+ file2 = infile
+ outfile_name = "EDKII_RECOVERY_IMAGE"+str(index1)+".Fv"
+ destination = open(output_dir+"/"+outfile_name,'wb')
+ shutil.copyfileobj(open(file1,'rb'), destination)
+ shutil.copyfileobj(open(file2,'rb'), destination)
+ destination.close()
+ index1 += 1
+ elif (re.search("EDKII_BOOT_STAGE1_IMAGE"+ str(index2), infile)):
+ file1 = infile
+ outfile_name = "EDKII_BOOT_STAGE1_IMAGE"+str(index2)+".Fv"
+ destination = open(output_dir+"/"+outfile_name,'wb')
+ shutil.copyfileobj(open(file1,'rb'), destination)
+ destination.close()
+ index2 += 1
+ else:
+ if (re.search("EDKII_BOOT_STAGE2", infile)):
+ shutil.copy(infile, output_dir)
+ if (re.search("EDKII_BOOT_STAGE2_RECOVERY", infile)):
+ shutil.copy(infile, output_dir)
+ if (re.search("EDKII_BOOT_STAGE2_COMPACT", infile)):
+ shutil.copy(infile, output_dir)
+ if (re.search("EDKII_BOOTROM_OVERRIDE", infile)):
+ shutil.copy(infile, output_dir)
+
+
+ #check files for fd and extract the nvram area and create new binary file with it
+ for infile in listing:
+ if infile.endswith(".fd"):
+ # open current file, then update the offset and index
+ currentBin = open(infile, 'rb+')
+ currentBinLength = len(currentBin.read())
+
+ #
+ # Search for Spi Entry Offset:
+ #
+ currentBin.seek(nvramLocation, os.SEEK_SET)
+ mySpiLocation = currentBin.tell()
+ outfile_name = "EDKII_NVRAM.bin"
+ destination = open(output_dir+"/"+outfile_name,'wb')
+ bytes_read = currentBin.read(nvramSize)
+ destination.write(bytes_read)
+ currentBin.close()
+ else:
+ print '\t ERROR: Build directory does not exist for platform: \t', platformName, '\n'
+else:
+ print '\t ERROR: Incorrect build type specified: \t', buildType, '\n'
+ print '\t Options are: \n'
+ print '\t 1:\t', buildOptionDebug, ' or ', buildOptionDebug.lower(), '\n'
+ print '\t 2:\t', buildOptionRelease, ' or ', buildOptionRelease.lower(),'\n'
+ print '\t Please specify correct build option\t\n'
+
diff --git a/QuarkPlatformPkg/Tools/SignTool/DummySignTool.c b/QuarkPlatformPkg/Tools/SignTool/DummySignTool.c
new file mode 100755
index 0000000..be6cef0
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/SignTool/DummySignTool.c
@@ -0,0 +1,289 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ CapsuleCreate.c
+
+Abstract:
+
+ Definitions for the CapsuleCreate utility.
+
+--*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Common/UefiBaseTypes.h>
+
+#include "CommonLib.h"
+#include "ParseInf.h"
+#include "EfiUtilityMsgs.h"
+
+#define UTILITY_NAME "DummySignTool"
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+
+#define MAX_IMAGE_SIZE 0xA00000
+
+#pragma pack(1)
+typedef struct {
+ UINT8 Reserved[1024];
+} CSH_DUMMY_HEADER;
+#pragma pack()
+
+
+STATIC
+VOID
+Version (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print out version information for this utility.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ fprintf (stdout, "%s Version %d.%d \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
+}
+
+STATIC
+VOID
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print Error / Help message.
+
+Arguments:
+
+ VOID
+
+Returns:
+
+ None
+
+--*/
+{
+ //
+ // Summary usage
+ //
+ fprintf (stdout, "\nUsage: %s InputFileName\n\n", UTILITY_NAME);
+
+ //
+ // Copyright declaration
+ //
+ fprintf (stdout, "Copyright (c) 2013, Intel Corporation. All rights reserved.\n\n");
+}
+
+int
+main (
+ int argc,
+ CHAR8 *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ CHAR8 *ImageBuffer;
+ CHAR8 *InputImageFileName;
+ CHAR8 *OutputImageFileName;
+ FILE *InputImageFile;
+ FILE *OutputImageFile;
+ CHAR8 FileName[_MAX_PATH];
+ CSH_DUMMY_HEADER CshDummyHeader;
+ UINT32 InputImageSize;
+ UINT32 ReadFileSize;
+
+
+ SetUtilityName (UTILITY_NAME);
+
+ if (argc == 1) {
+ Error (NULL, 0, 1001, "Missing options", "no options input");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ //
+ // Parse command line
+ //
+ argc --;
+ argv ++;
+
+ if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
+ Version ();
+ Usage ();
+ return STATUS_SUCCESS;
+ }
+
+ if (stricmp (argv[0], "--version") == 0) {
+ Version ();
+ return STATUS_SUCCESS;
+ }
+
+ InputImageFileName = NULL;
+ OutputImageFileName = NULL;
+ if (argc > 0) {
+ InputImageFileName = argv[0];
+ argv ++;
+ argc --;
+ }
+
+ if (argc > 0) {
+ OutputImageFileName = argv[0];
+ argv ++;
+ argc --;
+ }
+
+ VerboseMsg ("%s tool start.", UTILITY_NAME);
+
+ InputImageFile = NULL;
+ OutputImageFile = NULL;
+ ImageBuffer = NULL;
+
+ //
+ // Open the input image file
+ //
+ FileName[0] = '\0';
+ if (InputImageFileName == NULL) {
+ Error (NULL, 0, 1003, "Missing option", "Input Image file");
+ goto Finish;
+ }
+ strcpy (FileName, InputImageFileName);
+ InputImageFile = fopen (FileName, "rb");
+ if (InputImageFile == NULL) {
+ Error (NULL, 0, 1007, "Error opening file", FileName);
+ goto Finish;
+ }
+
+ //
+ // Open output image file
+ //
+ FileName[0] = '\0';
+ if (OutputImageFileName == NULL) {
+ Error (NULL, 0, 1005, "Missing option", "Output Image file");
+ goto Finish;
+ }
+ strcpy (FileName, OutputImageFileName);
+ OutputImageFile = fopen (FileName, "wb");
+ if (OutputImageFile == NULL) {
+ Error (NULL, 0, 1006, "Error opening file", FileName);
+ goto Finish;
+ }
+
+ //
+ // Get size of input image
+ //
+ fseek(InputImageFile, 0, SEEK_END);
+ InputImageSize = (UINT32) ftell(InputImageFile);
+ rewind(InputImageFile);
+
+ //
+ // Allocate a buffer to read the input images into
+ //
+ ImageBuffer = (CHAR8*) malloc (sizeof(CHAR8)*MAX_IMAGE_SIZE);
+ if (ImageBuffer == NULL) {
+ goto Finish;
+ }
+ ZeroMem (ImageBuffer, sizeof(CHAR8)*MAX_IMAGE_SIZE);
+
+ //
+ // Initialise Data
+ //
+ ZeroMem (&CshDummyHeader, sizeof (CshDummyHeader));
+
+ //
+ // Read input image into buffer
+ //
+ if (InputImageSize >= MAX_IMAGE_SIZE) {
+ Error (NULL, 0, 1008, "Input image size is", " > MAX_IMAGE_SIZE");
+ goto Finish;
+ }
+ ReadFileSize = (UINT32) fread((CHAR8 *)ImageBuffer, 1, InputImageSize, InputImageFile);
+ if (ReadFileSize != InputImageSize) {
+ Error (NULL, 0, 1009, "Error reading input file", ".");
+ goto Finish;
+ }
+
+ //
+ // Write to output file
+ //
+ fwrite (&CshDummyHeader, 1, sizeof (CshDummyHeader), OutputImageFile);
+ fwrite (ImageBuffer, 1, InputImageSize, OutputImageFile);
+
+Finish:
+ if (InputImageFile != NULL) {
+ fclose (InputImageFile);
+ }
+
+ if (OutputImageFile != NULL) {
+ fclose (OutputImageFile);
+ }
+
+ if (ImageBuffer != NULL) {
+ free (ImageBuffer);
+ }
+
+ //
+ // If any errors were reported via the standard error reporting
+ // routines, then the status has been saved. Get the value and
+ // return it to the caller.
+ //
+ VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
+
+ return GetUtilityStatus ();
+}
diff --git a/QuarkPlatformPkg/Tools/SignTool/DummySignTool.exe b/QuarkPlatformPkg/Tools/SignTool/DummySignTool.exe
new file mode 100755
index 0000000..5bb3d9b
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/SignTool/DummySignTool.exe
Binary files differ
diff --git a/QuarkPlatformPkg/Tools/SignTool/GNUmakefile b/QuarkPlatformPkg/Tools/SignTool/GNUmakefile
new file mode 100755
index 0000000..bc33352
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/SignTool/GNUmakefile
@@ -0,0 +1,55 @@
+## @file
+# Makefile for for 'DummySignTool' module build.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ARCH = IA32
+MAKEROOT = ../../../BaseTools/Source/C
+LIBS = -lCommon
+
+include $(MAKEROOT)/Makefiles/header.makefile
+
+APPNAME = DummySignTool
+
+OBJECTS = DummySignTool.o
+
+
+APPLICATION = $(APPNAME)
+
+.PHONY:all
+all: $(APPLICATION)
+
+$(APPLICATION): $(OBJECTS)
+ $(LINKER) -o $(APPLICATION) $(LFLAGS) $(OBJECTS) -L$(MAKEROOT)/libs $(LIBS)
+
+$(OBJECTS): $(MAKEROOT)/Include/Common/BuildVersion.h
+
+#include $(MAKEROOT)/Makefiles/footer.makefile
+
+
+
diff --git a/QuarkPlatformPkg/Tools/SignTool/Makefile b/QuarkPlatformPkg/Tools/SignTool/Makefile
new file mode 100755
index 0000000..439f7cb
--- /dev/null
+++ b/QuarkPlatformPkg/Tools/SignTool/Makefile
@@ -0,0 +1,42 @@
+## @file
+# Windows makefile for 'DummySignTool' module build.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+!INCLUDE ..\Makefiles\ms.common
+
+APPNAME = DummySignTool
+
+LIBS = $(LIB_PATH)\Common.lib
+
+OBJECTS = DummySignTool.obj
+
+!INCLUDE ..\Makefiles\ms.app
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/BaseLib.inf b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/BaseLib.inf
new file mode 100644
index 0000000..16e8ae8
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/BaseLib.inf
@@ -0,0 +1,517 @@
+## @file
+# Base Library implementation.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseLib
+ FILE_GUID = 27d67720-ea68-48ae-93da-a3a074c90e30
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BaseLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC ARM
+#
+
+[Sources]
+ ../../../../../MdePkg/Library/BaseLib/CheckSum.c
+ ../../../../../MdePkg/Library/BaseLib/SwitchStack.c
+ ../../../../../MdePkg/Library/BaseLib/SwapBytes64.c
+ ../../../../../MdePkg/Library/BaseLib/SwapBytes32.c
+ ../../../../../MdePkg/Library/BaseLib/SwapBytes16.c
+ ../../../../../MdePkg/Library/BaseLib/LongJump.c
+ ../../../../../MdePkg/Library/BaseLib/SetJump.c
+ ../../../../../MdePkg/Library/BaseLib/RShiftU64.c
+ ../../../../../MdePkg/Library/BaseLib/RRotU64.c
+ ../../../../../MdePkg/Library/BaseLib/RRotU32.c
+ ../../../../../MdePkg/Library/BaseLib/MultU64x64.c
+ ../../../../../MdePkg/Library/BaseLib/MultU64x32.c
+ ../../../../../MdePkg/Library/BaseLib/MultS64x64.c
+ ../../../../../MdePkg/Library/BaseLib/ModU64x32.c
+ ../../../../../MdePkg/Library/BaseLib/LShiftU64.c
+ ../../../../../MdePkg/Library/BaseLib/LRotU64.c
+ ../../../../../MdePkg/Library/BaseLib/LRotU32.c
+ ../../../../../MdePkg/Library/BaseLib/LowBitSet64.c
+ ../../../../../MdePkg/Library/BaseLib/LowBitSet32.c
+ ../../../../../MdePkg/Library/BaseLib/HighBitSet64.c
+ ../../../../../MdePkg/Library/BaseLib/HighBitSet32.c
+ ../../../../../MdePkg/Library/BaseLib/GetPowerOfTwo64.c
+ ../../../../../MdePkg/Library/BaseLib/GetPowerOfTwo32.c
+ ../../../../../MdePkg/Library/BaseLib/DivU64x64Remainder.c
+ ../../../../../MdePkg/Library/BaseLib/DivU64x32Remainder.c
+ ../../../../../MdePkg/Library/BaseLib/DivU64x32.c
+ ../../../../../MdePkg/Library/BaseLib/DivS64x64Remainder.c
+ ../../../../../MdePkg/Library/BaseLib/ARShiftU64.c
+ ../../../../../MdePkg/Library/BaseLib/BitField.c
+ CpuDeadLoop.c
+ ../../../../../MdePkg/Library/BaseLib/Cpu.c
+ ../../../../../MdePkg/Library/BaseLib/LinkedList.c
+ ../../../../../MdePkg/Library/BaseLib/String.c
+ ../../../../../MdePkg/Library/BaseLib/BaseLibInternals.h
+ ../../../../../QuarkSocPkg/QuarkNorthCluster/Include/QuarkNcSocId.h
+ ../../../../../UefiCpuPkg/Include/Library/MtrrLib.h
+ ReadMsr64.c
+ WriteMsr64.c
+ QuarkMsr.c
+ QuarkMsr.h
+
+[Sources.Ia32]
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Wbinvd.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm7.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm6.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm5.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm4.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm3.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm2.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm1.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm0.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteLdtr.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteIdtr.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteGdtr.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr7.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr6.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr5.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr4.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr3.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr2.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr1.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr0.c | MSFT
+ Ia32/WriteCr4.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteCr3.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteCr2.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteCr0.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/SwapBytes64.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/SetJump.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/RRotU64.c | MSFT
+ Ia32/RShiftU64.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadPmc.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadTsc.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadLdtr.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadIdtr.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadGdtr.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadTr.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadSs.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadGs.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadFs.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadEs.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDs.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCs.c | MSFT
+ Ia32/MsrUtils.asm | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm7.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm6.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm5.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm4.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm3.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm2.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm1.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm0.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadEflags.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr7.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr6.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr5.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr4.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr3.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr2.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr1.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr0.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCr4.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCr3.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCr2.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCr0.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Mwait.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Monitor.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ModU64x32.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/MultU64x64.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/MultU64x32.c | MSFT
+ Ia32/LShiftU64.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/LRotU64.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/LongJump.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Invd.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/FxRestore.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/FxSave.c | MSFT
+ Ia32/FlushCacheLine.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnablePaging32.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.asm | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x32.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DisablePaging32.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuPause.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuIdEx.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuId.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ARShiftU64.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Thunk16.asm | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnablePaging64.asm | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnableCache.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DisableCache.c | MSFT
+
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Wbinvd.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm7.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm6.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm5.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm4.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm3.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm2.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm1.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMm0.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteLdtr.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteIdtr.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteGdtr.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr7.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr6.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr5.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr4.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr3.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr2.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr1.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteDr0.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteCr4.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteCr3.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteCr2.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteCr0.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/WriteMsr64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/SwapBytes64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/SetJump.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/RRotU64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/RShiftU64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadPmc.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadTsc.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadLdtr.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadIdtr.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadGdtr.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadTr.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadSs.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadGs.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadFs.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadEs.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDs.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCs.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMsr64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm7.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm6.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm5.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm4.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm3.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm2.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm1.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadMm0.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadEflags.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr7.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr6.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr5.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr4.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr3.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr2.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr1.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadDr0.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCr4.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCr3.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCr2.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ReadCr0.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Mwait.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Monitor.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ModU64x32.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/MultU64x64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/MultU64x32.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/LShiftU64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/LRotU64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/LongJump.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Invd.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/FxRestore.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/FxSave.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/FlushCacheLine.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnablePaging32.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnableInterrupts.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x32.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DisablePaging32.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DisableInterrupts.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuPause.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuIdEx.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuId.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ARShiftU64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Thunk16.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnablePaging64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnableCache.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DisableCache.asm | INTEL
+
+ Ia32/GccInline.c | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Thunk16.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnablePaging64.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DisablePaging32.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnablePaging32.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Mwait.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Monitor.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuIdEx.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/CpuId.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/LongJump.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/SetJump.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/SwapBytes64.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ModU64x32.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivU64x32.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/MultU64x64.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/MultU64x32.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/RRotU64.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/LRotU64.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/ARShiftU64.S | GCC
+ Ia32/MsrUtils.S | GCC
+ Ia32/RShiftU64.S | GCC
+ Ia32/LShiftU64.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/EnableCache.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DisableCache.S | GCC
+
+ ../../../../../MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c
+ ../../../../../MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ia32/Non-existing.c
+ ../../../../../MdePkg/Library/BaseLib/Unaligned.c
+ ../../../../../MdePkg/Library/BaseLib/X86WriteIdtr.c
+ ../../../../../MdePkg/Library/BaseLib/X86WriteGdtr.c
+ ../../../../../MdePkg/Library/BaseLib/X86Thunk.c
+ ../../../../../MdePkg/Library/BaseLib/X86ReadIdtr.c
+ ../../../../../MdePkg/Library/BaseLib/X86ReadGdtr.c
+ ../../../../../MdePkg/Library/BaseLib/X86Msr.c
+ ../../../../../MdePkg/Library/BaseLib/X86MemoryFence.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/X86MemoryFence.c | INTEL
+ ../../../../../MdePkg/Library/BaseLib/X86GetInterruptState.c
+ ../../../../../MdePkg/Library/BaseLib/X86FxSave.c
+ ../../../../../MdePkg/Library/BaseLib/X86FxRestore.c
+ ../../../../../MdePkg/Library/BaseLib/X86EnablePaging64.c
+ ../../../../../MdePkg/Library/BaseLib/X86EnablePaging32.c
+ ../../../../../MdePkg/Library/BaseLib/X86DisablePaging64.c
+ ../../../../../MdePkg/Library/BaseLib/X86DisablePaging32.c
+
+[Sources.X64]
+ ../../../../../MdePkg/Library/BaseLib/X64/Thunk16.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/CpuPause.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/DisableInterrupts.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/EnableInterrupts.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/FlushCacheLine.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/Invd.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/Wbinvd.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/DisablePaging64.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/Mwait.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/Monitor.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadPmc.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadTsc.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMm7.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMm6.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMm5.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMm4.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMm3.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMm2.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMm1.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMm0.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMm7.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMm6.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMm5.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMm4.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMm3.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMm2.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMm1.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMm0.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/FxRestore.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/FxSave.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteLdtr.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadLdtr.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteIdtr.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadIdtr.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteGdtr.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadGdtr.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadTr.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadSs.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadGs.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadFs.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadEs.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDs.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadCs.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteDr7.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteDr6.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteDr5.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteDr4.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteDr3.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteDr2.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteDr1.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteDr0.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDr7.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDr6.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDr5.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDr4.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDr3.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDr2.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDr1.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadDr0.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteCr4.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteCr3.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteCr2.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteCr0.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadCr4.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadCr3.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadCr2.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadCr0.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadEflags.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/CpuIdEx.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/CpuId.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/LongJump.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/SetJump.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/SwitchStack.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/EnableCache.asm
+ ../../../../../MdePkg/Library/BaseLib/X64/DisableCache.asm
+
+ ../../../../../MdePkg/Library/BaseLib/X64/CpuBreakpoint.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMsr64.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMsr64.c | MSFT
+
+ ../../../../../MdePkg/Library/BaseLib/X64/CpuBreakpoint.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/X64/WriteMsr64.asm | INTEL
+ ../../../../../MdePkg/Library/BaseLib/X64/ReadMsr64.asm | INTEL
+
+ ../../../../../MdePkg/Library/BaseLib/X64/Non-existing.c
+ ../../../../../MdePkg/Library/BaseLib/Math64.c
+ ../../../../../MdePkg/Library/BaseLib/Unaligned.c
+ ../../../../../MdePkg/Library/BaseLib/X86WriteIdtr.c
+ ../../../../../MdePkg/Library/BaseLib/X86WriteGdtr.c
+ ../../../../../MdePkg/Library/BaseLib/X86Thunk.c
+ ../../../../../MdePkg/Library/BaseLib/X86ReadIdtr.c
+ ../../../../../MdePkg/Library/BaseLib/X86ReadGdtr.c
+ ../../../../../MdePkg/Library/BaseLib/X86Msr.c
+ ../../../../../MdePkg/Library/BaseLib/X86MemoryFence.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/X86MemoryFence.c | INTEL
+ ../../../../../MdePkg/Library/BaseLib/X86GetInterruptState.c
+ ../../../../../MdePkg/Library/BaseLib/X86FxSave.c
+ ../../../../../MdePkg/Library/BaseLib/X86FxRestore.c
+ ../../../../../MdePkg/Library/BaseLib/X86EnablePaging64.c
+ ../../../../../MdePkg/Library/BaseLib/X86EnablePaging32.c
+ ../../../../../MdePkg/Library/BaseLib/X86DisablePaging64.c
+ ../../../../../MdePkg/Library/BaseLib/X86DisablePaging32.c
+ ../../../../../MdePkg/Library/BaseLib/X64/GccInline.c | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/Thunk16.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/SwitchStack.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/SetJump.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/LongJump.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/DisablePaging64.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/CpuId.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/CpuIdEx.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/EnableCache.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/X64/DisableCache.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/ChkStkGcc.c | GCC
+
+[Sources.IPF]
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessGp.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/ReadCpuid.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/ExecFc.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AsmPalCall.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessPsr.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessPmr.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessKr.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessKr7.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessGcr.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessEicr.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessDbr.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessMsr.s | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessMsr.s | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AccessMsrDb.s | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ipf/InternalFlushCacheRange.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/FlushCacheRange.c
+ ../../../../../MdePkg/Library/BaseLib/Ipf/InternalSwitchStack.c
+ ../../../../../MdePkg/Library/BaseLib/Ipf/GetInterruptState.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/CpuPause.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/CpuBreakpoint.c | INTEL
+ ../../../../../MdePkg/Library/BaseLib/Ipf/CpuBreakpointMsc.c | MSFT
+ ../../../../../MdePkg/Library/BaseLib/Ipf/AsmCpuMisc.s | GCC
+ ../../../../../MdePkg/Library/BaseLib/Ipf/Unaligned.c
+ ../../../../../MdePkg/Library/BaseLib/Ipf/SwitchStack.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/LongJmp.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/SetJmp.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/ReadCr.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/ReadAr.s
+ ../../../../../MdePkg/Library/BaseLib/Ipf/Ia64gen.h
+ ../../../../../MdePkg/Library/BaseLib/Ipf/Asm.h
+ ../../../../../MdePkg/Library/BaseLib/Math64.c
+
+[Sources.EBC]
+ ../../../../../MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c
+ ../../../../../MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c
+ ../../../../../MdePkg/Library/BaseLib/Ebc/SwitchStack.c
+ ../../../../../MdePkg/Library/BaseLib/Unaligned.c
+ ../../../../../MdePkg/Library/BaseLib/Math64.c
+
+[Sources.ARM]
+ ../../../../../MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c
+ ../../../../../MdePkg/Library/BaseLib/Arm/Unaligned.c
+ ../../../../../MdePkg/Library/BaseLib/Math64.c | RVCT
+
+ ../../../../../MdePkg/Library/BaseLib/Arm/SwitchStack.asm | RVCT
+ ../../../../../MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm | RVCT
+ ../../../../../MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm | RVCT
+ ../../../../../MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm | RVCT
+ ../../../../../MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm | RVCT
+ ../../../../../MdePkg/Library/BaseLib/Arm/CpuPause.asm | RVCT
+ ../../../../../MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm | RVCT
+
+ ../../../../../MdePkg/Library/BaseLib/Arm/Math64.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Arm/SwitchStack.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Arm/EnableInterrupts.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Arm/DisableInterrupts.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Arm/GetInterruptsState.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S | GCC
+ ../../../../../MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ DebugLib
+ QNCAccessLib
+ BaseMemoryLib
+ RecoveryOemHookLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength
+ gEfiMdePkgTokenSpaceGuid.PcdVerifyNodeInList
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/CpuDeadLoop.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/CpuDeadLoop.c
new file mode 100755
index 0000000..2653ae5
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/CpuDeadLoop.c
@@ -0,0 +1,68 @@
+/** @file
+ Base Library CPU Functions for all architectures.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+
+/**
+ This function allows the user to force a system recovery
+
+**/
+VOID
+EFIAPI
+OemInitiateRecovery (
+ VOID
+ );
+
+/**
+ Executes an infinite loop.
+
+ Forces the CPU to execute an infinite loop. A debugger may be used to skip
+ past the loop and the code that follows the loop must execute properly. This
+ implies that the infinite loop must not cause the code that follow it to be
+ optimized away.
+
+**/
+VOID
+EFIAPI
+CpuDeadLoop (
+ VOID
+ )
+{
+ volatile UINTN Index;
+
+ OemInitiateRecovery();
+ for (Index = 0; Index == 0;);
+}
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c
new file mode 100644
index 0000000..40ddc59
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c
@@ -0,0 +1,63 @@
+/** @file
+ AsmFlushCacheLine function
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+
+/**
+ Flushes a cache line from all the instruction and data caches within the
+ coherency domain of the CPU.
+
+ Flushed the cache line specified by LinearAddress, and returns LinearAddress.
+ This function is only available on IA-32 and x64.
+
+ @param LinearAddress The address of the cache line to flush. If the CPU is
+ in a physical addressing mode, then LinearAddress is a
+ physical address. If the CPU is in a virtual
+ addressing mode, then LinearAddress is a virtual
+ address.
+
+ @return LinearAddress
+**/
+VOID *
+EFIAPI
+AsmFlushCacheLine (
+ IN VOID *LinearAddress
+ )
+{
+ _asm {
+ mov eax, LinearAddress
+ wbinvd
+ }
+}
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/GccInline.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/GccInline.c
new file mode 100644
index 0000000..e4eec4f
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/GccInline.c
@@ -0,0 +1,1705 @@
+/** @file
+ GCC inline implementation of BaseLib processor specific functions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "BaseLibInternals.h"
+
+
+
+/**
+ Used to serialize load and store operations.
+
+ All loads and stores that proceed calls to this function are guaranteed to be
+ globally visible when this function returns.
+
+**/
+VOID
+EFIAPI
+MemoryFence (
+ VOID
+ )
+{
+ // This is a little bit of overkill and it is more about the compiler that it is
+ // actually processor synchronization. This is like the _ReadWriteBarrier
+ // Microsoft specific intrinsic
+ __asm__ __volatile__ ("":::"memory");
+}
+
+
+/**
+ Enables CPU interrupts.
+
+ Enables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+EnableInterrupts (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("sti"::: "memory");
+}
+
+
+/**
+ Disables CPU interrupts.
+
+ Disables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+DisableInterrupts (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("cli"::: "memory");
+}
+
+
+
+
+/**
+ Requests CPU to pause for a short period of time.
+
+ Requests CPU to pause for a short period of time. Typically used in MP
+ systems to prevent memory starvation while waiting for a spin lock.
+
+**/
+VOID
+EFIAPI
+CpuPause (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("pause");
+}
+
+
+/**
+ Generates a breakpoint on the CPU.
+
+ Generates a breakpoint on the CPU. The breakpoint must be implemented such
+ that code can resume normal execution after the breakpoint.
+
+**/
+VOID
+EFIAPI
+CpuBreakpoint (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("int $3");
+}
+
+
+
+/**
+ Reads the current value of the EFLAGS register.
+
+ Reads and returns the current value of the EFLAGS register. This function is
+ only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a
+ 64-bit value on X64.
+
+ @return EFLAGS on IA-32 or RFLAGS on X64.
+
+**/
+UINTN
+EFIAPI
+AsmReadEflags (
+ VOID
+ )
+{
+ UINTN Eflags;
+
+ __asm__ __volatile__ (
+ "pushfl \n\t"
+ "popl %0 "
+ : "=r" (Eflags)
+ );
+
+ return Eflags;
+}
+
+
+
+/**
+ Reads the current value of the Control Register 0 (CR0).
+
+ Reads and returns the current value of CR0. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 0 (CR0).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr0 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%cr0,%0"
+ : "=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of the Control Register 2 (CR2).
+
+ Reads and returns the current value of CR2. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 2 (CR2).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr2 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%cr2, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+/**
+ Reads the current value of the Control Register 3 (CR3).
+
+ Reads and returns the current value of CR3. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 3 (CR3).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr3 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%cr3, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of the Control Register 4 (CR4).
+
+ Reads and returns the current value of CR4. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 4 (CR4).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr4 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%cr4, %0"
+ : "=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes a value to Control Register 0 (CR0).
+
+ Writes and returns a new value to CR0. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr0 The value to write to CR0.
+
+ @return The value written to CR0.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr0 (
+ UINTN Cr0
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%cr0"
+ :
+ : "r" (Cr0)
+ );
+ return Cr0;
+}
+
+
+/**
+ Writes a value to Control Register 2 (CR2).
+
+ Writes and returns a new value to CR2. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr2 The value to write to CR2.
+
+ @return The value written to CR2.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr2 (
+ UINTN Cr2
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%cr2"
+ :
+ : "r" (Cr2)
+ );
+ return Cr2;
+}
+
+
+/**
+ Writes a value to Control Register 3 (CR3).
+
+ Writes and returns a new value to CR3. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr3 The value to write to CR3.
+
+ @return The value written to CR3.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr3 (
+ UINTN Cr3
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%cr3"
+ :
+ : "r" (Cr3)
+ );
+ return Cr3;
+}
+
+
+/**
+ Writes a value to Control Register 4 (CR4).
+
+ Writes and returns a new value to CR4. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr4 The value to write to CR4.
+
+ @return The value written to CR4.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr4 (
+ UINTN Cr4
+ )
+{
+ Cr4 &= 0xFFFFF9F7;
+ __asm__ __volatile__ (
+ "movl %0, %%cr4"
+ :
+ : "r" (Cr4)
+ );
+ return Cr4;
+}
+
+
+/**
+ Reads the current value of Debug Register 0 (DR0).
+
+ Reads and returns the current value of DR0. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr0 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr0, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 1 (DR1).
+
+ Reads and returns the current value of DR1. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr1 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr1, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 2 (DR2).
+
+ Reads and returns the current value of DR2. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr2 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr2, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 3 (DR3).
+
+ Reads and returns the current value of DR3. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr3 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr3, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 4 (DR4).
+
+ Reads and returns the current value of DR4. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr4 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr4, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 5 (DR5).
+
+ Reads and returns the current value of DR5. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr5 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr5, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 6 (DR6).
+
+ Reads and returns the current value of DR6. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr6 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr6, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 7 (DR7).
+
+ Reads and returns the current value of DR7. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr7 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr7, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes a value to Debug Register 0 (DR0).
+
+ Writes and returns a new value to DR0. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr0 The value to write to Dr0.
+
+ @return The value written to Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr0 (
+ UINTN Dr0
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr0"
+ :
+ : "r" (Dr0)
+ );
+ return Dr0;
+}
+
+
+/**
+ Writes a value to Debug Register 1 (DR1).
+
+ Writes and returns a new value to DR1. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr1 The value to write to Dr1.
+
+ @return The value written to Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr1 (
+ UINTN Dr1
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr1"
+ :
+ : "r" (Dr1)
+ );
+ return Dr1;
+}
+
+
+/**
+ Writes a value to Debug Register 2 (DR2).
+
+ Writes and returns a new value to DR2. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr2 The value to write to Dr2.
+
+ @return The value written to Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr2 (
+ UINTN Dr2
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr2"
+ :
+ : "r" (Dr2)
+ );
+ return Dr2;
+}
+
+
+/**
+ Writes a value to Debug Register 3 (DR3).
+
+ Writes and returns a new value to DR3. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr3 The value to write to Dr3.
+
+ @return The value written to Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr3 (
+ UINTN Dr3
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr3"
+ :
+ : "r" (Dr3)
+ );
+ return Dr3;
+}
+
+
+/**
+ Writes a value to Debug Register 4 (DR4).
+
+ Writes and returns a new value to DR4. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr4 The value to write to Dr4.
+
+ @return The value written to Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr4 (
+ UINTN Dr4
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr4"
+ :
+ : "r" (Dr4)
+ );
+ return Dr4;
+}
+
+
+/**
+ Writes a value to Debug Register 5 (DR5).
+
+ Writes and returns a new value to DR5. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr5 The value to write to Dr5.
+
+ @return The value written to Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr5 (
+ UINTN Dr5
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr5"
+ :
+ : "r" (Dr5)
+ );
+ return Dr5;
+}
+
+
+/**
+ Writes a value to Debug Register 6 (DR6).
+
+ Writes and returns a new value to DR6. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr6 The value to write to Dr6.
+
+ @return The value written to Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr6 (
+ UINTN Dr6
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr6"
+ :
+ : "r" (Dr6)
+ );
+ return Dr6;
+}
+
+
+/**
+ Writes a value to Debug Register 7 (DR7).
+
+ Writes and returns a new value to DR7. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr7 The value to write to Dr7.
+
+ @return The value written to Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr7 (
+ UINTN Dr7
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr7"
+ :
+ : "r" (Dr7)
+ );
+ return Dr7;
+}
+
+
+/**
+ Reads the current value of Code Segment Register (CS).
+
+ Reads and returns the current value of CS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of CS.
+
+**/
+UINT16
+EFIAPI
+AsmReadCs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%cs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Data Segment Register (DS).
+
+ Reads and returns the current value of DS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of DS.
+
+**/
+UINT16
+EFIAPI
+AsmReadDs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%ds, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Extra Segment Register (ES).
+
+ Reads and returns the current value of ES. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of ES.
+
+**/
+UINT16
+EFIAPI
+AsmReadEs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%es, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of FS Data Segment Register (FS).
+
+ Reads and returns the current value of FS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of FS.
+
+**/
+UINT16
+EFIAPI
+AsmReadFs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%fs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of GS Data Segment Register (GS).
+
+ Reads and returns the current value of GS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of GS.
+
+**/
+UINT16
+EFIAPI
+AsmReadGs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%gs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Stack Segment Register (SS).
+
+ Reads and returns the current value of SS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of SS.
+
+**/
+UINT16
+EFIAPI
+AsmReadSs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%ds, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Task Register (TR).
+
+ Reads and returns the current value of TR. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of TR.
+
+**/
+UINT16
+EFIAPI
+AsmReadTr (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "str %0"
+ : "=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current Global Descriptor Table Register(GDTR) descriptor.
+
+ Reads and returns the current GDTR descriptor and returns it in Gdtr. This
+ function is only available on IA-32 and X64.
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86ReadGdtr (
+ OUT IA32_DESCRIPTOR *Gdtr
+ )
+{
+ __asm__ __volatile__ (
+ "sgdt %0"
+ : "=m" (*Gdtr)
+ );
+}
+
+
+/**
+ Writes the current Global Descriptor Table Register (GDTR) descriptor.
+
+ Writes and the current GDTR descriptor specified by Gdtr. This function is
+ only available on IA-32 and X64.
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86WriteGdtr (
+ IN CONST IA32_DESCRIPTOR *Gdtr
+ )
+{
+ __asm__ __volatile__ (
+ "lgdt %0"
+ :
+ : "m" (*Gdtr)
+ );
+
+}
+
+
+/**
+ Reads the current Interrupt Descriptor Table Register(GDTR) descriptor.
+
+ Reads and returns the current IDTR descriptor and returns it in Idtr. This
+ function is only available on IA-32 and X64.
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86ReadIdtr (
+ OUT IA32_DESCRIPTOR *Idtr
+ )
+{
+ __asm__ __volatile__ (
+ "sidt %0"
+ : "=m" (*Idtr)
+ );
+}
+
+
+/**
+ Writes the current Interrupt Descriptor Table Register(GDTR) descriptor.
+
+ Writes the current IDTR descriptor and returns it in Idtr. This function is
+ only available on IA-32 and X64.
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86WriteIdtr (
+ IN CONST IA32_DESCRIPTOR *Idtr
+ )
+{
+ __asm__ __volatile__ (
+ "lidt %0"
+ :
+ : "m" (*Idtr)
+ );
+}
+
+
+/**
+ Reads the current Local Descriptor Table Register(LDTR) selector.
+
+ Reads and returns the current 16-bit LDTR descriptor value. This function is
+ only available on IA-32 and X64.
+
+ @return The current selector of LDT.
+
+**/
+UINT16
+EFIAPI
+AsmReadLdtr (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "sldt %0"
+ : "=g" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes the current Local Descriptor Table Register (GDTR) selector.
+
+ Writes and the current LDTR descriptor specified by Ldtr. This function is
+ only available on IA-32 and X64.
+
+ @param Ldtr 16-bit LDTR selector value.
+
+**/
+VOID
+EFIAPI
+AsmWriteLdtr (
+ IN UINT16 Ldtr
+ )
+{
+ __asm__ __volatile__ (
+ "lldtw %0"
+ :
+ : "g" (Ldtr) // %0
+ );
+}
+
+
+/**
+ Save the current floating point/SSE/SSE2 context to a buffer.
+
+ Saves the current floating point/SSE/SSE2 state to the buffer specified by
+ Buffer. Buffer must be aligned on a 16-byte boundary. This function is only
+ available on IA-32 and X64.
+
+ @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context.
+
+**/
+VOID
+EFIAPI
+InternalX86FxSave (
+ OUT IA32_FX_BUFFER *Buffer
+ )
+{
+ __asm__ __volatile__ (
+ "fxsave %0"
+ :
+ : "m" (*Buffer) // %0
+ );
+}
+
+
+/**
+ Restores the current floating point/SSE/SSE2 context from a buffer.
+
+ Restores the current floating point/SSE/SSE2 state from the buffer specified
+ by Buffer. Buffer must be aligned on a 16-byte boundary. This function is
+ only available on IA-32 and X64.
+
+ @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context.
+
+**/
+VOID
+EFIAPI
+InternalX86FxRestore (
+ IN CONST IA32_FX_BUFFER *Buffer
+ )
+{
+ __asm__ __volatile__ (
+ "fxrstor %0"
+ :
+ : "m" (*Buffer) // %0
+ );
+}
+
+
+/**
+ Reads the current value of 64-bit MMX Register #0 (MM0).
+
+ Reads and returns the current value of MM0. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of MM0.
+
+**/
+UINT64
+EFIAPI
+AsmReadMm0 (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "push %%eax \n\t"
+ "push %%eax \n\t"
+ "movq %%mm0, (%%esp)\n\t"
+ "pop %%eax \n\t"
+ "pop %%edx \n\t"
+ : "=A" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of 64-bit MMX Register #1 (MM1).
+
+ Reads and returns the current value of MM1. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of MM1.
+
+**/
+UINT64
+EFIAPI
+AsmReadMm1 (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "push %%eax \n\t"
+ "push %%eax \n\t"
+ "movq %%mm1, (%%esp)\n\t"
+ "pop %%eax \n\t"
+ "pop %%edx \n\t"
+ : "=A" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of 64-bit MMX Register #2 (MM2).
+
+ Reads and returns the current value of MM2. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of MM2.
+
+**/
+UINT64
+EFIAPI
+AsmReadMm2 (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "push %%eax \n\t"
+ "push %%eax \n\t"
+ "movq %%mm2, (%%esp)\n\t"
+ "pop %%eax \n\t"
+ "pop %%edx \n\t"
+ : "=A" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of 64-bit MMX Register #3 (MM3).
+
+ Reads and returns the current value of MM3. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of MM3.
+
+**/
+UINT64
+EFIAPI
+AsmReadMm3 (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "push %%eax \n\t"
+ "push %%eax \n\t"
+ "movq %%mm3, (%%esp)\n\t"
+ "pop %%eax \n\t"
+ "pop %%edx \n\t"
+ : "=A" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of 64-bit MMX Register #4 (MM4).
+
+ Reads and returns the current value of MM4. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of MM4.
+
+**/
+UINT64
+EFIAPI
+AsmReadMm4 (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "push %%eax \n\t"
+ "push %%eax \n\t"
+ "movq %%mm4, (%%esp)\n\t"
+ "pop %%eax \n\t"
+ "pop %%edx \n\t"
+ : "=A" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of 64-bit MMX Register #5 (MM5).
+
+ Reads and returns the current value of MM5. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of MM5.
+
+**/
+UINT64
+EFIAPI
+AsmReadMm5 (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "push %%eax \n\t"
+ "push %%eax \n\t"
+ "movq %%mm5, (%%esp)\n\t"
+ "pop %%eax \n\t"
+ "pop %%edx \n\t"
+ : "=A" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of 64-bit MMX Register #6 (MM6).
+
+ Reads and returns the current value of MM6. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of MM6.
+
+**/
+UINT64
+EFIAPI
+AsmReadMm6 (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "push %%eax \n\t"
+ "push %%eax \n\t"
+ "movq %%mm6, (%%esp)\n\t"
+ "pop %%eax \n\t"
+ "pop %%edx \n\t"
+ : "=A" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of 64-bit MMX Register #7 (MM7).
+
+ Reads and returns the current value of MM7. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of MM7.
+
+**/
+UINT64
+EFIAPI
+AsmReadMm7 (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "push %%eax \n\t"
+ "push %%eax \n\t"
+ "movq %%mm7, (%%esp)\n\t"
+ "pop %%eax \n\t"
+ "pop %%edx \n\t"
+ : "=A" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes the current value of 64-bit MMX Register #0 (MM0).
+
+ Writes the current value of MM0. This function is only available on IA32 and
+ X64.
+
+ @param Value The 64-bit value to write to MM0.
+
+**/
+VOID
+EFIAPI
+AsmWriteMm0 (
+ IN UINT64 Value
+ )
+{
+ __asm__ __volatile__ (
+ "movq %0, %%mm0" // %0
+ :
+ : "m" (Value)
+ );
+}
+
+
+/**
+ Writes the current value of 64-bit MMX Register #1 (MM1).
+
+ Writes the current value of MM1. This function is only available on IA32 and
+ X64.
+
+ @param Value The 64-bit value to write to MM1.
+
+**/
+VOID
+EFIAPI
+AsmWriteMm1 (
+ IN UINT64 Value
+ )
+{
+ __asm__ __volatile__ (
+ "movq %0, %%mm1" // %0
+ :
+ : "m" (Value)
+ );
+}
+
+
+/**
+ Writes the current value of 64-bit MMX Register #2 (MM2).
+
+ Writes the current value of MM2. This function is only available on IA32 and
+ X64.
+
+ @param Value The 64-bit value to write to MM2.
+
+**/
+VOID
+EFIAPI
+AsmWriteMm2 (
+ IN UINT64 Value
+ )
+{
+ __asm__ __volatile__ (
+ "movq %0, %%mm2" // %0
+ :
+ : "m" (Value)
+ );
+}
+
+
+/**
+ Writes the current value of 64-bit MMX Register #3 (MM3).
+
+ Writes the current value of MM3. This function is only available on IA32 and
+ X64.
+
+ @param Value The 64-bit value to write to MM3.
+
+**/
+VOID
+EFIAPI
+AsmWriteMm3 (
+ IN UINT64 Value
+ )
+{
+ __asm__ __volatile__ (
+ "movq %0, %%mm3" // %0
+ :
+ : "m" (Value)
+ );
+}
+
+
+/**
+ Writes the current value of 64-bit MMX Register #4 (MM4).
+
+ Writes the current value of MM4. This function is only available on IA32 and
+ X64.
+
+ @param Value The 64-bit value to write to MM4.
+
+**/
+VOID
+EFIAPI
+AsmWriteMm4 (
+ IN UINT64 Value
+ )
+{
+ __asm__ __volatile__ (
+ "movq %0, %%mm4" // %0
+ :
+ : "m" (Value)
+ );
+}
+
+
+/**
+ Writes the current value of 64-bit MMX Register #5 (MM5).
+
+ Writes the current value of MM5. This function is only available on IA32 and
+ X64.
+
+ @param Value The 64-bit value to write to MM5.
+
+**/
+VOID
+EFIAPI
+AsmWriteMm5 (
+ IN UINT64 Value
+ )
+{
+ __asm__ __volatile__ (
+ "movq %0, %%mm5" // %0
+ :
+ : "m" (Value)
+ );
+}
+
+
+/**
+ Writes the current value of 64-bit MMX Register #6 (MM6).
+
+ Writes the current value of MM6. This function is only available on IA32 and
+ X64.
+
+ @param Value The 64-bit value to write to MM6.
+
+**/
+VOID
+EFIAPI
+AsmWriteMm6 (
+ IN UINT64 Value
+ )
+{
+ __asm__ __volatile__ (
+ "movq %0, %%mm6" // %0
+ :
+ : "m" (Value)
+ );
+}
+
+
+/**
+ Writes the current value of 64-bit MMX Register #7 (MM7).
+
+ Writes the current value of MM7. This function is only available on IA32 and
+ X64.
+
+ @param Value The 64-bit value to write to MM7.
+
+**/
+VOID
+EFIAPI
+AsmWriteMm7 (
+ IN UINT64 Value
+ )
+{
+ __asm__ __volatile__ (
+ "movq %0, %%mm7" // %0
+ :
+ : "m" (Value)
+ );
+}
+
+
+/**
+ Reads the current value of Time Stamp Counter (TSC).
+
+ Reads and returns the current value of TSC. This function is only available
+ on IA-32 and X64.
+
+ @return The current value of TSC
+
+**/
+UINT64
+EFIAPI
+AsmReadTsc (
+ VOID
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "rdtsc"
+ : "=A" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of a Performance Counter (PMC).
+
+ Reads and returns the current value of performance counter specified by
+ Index. This function is only available on IA-32 and X64.
+
+ @param Index The 32-bit Performance Counter index to read.
+
+ @return The value of the PMC specified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadPmc (
+ IN UINT32 Index
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "rdpmc"
+ : "=A" (Data)
+ : "c" (Index)
+ );
+
+ return Data;
+}
+
+
+
+
+/**
+ Executes a WBINVD instruction.
+
+ Executes a WBINVD instruction. This function is only available on IA-32 and
+ X64.
+
+**/
+VOID
+EFIAPI
+AsmWbinvd (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("wbinvd":::"memory");
+}
+
+
+/**
+ Executes a INVD instruction.
+
+ Executes a INVD instruction. This function is only available on IA-32 and
+ X64.
+
+**/
+VOID
+EFIAPI
+AsmInvd (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("invd":::"memory");
+
+}
+
+
+/**
+ Flushes a cache line from all the instruction and data caches within the
+ coherency domain of the CPU.
+
+ Flushed the cache line specified by LinearAddress, and returns LinearAddress.
+ This function is only available on IA-32 and X64.
+
+ @param LinearAddress The address of the cache line to flush. If the CPU is
+ in a physical addressing mode, then LinearAddress is a
+ physical address. If the CPU is in a virtual
+ addressing mode, then LinearAddress is a virtual
+ address.
+
+ @return LinearAddress
+**/
+VOID *
+EFIAPI
+AsmFlushCacheLine (
+ IN VOID *LinearAddress
+ )
+{
+ __asm__ __volatile__ ("wbinvd":::"memory");
+
+ return LinearAddress;
+}
+
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/LShiftU64.S b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/LShiftU64.S
new file mode 100644
index 0000000..60ad8aa
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/LShiftU64.S
@@ -0,0 +1,62 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# LShiftU64.S
+#
+# Abstract:
+#
+# 64-bit left shift function for IA-32
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(InternalMathLShiftU64)
+
+#------------------------------------------------------------------------------
+# UINT64
+# EFIAPI
+# InternalMathLShiftU64 (
+# IN UINT64 Operand,
+# IN UINTN Count
+# );
+#------------------------------------------------------------------------------
+ASM_PFX(InternalMathLShiftU64):
+ movb 12(%esp), %cl
+ xorl %eax, %eax
+ movl 4(%esp), %edx
+ testb $32, %cl # Count >= 32?
+ jnz L0
+ movl %edx, %eax
+ movl 8(%esp), %edx
+L0:
+ shld %cl, %eax, %edx
+ shl %cl, %eax
+ ret
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/LShiftU64.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/LShiftU64.c
new file mode 100644
index 0000000..afee19d
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/LShiftU64.c
@@ -0,0 +1,70 @@
+/** @file
+ 64-bit left shift function for IA-32.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+
+/**
+ Shifts a 64-bit integer left between 0 and 63 bits. The low bits
+ are filled with zeros. The shifted value is returned.
+
+ This function shifts the 64-bit value Operand to the left by Count bits. The
+ low Count bits are set to zero. The shifted value is returned.
+
+ @param Operand The 64-bit operand to shift left.
+ @param Count The number of bits to shift left.
+
+ @return Operand << Count
+
+**/
+UINT64
+EFIAPI
+InternalMathLShiftU64 (
+ IN UINT64 Operand,
+ IN UINTN Count
+ )
+{
+ _asm {
+ mov cl, byte ptr [Count]
+ xor eax, eax
+ mov edx, dword ptr [Operand + 0]
+ test cl, 32 // Count >= 32?
+ jnz dontMoveReg
+ mov eax, edx
+ mov edx, dword ptr [Operand + 4]
+dontMoveReg:
+ shld edx, eax, cl
+ shl eax, cl
+ }
+}
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/MsrUtils.S b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/MsrUtils.S
new file mode 100644
index 0000000..35bfdb5
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/MsrUtils.S
@@ -0,0 +1,95 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# ReadMsrUtils.S
+#
+# Abstract:
+#
+# 64-bit logical right shift function for IA-32
+#
+#------------------------------------------------------------------------------
+
+ .686:
+ .code:
+
+ASM_GLOBAL ASM_PFX(AsmReadMsrReturnResult)
+ASM_GLOBAL ASM_PFX(AsmReadMsrRealMsrAccess)
+ASM_GLOBAL ASM_PFX(AsmWriteMsrRealMsrAccess)
+
+#------------------------------------------------------------------------------
+# UINT64
+# EFIAPI
+# AsmReadMsrReturnResult (
+# IN UINT32 Index,
+# IN UINT32 QuarkMsrDataLow,
+# IN UINT32 QuarkMsrDataHigh
+# );
+#------------------------------------------------------------------------------
+ASM_PFX(AsmReadMsrReturnResult):
+ movl 8(%esp), %eax # QuarkMsrDataLow
+ movl 4(%esp), %ecx # Index
+ movl 12(%esp), %edx # QuarkMsrDataHigh
+ ret
+
+#------------------------------------------------------------------------------
+# UINT64
+# EFIAPI
+# AsmReadMsrRealMsrAccess (
+# IN UINT32 Index
+# );
+#------------------------------------------------------------------------------
+ASM_PFX(AsmReadMsrRealMsrAccess):
+ movl 4(%esp), %ecx # Index
+ movl $0xFEE00900, %eax
+ movl $0x00000000, %edx
+ cmpl $0x0000001B, %ecx
+ je L0
+ rdmsr
+L0:
+ ret
+
+#------------------------------------------------------------------------------
+# UINT64
+# EFIAPI
+# AsmWriteMsrRealMsrAccess (
+# IN UINT32 Index,
+# IN UINT32 QuarkMsrDataLow,
+# IN UINT32 QuarkMsrDataHigh
+# );
+#------------------------------------------------------------------------------
+ASM_PFX(AsmWriteMsrRealMsrAccess):
+ movl 8(%esp), %eax # QuarkMsrDataLow
+ movl 4(%esp), %ecx # Index
+ movl 12(%esp), %edx # QuarkMsrDataHigh
+ wrmsr
+ ret
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/MsrUtils.asm b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/MsrUtils.asm
new file mode 100644
index 0000000..d6a3e29
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/MsrUtils.asm
@@ -0,0 +1,96 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; ReadMsrUtils.asm
+;
+; Abstract:
+;
+; Read Msr support functions
+;
+;------------------------------------------------------------------------------
+
+ .586p
+ .model flat,C
+ .code
+
+;------------------------------------------------------------------------------
+; UINT64
+; EFIAPI
+; AsmReadMsrReturnResult (
+; IN UINT32 Index,
+; IN UINT32 QuarkMsrDataLow,
+; IN UINT32 QuarkMsrDataHigh
+; );
+;------------------------------------------------------------------------------
+AsmReadMsrReturnResult PROC
+ mov eax, [esp + 8] ; QuarkMsrDataLow
+ mov ecx, [esp + 4] ; Index
+ mov edx, [esp + 12] ; QuarkMsrDataHigh
+ ret
+AsmReadMsrReturnResult ENDP
+
+;------------------------------------------------------------------------------
+; UINT64
+; EFIAPI
+; AsmReadMsrRealMsrAccess (
+; IN UINT32 Index
+; );
+;------------------------------------------------------------------------------
+AsmReadMsrRealMsrAccess PROC
+ mov ecx, [esp + 4] ; Index
+ mov eax, 0FEE00900h
+ mov edx, 00000000h
+ cmp ecx, 01Bh ; EFI_MSR_IA32_APIC_BASE
+ je exitDone
+ rdmsr
+exitDone:
+ ret
+AsmReadMsrRealMsrAccess ENDP
+
+;------------------------------------------------------------------------------
+; UINT64
+; EFIAPI
+; AsmWriteMsrRealMsrAccess (
+; IN UINT32 Index,
+; IN UINT32 QuarkMsrDataLow,
+; IN UINT32 QuarkMsrDataHigh
+; );
+;------------------------------------------------------------------------------
+AsmWriteMsrRealMsrAccess PROC
+ mov eax, [esp + 8] ; QuarkMsrDataLow
+ mov ecx, [esp + 4] ; Index
+ mov edx, [esp + 12] ; QuarkMsrDataHigh
+ wrmsr
+ ret
+AsmWriteMsrRealMsrAccess ENDP
+
+ END
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/RShiftU64.S b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/RShiftU64.S
new file mode 100644
index 0000000..e0c8456
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/RShiftU64.S
@@ -0,0 +1,65 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# RShiftU64.S
+#
+# Abstract:
+#
+# 64-bit logical right shift function for IA-32
+#
+#------------------------------------------------------------------------------
+
+ .686:
+ .code:
+
+ASM_GLOBAL ASM_PFX(InternalMathRShiftU64)
+
+#------------------------------------------------------------------------------
+# UINT64
+# EFIAPI
+# InternalMathRShiftU64 (
+# IN UINT64 Operand,
+# IN UINTN Count
+# );
+#------------------------------------------------------------------------------
+ASM_PFX(InternalMathRShiftU64):
+ movb 12(%esp), %cl # cl <- Count
+ xorl %edx, %edx
+ movl 8(%esp), %eax
+ testb $32, %cl # Count >= 32?
+ jnz L0
+ movl %eax, %edx
+ movl 4(%esp), %eax
+L0:
+ shrdl %cl, %edx, %eax
+ shr %cl, %edx
+ ret
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/RShiftU64.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/RShiftU64.c
new file mode 100644
index 0000000..ec0f438
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/RShiftU64.c
@@ -0,0 +1,70 @@
+/** @file
+ 64-bit logical right shift function for IA-32
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+
+/**
+ Shifts a 64-bit integer right between 0 and 63 bits. This high bits
+ are filled with zeros. The shifted value is returned.
+
+ This function shifts the 64-bit value Operand to the right by Count bits. The
+ high Count bits are set to zero. The shifted value is returned.
+
+ @param Operand The 64-bit operand to shift right.
+ @param Count The number of bits to shift right.
+
+ @return Operand >> Count
+
+**/
+UINT64
+EFIAPI
+InternalMathRShiftU64 (
+ IN UINT64 Operand,
+ IN UINTN Count
+ )
+{
+ _asm {
+ mov cl, byte ptr [Count]
+ xor edx, edx
+ mov eax, dword ptr [Operand + 4]
+ test cl, 32
+ jnz dontMoveReg
+ mov edx, eax
+ mov eax, dword ptr [Operand + 0]
+dontMoveReg:
+ shrd eax, edx, cl
+ shr edx, cl
+ }
+}
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/WriteCr4.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/WriteCr4.c
new file mode 100644
index 0000000..5a9db77
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/Ia32/WriteCr4.c
@@ -0,0 +1,59 @@
+/** @file
+ AsmWriteCr4 function
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+/**
+ Writes a value to Control Register 4 (CR4).
+
+ Writes and returns a new value to CR4. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Value The value to write to CR4.
+
+ @return The value written to CR4.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr4 (
+ UINTN Value
+ )
+{
+ _asm {
+ mov eax, Value
+ and eax, 0FFFFF9F7h // Mask bits not supported by MinuteIA
+ _emit 0x0f // mov cr4, eax
+ _emit 0x22
+ _emit 0xE0
+ }
+}
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/QuarkMsr.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/QuarkMsr.c
new file mode 100644
index 0000000..8ac4216
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/QuarkMsr.c
@@ -0,0 +1,105 @@
+/** @file
+ TranslateMsrIndex function
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <QuarkNcSocId.h>
+#include "QuarkMsr.h"
+#include <MtrrLib.h>
+
+//
+// This table defines the offset, base and length of the fixed MTRRs
+//
+STATIC
+QUARK_MTRR_CONVERSION_TABLE QuarkMtrrConversionTable[] = {
+ {MTRR_LIB_IA32_MTRR_CAP, QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP},
+ {MTRR_LIB_IA32_MTRR_DEF_TYPE, QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE},
+ {MTRR_LIB_IA32_MTRR_FIX64K_00000, QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000},
+ {MTRR_LIB_IA32_MTRR_FIX16K_80000, QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000},
+ {MTRR_LIB_IA32_MTRR_FIX16K_A0000, QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_A0000},
+ {MTRR_LIB_IA32_MTRR_FIX4K_C0000, QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C0000},
+ {MTRR_LIB_IA32_MTRR_FIX4K_C8000, QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C8000},
+ {MTRR_LIB_IA32_MTRR_FIX4K_D0000, QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D0000},
+ {MTRR_LIB_IA32_MTRR_FIX4K_D8000, QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D8000},
+ {MTRR_LIB_IA32_MTRR_FIX4K_E0000, QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E0000},
+ {MTRR_LIB_IA32_MTRR_FIX4K_E8000, QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E8000},
+ {MTRR_LIB_IA32_MTRR_FIX4K_F0000, QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F0000},
+ {MTRR_LIB_IA32_MTRR_FIX4K_F8000, QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000},
+ {EFI_MSR_PENTIUM_SMRR_PHYS_BASE, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSBASE},
+ {EFI_MSR_PENTIUM_SMRR_PHYS_MASK, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK},
+ {MTRR_LIB_IA32_MTRR_PHYSBASE0, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0},
+ {MTRR_LIB_IA32_MTRR_PHYSMASK0, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK0},
+ {MTRR_LIB_IA32_MTRR_PHYSBASE1, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE1},
+ {MTRR_LIB_IA32_MTRR_PHYSMASK1, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK1},
+ {MTRR_LIB_IA32_MTRR_PHYSBASE2, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE2},
+ {MTRR_LIB_IA32_MTRR_PHYSMASK2, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK2},
+ {MTRR_LIB_IA32_MTRR_PHYSBASE3, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE3},
+ {MTRR_LIB_IA32_MTRR_PHYSMASK3, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK3},
+ {MTRR_LIB_IA32_MTRR_PHYSBASE4, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE4},
+ {MTRR_LIB_IA32_MTRR_PHYSMASK4, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK4},
+ {MTRR_LIB_IA32_MTRR_PHYSBASE5, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE5},
+ {MTRR_LIB_IA32_MTRR_PHYSMASK5, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK5},
+ {MTRR_LIB_IA32_MTRR_PHYSBASE6, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE6},
+ {MTRR_LIB_IA32_MTRR_PHYSMASK6, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK6},
+ {MTRR_LIB_IA32_MTRR_PHYSBASE7, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE7},
+ {MTRR_LIB_IA32_MTRR_PHYSMASK7, QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK7},
+ {0xFFFFFFFF, 0xFF}
+};
+
+
+/**
+ Translates an MSR to the Quark Host Bridge equivalent MSR register.
+
+ @param Index The 32-bit MSR index to translate.
+
+ @return The 8 bit translated MSR location in Host Bridge.
+
+**/
+UINT8
+EFIAPI
+TranslateMsrIndex (
+ IN UINT32 Index
+ )
+{
+ UINT8 QuarkMsrIndex = 0;
+ UINT8 MsrTableEntry = 0;
+
+ while(QuarkMtrrConversionTable[MsrTableEntry].StandardMsr != 0xFFFFFFFF) {
+ if (Index == QuarkMtrrConversionTable[MsrTableEntry].StandardMsr) {
+ QuarkMsrIndex = QuarkMtrrConversionTable[MsrTableEntry].QuarkMsr;
+ break;
+ }
+ MsrTableEntry++;
+ }
+
+ return(QuarkMsrIndex);
+}
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/QuarkMsr.h b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/QuarkMsr.h
new file mode 100644
index 0000000..300fa12
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/QuarkMsr.h
@@ -0,0 +1,142 @@
+/** @file
+ QuarkMsr header function
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+//
+// Structure to describe a fixed MTRR
+//
+typedef struct {
+ UINT32 StandardMsr;
+ UINT8 QuarkMsr;
+} QUARK_MTRR_CONVERSION_TABLE;
+
+/**
+ Read required data from QNC internal message network
+**/
+UINT32
+EFIAPI
+QNCPortRead(
+ UINT8 Port,
+ UINT8 RegAddress
+ );
+
+/**
+ Write prepared data into QNC internal message network.
+
+**/
+VOID
+EFIAPI
+QNCPortWrite (
+ UINT8 Port,
+ UINT8 RegAddress,
+ UINT32 WriteValue
+ );
+
+UINT8
+EFIAPI
+TranslateMsrIndex (
+ IN UINT32 Index
+ );
+
+/**
+ Loads the results of an MSR read operation into processor registers:
+ eax (QuarkMsrDataLow)
+ edx (QuarkMsrDataHigh)
+ ecx (Index)
+
+ @param Index The MSR index
+ @param QuarkMsrDataLow The low DWORD of the MSR read operation
+ @param QuarkMsrDataHigh The high DWORD of the MSR read operation
+
+ @return 64-bit MSR result
+
+**/
+UINT64
+EFIAPI
+AsmReadMsrReturnResult (
+ IN UINT32 Index,
+ IN UINT32 QuarkMsrDataLow,
+ IN UINT32 QuarkMsrDataHigh
+ );
+
+/**
+ Performs an MSR read operation
+
+ @param Index The MSR index
+
+ @return 64-bit MSR result
+
+**/
+UINT64
+EFIAPI
+AsmReadMsrRealMsrAccess (
+ IN UINT32 Index
+ );
+
+/**
+ Performs an MSR write operation
+
+ @param Index The MSR index
+ @param QuarkMsrDataLow The low DWORD of the MSR write operation
+ @param QuarkMsrDataHigh The high DWORD of the MSR write operation
+
+**/
+UINT64
+EFIAPI
+AsmWriteMsrRealMsrAccess (
+ IN UINT32 Index,
+ IN UINT32 QuarkMsrDataLow,
+ IN UINT32 QuarkMsrDataHigh
+ );
+
+#define EFI_MSR_IA32_APIC_BASE 0x1B
+#define EFI_MSR_PENTIUM_SMRR_PHYS_BASE 0xA0
+#define EFI_MSR_PENTIUM_SMRR_PHYS_MASK 0xA1
+#define MTRR_LIB_IA32_MTRR_PHYSBASE0 0x200
+#define MTRR_LIB_IA32_MTRR_PHYSMASK0 0x201
+#define MTRR_LIB_IA32_MTRR_PHYSBASE1 0x202
+#define MTRR_LIB_IA32_MTRR_PHYSMASK1 0x203
+#define MTRR_LIB_IA32_MTRR_PHYSBASE2 0x204
+#define MTRR_LIB_IA32_MTRR_PHYSMASK2 0x205
+#define MTRR_LIB_IA32_MTRR_PHYSBASE3 0x206
+#define MTRR_LIB_IA32_MTRR_PHYSMASK3 0x207
+#define MTRR_LIB_IA32_MTRR_PHYSBASE4 0x208
+#define MTRR_LIB_IA32_MTRR_PHYSMASK4 0x209
+#define MTRR_LIB_IA32_MTRR_PHYSBASE5 0x20A
+#define MTRR_LIB_IA32_MTRR_PHYSMASK5 0x20B
+#define MTRR_LIB_IA32_MTRR_PHYSBASE6 0x20C
+#define MTRR_LIB_IA32_MTRR_PHYSMASK6 0x20D
+#define MTRR_LIB_IA32_MTRR_PHYSBASE7 0x20E
+#define MTRR_LIB_IA32_MTRR_PHYSMASK7 0x20F
+
+
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/ReadMsr64.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/ReadMsr64.c
new file mode 100644
index 0000000..e3b811f
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/ReadMsr64.c
@@ -0,0 +1,77 @@
+/** @file
+ AsmReadMsr64 function
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include <QuarkNcSocId.h>
+#include "QuarkMsr.h"
+
+
+/**
+ Returns a 64-bit Machine Specific Register(MSR).
+
+ Reads and returns the 64-bit MSR specified by Index. No parameter checking is
+ performed on Index, and some Index values may cause CPU exceptions. The
+ caller must either guarantee that Index is valid, or the caller must set up
+ exception handlers to catch the exceptions. This function is only available
+ on IA-32 and x64.
+
+ @param Index The 32-bit MSR index to read.
+
+ @return The value of the MSR identified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadMsr64 (
+ IN UINT32 Index
+ )
+{
+ UINT8 QuarkMsrIndex = 0;
+ UINT32 QuarkMsrDataLow = 0;
+ UINT32 QuarkMsrDataHigh = 0;
+ UINT64 QuarkMsrReturn = 0;
+
+ QuarkMsrIndex = TranslateMsrIndex (Index);
+ if((QuarkMsrIndex >= QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP) && (QuarkMsrIndex <= QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK7)) {
+ QuarkMsrDataLow = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QuarkMsrIndex);
+ if((QuarkMsrIndex >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000) && (QuarkMsrIndex <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
+ QuarkMsrDataHigh = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QuarkMsrIndex+1);
+ }
+ QuarkMsrReturn = AsmReadMsrReturnResult(Index, QuarkMsrDataLow, QuarkMsrDataHigh);
+ }
+ else {
+ QuarkMsrReturn = AsmReadMsrRealMsrAccess(Index);
+ }
+ return (QuarkMsrReturn);
+}
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseLib/WriteMsr64.c b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/WriteMsr64.c
new file mode 100644
index 0000000..6818eba
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseLib/WriteMsr64.c
@@ -0,0 +1,82 @@
+/** @file
+ AsmWriteMsr64 function
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include <QuarkNcSocId.h>
+#include "QuarkMsr.h"
+
+/**
+ Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
+ value.
+
+ Writes the 64-bit value specified by Value to the MSR specified by Index. The
+ 64-bit value written to the MSR is returned. No parameter checking is
+ performed on Index or Value, and some of these may cause CPU exceptions. The
+ caller must either guarantee that Index and Value are valid, or the caller
+ must establish proper exception handlers. This function is only available on
+ IA-32 and x64.
+
+ @param Index The 32-bit MSR index to write.
+ @param Value The 64-bit value to write to the MSR.
+
+ @return Value
+
+**/
+UINT64
+EFIAPI
+AsmWriteMsr64 (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ UINT8 QuarkMsrIndex = 0;
+ UINT32 QuarkMsrDataLow = 0;
+ UINT32 QuarkMsrDataHigh = 0;
+ UINT64 QuarkMsrReturn = 0;
+
+ QuarkMsrIndex = TranslateMsrIndex (Index);
+ if((QuarkMsrIndex >= QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP) && (QuarkMsrIndex <= QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK7)) {
+ QuarkMsrDataLow = (Value & 0xFFFFFFFF);
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QuarkMsrIndex, QuarkMsrDataLow);
+ if((QuarkMsrIndex >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000) && (QuarkMsrIndex <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
+ QuarkMsrDataHigh = ((Value >> 32) & 0xFFFFFFFF);
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QuarkMsrIndex+1, QuarkMsrDataHigh);
+ }
+ QuarkMsrReturn = AsmReadMsrReturnResult(Index, QuarkMsrDataLow, QuarkMsrDataHigh);
+ }
+ else {
+ QuarkMsrReturn = AsmWriteMsrRealMsrAccess(Index, QuarkMsrDataLow, QuarkMsrDataHigh);
+ }
+ return (QuarkMsrReturn);
+}
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf b/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
new file mode 100644
index 0000000..77aa9d5
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
@@ -0,0 +1,118 @@
+## @file
+# Instance of Base Memory Library using REP string instructions.
+#
+# Base Memory Library that uses REP string instructions for
+# high performance and small size. Optimized for use in PEI.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseMemoryLibRepStr
+ FILE_GUID = e7884bf4-51a1-485b-982a-ff89129983bc
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BaseMemoryLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c
+
+[Sources.Ia32]
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.S
+ Ia32/ScanMem8.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.asm
+ Ia32/ScanMem8.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.asm
+
+[Sources.X64]
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.S
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.asm
+ ../../../../../MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.asm
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ BaseLib
+
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.S b/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.S
new file mode 100644
index 0000000..b485266
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.S
@@ -0,0 +1,73 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# ScanMem8.Asm
+#
+# Abstract:
+#
+# ScanMem8 function
+#
+# Notes:
+#
+# The following BaseMemoryLib instances contain the same copy of this file:
+#
+# BaseMemoryLibRepStr
+# BaseMemoryLibMmx
+# BaseMemoryLibSse2
+# BaseMemoryLibOptDxe
+# BaseMemoryLibOptPei
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(InternalMemScanMem8)
+
+#------------------------------------------------------------------------------
+# CONST VOID *
+# EFIAPI
+# InternalMemScanMem8 (
+# IN CONST VOID *Buffer,
+# IN UINTN Length,
+# IN UINT8 Value
+# );
+#------------------------------------------------------------------------------
+ASM_PFX(InternalMemScanMem8):
+ push %edi
+ movl 12(%esp), %ecx
+ movl 8(%esp), %edi
+ movb 16(%esp), %al
+ repne scasb
+ leal -1(%edi), %eax
+ jz L0
+ movl %ecx, %eax
+L0:
+ pop %edi
+ ret
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.asm b/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.asm
new file mode 100644
index 0000000..bd61602
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.asm
@@ -0,0 +1,76 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013 Intel Corporation.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; Module Name:
+;
+; ScanMem8.Asm
+;
+; Abstract:
+;
+; ScanMem8 function
+;
+; Notes:
+;
+; The following BaseMemoryLib instances contain the same copy of this file:
+;
+; BaseMemoryLibRepStr
+; BaseMemoryLibMmx
+; BaseMemoryLibSse2
+; BaseMemoryLibOptDxe
+; BaseMemoryLibOptPei
+;
+;------------------------------------------------------------------------------
+
+ .686
+ .model flat,C
+ .code
+
+;------------------------------------------------------------------------------
+; CONST VOID *
+; EFIAPI
+; InternalMemScanMem8 (
+; IN CONST VOID *Buffer,
+; IN UINTN Length,
+; IN UINT8 Value
+; );
+;------------------------------------------------------------------------------
+InternalMemScanMem8 PROC USES edi
+ mov ecx, [esp + 12]
+ mov edi, [esp + 8]
+ mov al, [esp + 16]
+ repne scasb
+ lea eax, [edi - 1]
+ jz L0
+ mov eax, ecx
+L0:
+ ret
+InternalMemScanMem8 ENDP
+
+ END
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.c b/QuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.c
new file mode 100755
index 0000000..8405db6
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.c
@@ -0,0 +1,55 @@
+/** @file
+ This file includes the function that can be customized by OEM.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+/**
+ This function allows the user to force a system recovery
+
+**/
+VOID
+EFIAPI
+OemInitiateRecovery (
+ VOID
+ );
+
+/**
+ This function allows the user to force a system recovery
+
+**/
+VOID
+EFIAPI
+OemInitiateRecovery (
+ VOID
+ )
+{
+
+}
diff --git a/QuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.inf b/QuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.inf
new file mode 100755
index 0000000..db0b501
--- /dev/null
+++ b/QuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.inf
@@ -0,0 +1,62 @@
+## @file
+# Library Hook Point functions for recovery
+#
+# This library provides hook points for OEM w.r.t recovery
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RecoveryOemHookLib
+ FILE_GUID = 901AEEBB-1BE3-42A7-A54B-D26C985AF0F6
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RecoveryOemHookLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ BaseRecoveryOemHookLibNull.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+
+[Ppis]
+
diff --git a/QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
new file mode 100644
index 0000000..e1b16b0
--- /dev/null
+++ b/QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
@@ -0,0 +1,1717 @@
+/** @file
+ MTRR setting library
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Base.h>
+
+#include <Library/MtrrLib.h>
+#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+//
+// Context to save and restore when MTRRs are programmed
+//
+typedef struct {
+ UINTN Cr4;
+ BOOLEAN InterruptState;
+} MTRR_CONTEXT;
+
+//
+// This table defines the offset, base and length of the fixed MTRRs
+//
+CONST FIXED_MTRR mMtrrLibFixedMtrrTable[] = {
+ {
+ MTRR_LIB_IA32_MTRR_FIX64K_00000,
+ 0,
+ SIZE_64KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_80000,
+ 0x80000,
+ SIZE_16KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_A0000,
+ 0xA0000,
+ SIZE_16KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C0000,
+ 0xC0000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C8000,
+ 0xC8000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D0000,
+ 0xD0000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D8000,
+ 0xD8000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E0000,
+ 0xE0000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E8000,
+ 0xE8000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F0000,
+ 0xF0000,
+ SIZE_4KB
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F8000,
+ 0xF8000,
+ SIZE_4KB
+ },
+};
+
+//
+// Lookup table used to print MTRRs
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mMtrrMemoryCacheTypeShortName[] = {
+ "UC", // CacheUncacheable
+ "WC", // CacheWriteCombining
+ "R*", // Invalid
+ "R*", // Invalid
+ "WT", // CacheWriteThrough
+ "WP", // CacheWriteProtected
+ "WB", // CacheWriteBack
+ "R*" // Invalid
+};
+
+/**
+ Returns the variable MTRR count for the CPU.
+
+ @return Variable MTRR count
+
+**/
+UINT32
+EFIAPI
+GetVariableMtrrCount (
+ VOID
+ )
+{
+ UINT32 VariableMtrrCount;
+
+ if (!IsMtrrSupported ()) {
+ return 0;
+ }
+
+ VariableMtrrCount = (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK);
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ return VariableMtrrCount;
+}
+
+/**
+ Returns the firmware usable variable MTRR count for the CPU.
+
+ @return Firmware usable variable MTRR count
+
+**/
+UINT32
+EFIAPI
+GetFirmwareVariableMtrrCount (
+ VOID
+ )
+{
+ UINT32 VariableMtrrCount;
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+ if (VariableMtrrCount < RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER) {
+ return 0;
+ }
+
+ return VariableMtrrCount - RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER;
+}
+
+/**
+ Returns the default MTRR cache type for the system.
+
+ @return The default MTRR cache type.
+
+**/
+MTRR_MEMORY_CACHE_TYPE
+EFIAPI
+MtrrGetDefaultMemoryType (
+ VOID
+ )
+{
+ if (!IsMtrrSupported ()) {
+ return CacheUncacheable;
+ }
+
+ return (MTRR_MEMORY_CACHE_TYPE) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE) & 0x7);
+}
+
+/**
+ Preparation before programming MTRR.
+
+ This function will do some preparation for programming MTRRs:
+ disable cache, invalid cache and disable MTRR caching functionality
+
+ @param[out] Pointer to context to save
+
+**/
+VOID
+PreMtrrChange (
+ OUT MTRR_CONTEXT *MtrrContext
+ )
+{
+ //
+ // Disable interrupts and save current interrupt state
+ //
+ MtrrContext->InterruptState = SaveAndDisableInterrupts();
+
+ //
+ // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
+ //
+ AsmDisableCache ();
+
+ //
+ // Save original CR4 value and clear PGE flag (Bit 7)
+ //
+ MtrrContext->Cr4 = AsmReadCr4 ();
+ AsmWriteCr4 (MtrrContext->Cr4 & (~BIT7));
+
+ //
+ // Flush all TLBs
+ //
+ CpuFlushTlb ();
+
+ //
+ // Disable Mtrrs
+ //
+ AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 0);
+}
+
+/**
+ Cleaning up after programming MTRRs.
+
+ This function will do some clean up after programming MTRRs:
+ Flush all TLBs, re-enable caching, restore CR4.
+
+ @param[in] Pointer to context to restore
+
+**/
+VOID
+PostMtrrChangeEnableCache (
+ IN MTRR_CONTEXT *MtrrContext
+ )
+{
+ //
+ // Flush all TLBs
+ //
+ CpuFlushTlb ();
+
+ //
+ // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
+ //
+ AsmEnableCache ();
+
+ //
+ // Restore original CR4 value
+ //
+ AsmWriteCr4 (MtrrContext->Cr4);
+
+ //
+ // Restore original interrupt state
+ //
+ SetInterruptState (MtrrContext->InterruptState);
+}
+
+/**
+ Cleaning up after programming MTRRs.
+
+ This function will do some clean up after programming MTRRs:
+ enable MTRR caching functionality, and enable cache
+
+ @param[in] Pointer to context to restore
+
+**/
+VOID
+PostMtrrChange (
+ IN MTRR_CONTEXT *MtrrContext
+ )
+{
+ //
+ // Enable Cache MTRR
+ //
+ AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 3);
+
+ PostMtrrChangeEnableCache (MtrrContext);
+}
+
+
+/**
+ Programs fixed MTRRs registers.
+
+ @param MemoryCacheType The memory type to set.
+ @param Base The base address of memory range.
+ @param Length The length of memory range.
+
+ @retval RETURN_SUCCESS The cache type was updated successfully
+ @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
+ for the fixed MTRRs.
+
+**/
+RETURN_STATUS
+ProgramFixedMtrr (
+ IN UINT64 MemoryCacheType,
+ IN OUT UINT64 *Base,
+ IN OUT UINT64 *Length
+ )
+{
+ UINT32 MsrNum;
+ UINT32 ByteShift;
+ UINT64 TempQword;
+ UINT64 OrMask;
+ UINT64 ClearMask;
+
+ TempQword = 0;
+ OrMask = 0;
+ ClearMask = 0;
+
+ for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {
+ if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&
+ (*Base <
+ (
+ mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +
+ (8 * mMtrrLibFixedMtrrTable[MsrNum].Length)
+ )
+ )
+ ) {
+ break;
+ }
+ }
+
+ if (MsrNum == MTRR_NUMBER_OF_FIXED_MTRR) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // We found the fixed MTRR to be programmed
+ //
+ for (ByteShift = 0; ByteShift < 8; ByteShift++) {
+ if (*Base ==
+ (
+ mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +
+ (ByteShift * mMtrrLibFixedMtrrTable[MsrNum].Length)
+ )
+ ) {
+ break;
+ }
+ }
+
+ if (ByteShift == 8) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ for (
+ ;
+ ((ByteShift < 8) && (*Length >= mMtrrLibFixedMtrrTable[MsrNum].Length));
+ ByteShift++
+ ) {
+ OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));
+ ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));
+ *Length -= mMtrrLibFixedMtrrTable[MsrNum].Length;
+ *Base += mMtrrLibFixedMtrrTable[MsrNum].Length;
+ }
+
+ if (ByteShift < 8 && (*Length != 0)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ TempQword =
+ (AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask;
+ AsmWriteMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr, TempQword);
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Get the attribute of variable MTRRs.
+
+ This function shadows the content of variable MTRRs into an
+ internal array: VariableMtrr.
+
+ @param MtrrValidBitsMask The mask for the valid bit of the MTRR
+ @param MtrrValidAddressMask The valid address mask for MTRR
+ @param VariableMtrr The array to shadow variable MTRRs content
+
+ @return The return value of this paramter indicates the
+ number of MTRRs which has been used.
+
+**/
+UINT32
+EFIAPI
+MtrrGetMemoryAttributeInVariableMtrr (
+ IN UINT64 MtrrValidBitsMask,
+ IN UINT64 MtrrValidAddressMask,
+ OUT VARIABLE_MTRR *VariableMtrr
+ )
+{
+ UINTN Index;
+ UINT32 MsrNum;
+ UINT32 UsedMtrr;
+ UINT32 FirmwareVariableMtrrCount;
+ UINT32 VariableMtrrEnd;
+
+ if (!IsMtrrSupported ()) {
+ return 0;
+ }
+
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
+ VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;
+
+ ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);
+ UsedMtrr = 0;
+
+ for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;
+ (
+ (MsrNum < VariableMtrrEnd) &&
+ (Index < FirmwareVariableMtrrCount)
+ );
+ MsrNum += 2
+ ) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {
+ VariableMtrr[Index].Msr = MsrNum;
+ VariableMtrr[Index].BaseAddress = (AsmReadMsr64 (MsrNum) &
+ MtrrValidAddressMask);
+ VariableMtrr[Index].Length = ((~(AsmReadMsr64 (MsrNum + 1) &
+ MtrrValidAddressMask)
+ ) &
+ MtrrValidBitsMask
+ ) + 1;
+ VariableMtrr[Index].Type = (AsmReadMsr64 (MsrNum) & 0x0ff);
+ VariableMtrr[Index].Valid = TRUE;
+ VariableMtrr[Index].Used = TRUE;
+ UsedMtrr = UsedMtrr + 1;
+ Index++;
+ }
+ }
+ return UsedMtrr;
+}
+
+
+/**
+ Checks overlap between given memory range and MTRRs.
+
+ @param Start The start address of memory range.
+ @param End The end address of memory range.
+ @param VariableMtrr The array to shadow variable MTRRs content
+
+ @retval TRUE Overlap exists.
+ @retval FALSE No overlap.
+
+**/
+BOOLEAN
+CheckMemoryAttributeOverlap (
+ IN PHYSICAL_ADDRESS Start,
+ IN PHYSICAL_ADDRESS End,
+ IN VARIABLE_MTRR *VariableMtrr
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < 6; Index++) {
+ if (
+ VariableMtrr[Index].Valid &&
+ !(
+ (Start > (VariableMtrr[Index].BaseAddress +
+ VariableMtrr[Index].Length - 1)
+ ) ||
+ (End < VariableMtrr[Index].BaseAddress)
+ )
+ ) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Marks a variable MTRR as non-valid.
+
+ @param Index The index of the array VariableMtrr to be invalidated
+ @param VariableMtrr The array to shadow variable MTRRs content
+ @param UsedMtrr The number of MTRRs which has already been used
+
+**/
+VOID
+InvalidateShadowMtrr (
+ IN UINTN Index,
+ IN VARIABLE_MTRR *VariableMtrr,
+ OUT UINT32 *UsedMtrr
+ )
+{
+ VariableMtrr[Index].Valid = FALSE;
+ *UsedMtrr = *UsedMtrr - 1;
+}
+
+
+/**
+ Combine memory attributes.
+
+ If overlap exists between given memory range and MTRRs, try to combine them.
+
+ @param Attributes The memory type to set.
+ @param Base The base address of memory range.
+ @param Length The length of memory range.
+ @param VariableMtrr The array to shadow variable MTRRs content
+ @param UsedMtrr The number of MTRRs which has already been used
+ @param OverwriteExistingMtrr Returns whether an existing MTRR was used
+
+ @retval EFI_SUCCESS Memory region successfully combined.
+ @retval EFI_ACCESS_DENIED Memory region cannot be combined.
+
+**/
+RETURN_STATUS
+CombineMemoryAttribute (
+ IN UINT64 Attributes,
+ IN OUT UINT64 *Base,
+ IN OUT UINT64 *Length,
+ IN VARIABLE_MTRR *VariableMtrr,
+ IN OUT UINT32 *UsedMtrr,
+ OUT BOOLEAN *OverwriteExistingMtrr
+ )
+{
+ UINT32 Index;
+ UINT64 CombineStart;
+ UINT64 CombineEnd;
+ UINT64 MtrrEnd;
+ UINT64 EndAddress;
+ UINT32 FirmwareVariableMtrrCount;
+ BOOLEAN CoveredByExistingMtrr;
+
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
+
+ *OverwriteExistingMtrr = FALSE;
+ CoveredByExistingMtrr = FALSE;
+ EndAddress = *Base +*Length - 1;
+
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {
+
+ MtrrEnd = VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length - 1;
+ if (
+ !VariableMtrr[Index].Valid ||
+ (
+ *Base > (MtrrEnd) ||
+ (EndAddress < VariableMtrr[Index].BaseAddress)
+ )
+ ) {
+ continue;
+ }
+
+ //
+ // Combine same attribute MTRR range
+ //
+ if (Attributes == VariableMtrr[Index].Type) {
+ //
+ // if the Mtrr range contain the request range, set a flag, then continue to
+ // invalidate any MTRR of the same request range with higher priority cache type.
+ //
+ if (VariableMtrr[Index].BaseAddress <= *Base && MtrrEnd >= EndAddress) {
+ CoveredByExistingMtrr = TRUE;
+ continue;
+ }
+ //
+ // invalid this MTRR, and program the combine range
+ //
+ CombineStart =
+ (*Base) < VariableMtrr[Index].BaseAddress ?
+ (*Base) :
+ VariableMtrr[Index].BaseAddress;
+ CombineEnd = EndAddress > MtrrEnd ? EndAddress : MtrrEnd;
+
+ //
+ // Record the MTRR usage status in VariableMtrr array.
+ //
+ InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);
+ *Base = CombineStart;
+ *Length = CombineEnd - CombineStart + 1;
+ EndAddress = CombineEnd;
+ *OverwriteExistingMtrr = TRUE;
+ continue;
+ } else {
+ //
+ // The cache type is different, but the range is convered by one MTRR
+ //
+ if (VariableMtrr[Index].BaseAddress == *Base && MtrrEnd == EndAddress) {
+ InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);
+ continue;
+ }
+
+ }
+
+ if ((Attributes== MTRR_CACHE_WRITE_THROUGH &&
+ VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) ||
+ (Attributes == MTRR_CACHE_WRITE_BACK &&
+ VariableMtrr[Index].Type == MTRR_CACHE_WRITE_THROUGH) ||
+ (Attributes == MTRR_CACHE_UNCACHEABLE) ||
+ (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE)
+ ) {
+ *OverwriteExistingMtrr = TRUE;
+ continue;
+ }
+ //
+ // Other type memory overlap is invalid
+ //
+ return RETURN_ACCESS_DENIED;
+ }
+
+ if (CoveredByExistingMtrr) {
+ *Length = 0;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Calculate the maximum value which is a power of 2, but less the MemoryLength.
+
+ @param MemoryLength The number to pass in.
+ @return The maximum value which is align to power of 2 and less the MemoryLength
+
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+{
+ UINT64 Result;
+
+ if (RShiftU64 (MemoryLength, 32) != 0) {
+ Result = LShiftU64 (
+ (UINT64) GetPowerOfTwo32 (
+ (UINT32) RShiftU64 (MemoryLength, 32)
+ ),
+ 32
+ );
+ } else {
+ Result = (UINT64) GetPowerOfTwo32 ((UINT32) MemoryLength);
+ }
+
+ return Result;
+}
+
+
+/**
+ Determine the MTRR numbers used to program a memory range.
+
+ This function first checks the alignment of the base address. If the alignment of the base address <= Length,
+ cover the memory range (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and Length -= alignment.
+ Repeat the step until alignment > Length.
+
+ Then this function determines which direction of programming the variable MTRRs for the remaining length
+ will use fewer MTRRs.
+
+ @param BaseAddress Length of Memory to program MTRR
+ @param Length Length of Memory to program MTRR
+ @param MtrrNumber Pointer to the number of necessary MTRRs
+
+ @retval TRUE Positive direction is better.
+ FALSE Negtive direction is better.
+
+**/
+BOOLEAN
+GetMtrrNumberAndDirection (
+ IN UINT64 BaseAddress,
+ IN UINT64 Length,
+ IN UINTN *MtrrNumber
+ )
+{
+ UINT64 TempQword;
+ UINT64 Alignment;
+ UINT32 Positive;
+ UINT32 Subtractive;
+
+ *MtrrNumber = 0;
+
+ if (BaseAddress != 0) {
+ do {
+ //
+ // Calculate the alignment of the base address.
+ //
+ Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));
+
+ if (Alignment > Length) {
+ break;
+ }
+
+ (*MtrrNumber)++;
+ BaseAddress += Alignment;
+ Length -= Alignment;
+ } while (TRUE);
+
+ if (Length == 0) {
+ return TRUE;
+ }
+ }
+
+ TempQword = Length;
+ Positive = 0;
+ Subtractive = 0;
+
+ do {
+ TempQword -= Power2MaxMemory (TempQword);
+ Positive++;
+ } while (TempQword != 0);
+
+ TempQword = Power2MaxMemory (LShiftU64 (Length, 1)) - Length;
+ Subtractive++;
+ do {
+ TempQword -= Power2MaxMemory (TempQword);
+ Subtractive++;
+ } while (TempQword != 0);
+
+ if (Positive <= Subtractive) {
+ *MtrrNumber += Positive;
+ return TRUE;
+ } else {
+ *MtrrNumber += Subtractive;
+ return FALSE;
+ }
+}
+
+/**
+ Invalid variable MTRRs according to the value in the shadow array.
+
+ This function programs MTRRs according to the values specified
+ in the shadow array.
+
+ @param VariableMtrr The array to shadow variable MTRRs content
+
+**/
+VOID
+InvalidateMtrr (
+ IN VARIABLE_MTRR *VariableMtrr
+ )
+{
+ UINTN Index;
+ UINTN VariableMtrrCount;
+ MTRR_CONTEXT MtrrContext;
+
+ PreMtrrChange (&MtrrContext);
+ Index = 0;
+ VariableMtrrCount = GetVariableMtrrCount ();
+ while (Index < VariableMtrrCount) {
+ if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {
+ AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);
+ AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0);
+ VariableMtrr[Index].Used = FALSE;
+ }
+ Index ++;
+ }
+ PostMtrrChange (&MtrrContext);
+}
+
+
+/**
+ Programs variable MTRRs
+
+ This function programs variable MTRRs
+
+ @param MtrrNumber Index of MTRR to program.
+ @param BaseAddress Base address of memory region.
+ @param Length Length of memory region.
+ @param MemoryCacheType Memory type to set.
+ @param MtrrValidAddressMask The valid address mask for MTRR
+
+**/
+VOID
+ProgramVariableMtrr (
+ IN UINTN MtrrNumber,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 MemoryCacheType,
+ IN UINT64 MtrrValidAddressMask
+ )
+{
+ UINT64 TempQword;
+ MTRR_CONTEXT MtrrContext;
+
+ PreMtrrChange (&MtrrContext);
+
+ //
+ // MTRR Physical Base
+ //
+ TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType;
+ AsmWriteMsr64 ((UINT32) MtrrNumber, TempQword);
+
+ //
+ // MTRR Physical Mask
+ //
+ TempQword = ~(Length - 1);
+ AsmWriteMsr64 (
+ (UINT32) (MtrrNumber + 1),
+ (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED
+ );
+
+ PostMtrrChange (&MtrrContext);
+}
+
+
+/**
+ Convert the Memory attibute value to MTRR_MEMORY_CACHE_TYPE.
+
+ @param MtrrType MTRR memory type
+
+ @return The enum item in MTRR_MEMORY_CACHE_TYPE
+
+**/
+MTRR_MEMORY_CACHE_TYPE
+GetMemoryCacheTypeFromMtrrType (
+ IN UINT64 MtrrType
+ )
+{
+ switch (MtrrType) {
+ case MTRR_CACHE_UNCACHEABLE:
+ return CacheUncacheable;
+ case MTRR_CACHE_WRITE_COMBINING:
+ return CacheWriteCombining;
+ case MTRR_CACHE_WRITE_THROUGH:
+ return CacheWriteThrough;
+ case MTRR_CACHE_WRITE_PROTECTED:
+ return CacheWriteProtected;
+ case MTRR_CACHE_WRITE_BACK:
+ return CacheWriteBack;
+ default:
+ //
+ // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
+ // no mtrr covers the range
+ //
+ return CacheUncacheable;
+ }
+}
+
+/**
+ Initializes the valid bits mask and valid address mask for MTRRs.
+
+ This function initializes the valid bits mask and valid address mask for MTRRs.
+
+ @param MtrrValidBitsMask The mask for the valid bit of the MTRR
+ @param MtrrValidAddressMask The valid address mask for the MTRR
+
+**/
+VOID
+MtrrLibInitializeMtrrMask (
+ OUT UINT64 *MtrrValidBitsMask,
+ OUT UINT64 *MtrrValidAddressMask
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+
+ PhysicalAddressBits = (UINT8) RegEax;
+
+ *MtrrValidBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
+ *MtrrValidAddressMask = *MtrrValidBitsMask & 0xfffffffffffff000ULL;
+ } else {
+ *MtrrValidBitsMask = MTRR_LIB_CACHE_VALID_ADDRESS;
+ *MtrrValidAddressMask = 0xFFFFFFFF;
+ }
+}
+
+
+/**
+ Determing the real attribute of a memory range.
+
+ This function is to arbitrate the real attribute of the memory when
+ there are 2 MTRR covers the same memory range. For further details,
+ please refer the IA32 Software Developer's Manual, Volume 3,
+ Section 10.11.4.1.
+
+ @param MtrrType1 the first kind of Memory type
+ @param MtrrType2 the second kind of memory type
+
+**/
+UINT64
+MtrrPrecedence (
+ UINT64 MtrrType1,
+ UINT64 MtrrType2
+ )
+{
+ UINT64 MtrrType;
+
+ MtrrType = MTRR_CACHE_INVALID_TYPE;
+ switch (MtrrType1) {
+ case MTRR_CACHE_UNCACHEABLE:
+ MtrrType = MTRR_CACHE_UNCACHEABLE;
+ break;
+ case MTRR_CACHE_WRITE_COMBINING:
+ if (
+ MtrrType2==MTRR_CACHE_WRITE_COMBINING ||
+ MtrrType2==MTRR_CACHE_UNCACHEABLE
+ ) {
+ MtrrType = MtrrType2;
+ }
+ break;
+ case MTRR_CACHE_WRITE_THROUGH:
+ if (
+ MtrrType2==MTRR_CACHE_WRITE_THROUGH ||
+ MtrrType2==MTRR_CACHE_WRITE_BACK
+ ) {
+ MtrrType = MTRR_CACHE_WRITE_THROUGH;
+ } else if(MtrrType2==MTRR_CACHE_UNCACHEABLE) {
+ MtrrType = MTRR_CACHE_UNCACHEABLE;
+ }
+ break;
+ case MTRR_CACHE_WRITE_PROTECTED:
+ if (MtrrType2 == MTRR_CACHE_WRITE_PROTECTED ||
+ MtrrType2 == MTRR_CACHE_UNCACHEABLE) {
+ MtrrType = MtrrType2;
+ }
+ break;
+ case MTRR_CACHE_WRITE_BACK:
+ if (
+ MtrrType2== MTRR_CACHE_UNCACHEABLE ||
+ MtrrType2==MTRR_CACHE_WRITE_THROUGH ||
+ MtrrType2== MTRR_CACHE_WRITE_BACK
+ ) {
+ MtrrType = MtrrType2;
+ }
+ break;
+ case MTRR_CACHE_INVALID_TYPE:
+ MtrrType = MtrrType2;
+ break;
+ default:
+ break;
+ }
+
+ if (MtrrType2 == MTRR_CACHE_INVALID_TYPE) {
+ MtrrType = MtrrType1;
+ }
+ return MtrrType;
+}
+
+
+/**
+ This function attempts to set the attributes for a memory range.
+
+ @param BaseAddress The physical address that is the start
+ address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the
+ memory region.
+
+ @retval RETURN_SUCCESS The attributes were set for the memory
+ region.
+ @retval RETURN_INVALID_PARAMETER Length is zero.
+ @retval RETURN_UNSUPPORTED The processor does not support one or
+ more bytes of the memory resource range
+ specified by BaseAddress and Length.
+ @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
+ for the memory resource range specified
+ by BaseAddress and Length.
+ @retval RETURN_ACCESS_DENIED The attributes for the memory resource
+ range specified by BaseAddress and Length
+ cannot be modified.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
+ modify the attributes of the memory
+ resource range.
+
+**/
+RETURN_STATUS
+EFIAPI
+MtrrSetMemoryAttribute (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN MTRR_MEMORY_CACHE_TYPE Attribute
+ )
+{
+ UINT64 TempQword;
+ RETURN_STATUS Status;
+ UINT64 MemoryType;
+ UINT64 Alignment;
+ BOOLEAN OverLap;
+ BOOLEAN Positive;
+ UINT32 MsrNum;
+ UINTN MtrrNumber;
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ UINT32 UsedMtrr;
+ UINT64 MtrrValidBitsMask;
+ UINT64 MtrrValidAddressMask;
+ BOOLEAN OverwriteExistingMtrr;
+ UINT32 FirmwareVariableMtrrCount;
+ UINT32 VariableMtrrEnd;
+ MTRR_CONTEXT MtrrContext;
+
+ DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));
+
+ if (!IsMtrrSupported ()) {
+ Status = RETURN_UNSUPPORTED;
+ goto Done;
+ }
+
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
+ VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;
+
+ MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);
+
+ TempQword = 0;
+ MemoryType = (UINT64)Attribute;
+ OverwriteExistingMtrr = FALSE;
+
+ //
+ // Check for an invalid parameter
+ //
+ if (Length == 0) {
+ Status = RETURN_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (
+ (BaseAddress & ~MtrrValidAddressMask) != 0 ||
+ (Length & ~MtrrValidAddressMask) != 0
+ ) {
+ Status = RETURN_UNSUPPORTED;
+ goto Done;
+ }
+
+ //
+ // Check if Fixed MTRR
+ //
+ Status = RETURN_SUCCESS;
+ while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {
+ PreMtrrChange (&MtrrContext);
+ Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);
+ PostMtrrChange (&MtrrContext);
+ if (RETURN_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ if (Length == 0) {
+ //
+ // A Length of 0 can only make sense for fixed MTTR ranges.
+ // Since we just handled the fixed MTRRs, we can skip the
+ // variable MTRR section.
+ //
+ goto Done;
+ }
+
+ //
+ // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
+ // we can set the base to 0 to save variable MTRRs.
+ //
+ if (BaseAddress == BASE_1MB) {
+ BaseAddress = 0;
+ Length += SIZE_1MB;
+ }
+
+ //
+ // Check for overlap
+ //
+ UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);
+ OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);
+ if (OverLap) {
+ Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);
+ if (RETURN_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Length == 0) {
+ //
+ // Combined successfully, invalidate the now-unused MTRRs
+ //
+ InvalidateMtrr(VariableMtrr);
+ Status = RETURN_SUCCESS;
+ goto Done;
+ }
+ }
+
+ //
+ // The memory type is the same with the type specified by
+ // MTRR_LIB_IA32_MTRR_DEF_TYPE.
+ //
+ if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryType ())) {
+ //
+ // Invalidate the now-unused MTRRs
+ //
+ InvalidateMtrr(VariableMtrr);
+ goto Done;
+ }
+
+ Positive = GetMtrrNumberAndDirection (BaseAddress, Length, &MtrrNumber);
+
+ if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {
+ Status = RETURN_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Invalidate the now-unused MTRRs
+ //
+ InvalidateMtrr(VariableMtrr);
+
+ //
+ // Find first unused MTRR
+ //
+ for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;
+ MsrNum < VariableMtrrEnd;
+ MsrNum += 2
+ ) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ break;
+ }
+ }
+
+ if (BaseAddress != 0) {
+ do {
+ //
+ // Calculate the alignment of the base address.
+ //
+ Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));
+
+ if (Alignment > Length) {
+ break;
+ }
+
+ //
+ // Find unused MTRR
+ //
+ for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ break;
+ }
+ }
+
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Alignment,
+ MemoryType,
+ MtrrValidAddressMask
+ );
+ BaseAddress += Alignment;
+ Length -= Alignment;
+ } while (TRUE);
+
+ if (Length == 0) {
+ goto Done;
+ }
+ }
+
+ TempQword = Length;
+
+ if (!Positive) {
+ Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
+
+ //
+ // Find unused MTRR
+ //
+ for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ break;
+ }
+ }
+
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ MemoryType,
+ MtrrValidAddressMask
+ );
+ BaseAddress += Length;
+ TempQword = Length - TempQword;
+ MemoryType = MTRR_CACHE_UNCACHEABLE;
+ }
+
+ do {
+ //
+ // Find unused MTRR
+ //
+ for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ break;
+ }
+ }
+
+ Length = Power2MaxMemory (TempQword);
+ if (!Positive) {
+ BaseAddress -= Length;
+ }
+
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ MemoryType,
+ MtrrValidAddressMask
+ );
+
+ if (Positive) {
+ BaseAddress += Length;
+ }
+ TempQword -= Length;
+
+ } while (TempQword > 0);
+
+Done:
+ DEBUG((DEBUG_CACHE, " Status = %r\n", Status));
+ if (!RETURN_ERROR (Status)) {
+ MtrrDebugPrintAllMtrrs ();
+ }
+
+ return Status;
+}
+
+
+/**
+ This function will get the memory cache type of the specific address.
+
+ This function is mainly for debug purpose.
+
+ @param Address The specific address
+
+ @return Memory cache type of the sepcific address
+
+**/
+MTRR_MEMORY_CACHE_TYPE
+EFIAPI
+MtrrGetMemoryAttribute (
+ IN PHYSICAL_ADDRESS Address
+ )
+{
+ UINT64 TempQword;
+ UINTN Index;
+ UINTN SubIndex;
+ UINT64 MtrrType;
+ UINT64 TempMtrrType;
+ MTRR_MEMORY_CACHE_TYPE CacheType;
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ UINT64 MtrrValidBitsMask;
+ UINT64 MtrrValidAddressMask;
+ UINTN VariableMtrrCount;
+
+ if (!IsMtrrSupported ()) {
+ return CacheUncacheable;
+ }
+
+ //
+ // Check if MTRR is enabled, if not, return UC as attribute
+ //
+ TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);
+ MtrrType = MTRR_CACHE_INVALID_TYPE;
+
+ if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
+ return CacheUncacheable;
+ }
+
+ //
+ // If address is less than 1M, then try to go through the fixed MTRR
+ //
+ if (Address < BASE_1MB) {
+ if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) {
+ //
+ // Go through the fixed MTRR
+ //
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&
+ Address < (
+ mMtrrLibFixedMtrrTable[Index].BaseAddress +
+ (mMtrrLibFixedMtrrTable[Index].Length * 8)
+ )
+ ) {
+ SubIndex =
+ ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /
+ mMtrrLibFixedMtrrTable[Index].Length;
+ TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
+ MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF;
+ return GetMemoryCacheTypeFromMtrrType (MtrrType);
+ }
+ }
+ }
+ }
+ MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);
+ MtrrGetMemoryAttributeInVariableMtrr(
+ MtrrValidBitsMask,
+ MtrrValidAddressMask,
+ VariableMtrr
+ );
+
+ //
+ // Go through the variable MTRR
+ //
+ VariableMtrrCount = GetVariableMtrrCount ();
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ if (VariableMtrr[Index].Valid) {
+ if (Address >= VariableMtrr[Index].BaseAddress &&
+ Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {
+ TempMtrrType = VariableMtrr[Index].Type;
+ MtrrType = MtrrPrecedence (MtrrType, TempMtrrType);
+ }
+ }
+ }
+ CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType);
+
+ return CacheType;
+}
+
+
+/**
+ This function will get the raw value in variable MTRRs
+
+ @param VariableSettings A buffer to hold variable MTRRs content.
+
+ @return The VariableSettings input pointer
+
+**/
+MTRR_VARIABLE_SETTINGS*
+EFIAPI
+MtrrGetVariableMtrr (
+ OUT MTRR_VARIABLE_SETTINGS *VariableSettings
+ )
+{
+ UINT32 Index;
+ UINT32 VariableMtrrCount;
+
+ if (!IsMtrrSupported ()) {
+ return VariableSettings;
+ }
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ VariableSettings->Mtrr[Index].Base =
+ AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));
+ VariableSettings->Mtrr[Index].Mask =
+ AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);
+ }
+
+ return VariableSettings;
+}
+
+
+/**
+ Worker function setting variable MTRRs
+
+ @param VariableSettings A buffer to hold variable MTRRs content.
+
+**/
+VOID
+MtrrSetVariableMtrrWorker (
+ IN MTRR_VARIABLE_SETTINGS *VariableSettings
+ )
+{
+ UINT32 Index;
+ UINT32 VariableMtrrCount;
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
+
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ AsmWriteMsr64 (
+ MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),
+ VariableSettings->Mtrr[Index].Base
+ );
+ AsmWriteMsr64 (
+ MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1,
+ VariableSettings->Mtrr[Index].Mask
+ );
+ }
+}
+
+
+/**
+ This function sets variable MTRRs
+
+ @param VariableSettings A buffer to hold variable MTRRs content.
+
+ @return The pointer of VariableSettings
+
+**/
+MTRR_VARIABLE_SETTINGS*
+EFIAPI
+MtrrSetVariableMtrr (
+ IN MTRR_VARIABLE_SETTINGS *VariableSettings
+ )
+{
+ MTRR_CONTEXT MtrrContext;
+
+ if (!IsMtrrSupported ()) {
+ return VariableSettings;
+ }
+
+ PreMtrrChange (&MtrrContext);
+ MtrrSetVariableMtrrWorker (VariableSettings);
+ PostMtrrChange (&MtrrContext);
+ return VariableSettings;
+}
+
+
+/**
+ This function gets the content in fixed MTRRs
+
+ @param FixedSettings A buffer to hold fixed Mtrrs content.
+
+ @retval The pointer of FixedSettings
+
+**/
+MTRR_FIXED_SETTINGS*
+EFIAPI
+MtrrGetFixedMtrr (
+ OUT MTRR_FIXED_SETTINGS *FixedSettings
+ )
+{
+ UINT32 Index;
+
+ if (!IsMtrrSupported ()) {
+ return FixedSettings;
+ }
+
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ FixedSettings->Mtrr[Index] =
+ AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
+ };
+
+ return FixedSettings;
+}
+
+/**
+ Worker function setting fixed MTRRs
+
+ @param FixedSettings A buffer to hold fixed Mtrrs content.
+
+**/
+VOID
+MtrrSetFixedMtrrWorker (
+ IN MTRR_FIXED_SETTINGS *FixedSettings
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ AsmWriteMsr64 (
+ mMtrrLibFixedMtrrTable[Index].Msr,
+ FixedSettings->Mtrr[Index]
+ );
+ }
+}
+
+
+/**
+ This function sets fixed MTRRs
+
+ @param FixedSettings A buffer to hold fixed Mtrrs content.
+
+ @retval The pointer of FixedSettings
+
+**/
+MTRR_FIXED_SETTINGS*
+EFIAPI
+MtrrSetFixedMtrr (
+ IN MTRR_FIXED_SETTINGS *FixedSettings
+ )
+{
+ MTRR_CONTEXT MtrrContext;
+
+ if (!IsMtrrSupported ()) {
+ return FixedSettings;
+ }
+
+ PreMtrrChange (&MtrrContext);
+ MtrrSetFixedMtrrWorker (FixedSettings);
+ PostMtrrChange (&MtrrContext);
+
+ return FixedSettings;
+}
+
+
+/**
+ This function gets the content in all MTRRs (variable and fixed)
+
+ @param MtrrSetting A buffer to hold all Mtrrs content.
+
+ @retval the pointer of MtrrSetting
+
+**/
+MTRR_SETTINGS *
+EFIAPI
+MtrrGetAllMtrrs (
+ OUT MTRR_SETTINGS *MtrrSetting
+ )
+{
+ if (!IsMtrrSupported ()) {
+ return MtrrSetting;
+ }
+
+ //
+ // Get fixed MTRRs
+ //
+ MtrrGetFixedMtrr (&MtrrSetting->Fixed);
+
+ //
+ // Get variable MTRRs
+ //
+ MtrrGetVariableMtrr (&MtrrSetting->Variables);
+
+ //
+ // Get MTRR_DEF_TYPE value
+ //
+ MtrrSetting->MtrrDefType = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);
+
+ return MtrrSetting;
+}
+
+
+/**
+ This function sets all MTRRs (variable and fixed)
+
+ @param MtrrSetting A buffer holding all MTRRs content.
+
+ @retval The pointer of MtrrSetting
+
+**/
+MTRR_SETTINGS *
+EFIAPI
+MtrrSetAllMtrrs (
+ IN MTRR_SETTINGS *MtrrSetting
+ )
+{
+ MTRR_CONTEXT MtrrContext;
+
+ if (!IsMtrrSupported ()) {
+ return MtrrSetting;
+ }
+
+ PreMtrrChange (&MtrrContext);
+
+ //
+ // Set fixed MTRRs
+ //
+ MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed);
+
+ //
+ // Set variable MTRRs
+ //
+ MtrrSetVariableMtrrWorker (&MtrrSetting->Variables);
+
+ //
+ // Set MTRR_DEF_TYPE value
+ //
+ AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType);
+
+ PostMtrrChangeEnableCache (&MtrrContext);
+
+ return MtrrSetting;
+}
+
+/**
+ This function prints all MTRRs for debugging.
+**/
+VOID
+EFIAPI
+MtrrDebugPrintAllMtrrs (
+ VOID
+ )
+{
+ DEBUG_CODE (
+ MTRR_SETTINGS MtrrSettings;
+ UINTN Index;
+ UINTN Index1;
+ UINTN VariableMtrrCount;
+ UINT64 Base;
+ UINT64 Limit;
+ UINT64 MtrrBase;
+ UINT64 MtrrLimit;
+ UINT64 RangeBase;
+ UINT64 RangeLimit;
+ UINT64 NoRangeBase;
+ UINT64 NoRangeLimit;
+ UINT32 RegEax;
+ UINTN MemoryType;
+ UINTN PreviousMemoryType;
+ BOOLEAN Found;
+
+ if (!IsMtrrSupported ()) {
+ return;
+ }
+
+ DEBUG((DEBUG_CACHE, "MTRR Settings\n"));
+ DEBUG((DEBUG_CACHE, "=============\n"));
+
+ MtrrGetAllMtrrs (&MtrrSettings);
+ DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", MtrrSettings.MtrrDefType));
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, MtrrSettings.Fixed.Mtrr[Index]));
+ }
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ DEBUG((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
+ Index,
+ MtrrSettings.Variables.Mtrr[Index].Base,
+ MtrrSettings.Variables.Mtrr[Index].Mask
+ ));
+ }
+ DEBUG((DEBUG_CACHE, "\n"));
+ DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));
+ DEBUG((DEBUG_CACHE, "====================================\n"));
+
+ Base = 0;
+ PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ Base = mMtrrLibFixedMtrrTable[Index].BaseAddress;
+ for (Index1 = 0; Index1 < 8; Index1++) {
+ MemoryType = (UINTN)(RShiftU64 (MtrrSettings.Fixed.Mtrr[Index], Index1 * 8) & 0xff);
+ if (MemoryType > CacheWriteBack) {
+ MemoryType = MTRR_CACHE_INVALID_TYPE;
+ }
+ if (MemoryType != PreviousMemoryType) {
+ if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
+ }
+ PreviousMemoryType = MemoryType;
+ DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));
+ }
+ Base += mMtrrLibFixedMtrrTable[Index].Length;
+ }
+ }
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
+
+ VariableMtrrCount = GetVariableMtrrCount ();
+
+ Base = BASE_1MB;
+ PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;
+ do {
+ MemoryType = MtrrGetMemoryAttribute (Base);
+ if (MemoryType > CacheWriteBack) {
+ MemoryType = MTRR_CACHE_INVALID_TYPE;
+ }
+
+ if (MemoryType != PreviousMemoryType) {
+ if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));
+ }
+ PreviousMemoryType = MemoryType;
+ DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));
+ }
+
+ RangeBase = BASE_1MB;
+ NoRangeBase = BASE_1MB;
+ Limit = BIT36 - 1;
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ Limit = LShiftU64 (1, RegEax & 0xff) - 1;
+ }
+ RangeLimit = Limit;
+ NoRangeLimit = Limit;
+
+ for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) {
+ if ((MtrrSettings.Variables.Mtrr[Index].Mask & BIT11) == 0) {
+ //
+ // If mask is not valid, then do not display range
+ //
+ continue;
+ }
+ MtrrBase = (MtrrSettings.Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1)));
+ MtrrLimit = MtrrBase + ((~(MtrrSettings.Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit);
+
+ if (Base >= MtrrBase && Base < MtrrLimit) {
+ Found = TRUE;
+ }
+
+ if (Base >= MtrrBase && MtrrBase > RangeBase) {
+ RangeBase = MtrrBase;
+ }
+ if (Base > MtrrLimit && MtrrLimit > RangeBase) {
+ RangeBase = MtrrLimit + 1;
+ }
+ if (Base < MtrrBase && MtrrBase < RangeLimit) {
+ RangeLimit = MtrrBase - 1;
+ }
+ if (Base < MtrrLimit && MtrrLimit <= RangeLimit) {
+ RangeLimit = MtrrLimit;
+ }
+
+ if (Base > MtrrLimit && NoRangeBase < MtrrLimit) {
+ NoRangeBase = MtrrLimit + 1;
+ }
+ if (Base < MtrrBase && NoRangeLimit > MtrrBase) {
+ NoRangeLimit = MtrrBase - 1;
+ }
+ }
+
+ if (Found) {
+ Base = RangeLimit + 1;
+ } else {
+ Base = NoRangeLimit + 1;
+ }
+ } while (Found);
+ DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1));
+ );
+}
+
+/**
+ Checks if MTRR is supported.
+
+ @retval TRUE MTRR is supported.
+ @retval FALSE MTRR is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+IsMtrrSupported (
+ VOID
+ )
+{
+ return TRUE;
+}
diff --git a/QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf b/QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
new file mode 100644
index 0000000..76e1932
--- /dev/null
+++ b/QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
@@ -0,0 +1,60 @@
+## @file
+# MTRR library provides API for MTRR operation
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MtrrLib
+ FILE_GUID = 6826b408-f4f3-47ee-917f-af7047f9d937
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MtrrLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ MtrrLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ BaseLib
+ CpuLib
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/IntelProprietaryLicense.txt b/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/IntelProprietaryLicense.txt
new file mode 100755
index 0000000..5e5918b
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/IntelProprietaryLicense.txt
@@ -0,0 +1,14 @@
+Intel Proprietary License
+
+Copyright (c) 2013, Intel Corporation. All rights reserved. Redistribution. Redistribution and use in binary form, without modification, are permitted provided that the following conditions are met:
+
+* Redistributions must reproduce the above copyright notice and the following disclaimer in the documentation and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its suppliers may be used to endorse or promote products derived from this software without specific prior written permission.
+* No reverse engineering, decompilation, or disassembly of this software is permitted.
+
+Limited patent license.
+Intel Corporation grants a world-wide, royalty-free, non-exclusive license under patents it now or hereafter owns or controls to make, have made, use, import, offer to sell and sell ("Utilize") this software, but solely to the extent that any such patent is necessary to Utilize the software alone, or in combination with an operating system licensed under an approved Open Source license as listed by the Open Source Initiative at http://opensource.org/licenses. The patent license shall not apply to any other combinations which include this software. No hardware per se is licensed hereunder.
+
+
+DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/QuarkMicrocode.inf b/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/QuarkMicrocode.inf
new file mode 100755
index 0000000..3449eb5
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/QuarkMicrocode.inf
@@ -0,0 +1,50 @@
+## @file
+# Chipset Microcode module inf file.
+#
+# Chipset Microcode module inf file, use PcdQuarkMicrocodeFile to find.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QuarkMicrocode
+ FILE_GUID = 2E1202AE-4B62-4856-9A75-2CF16DF2BAC5
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Binaries]
+ BIN|RMU.bin|*
diff --git a/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin b/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin
new file mode 100755
index 0000000..4e5c0db
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Binary/Quark2Microcode/RMU.bin
Binary files differ
diff --git a/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/IntelProprietaryLicense.txt b/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/IntelProprietaryLicense.txt
new file mode 100755
index 0000000..5e5918b
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/IntelProprietaryLicense.txt
@@ -0,0 +1,14 @@
+Intel Proprietary License
+
+Copyright (c) 2013, Intel Corporation. All rights reserved. Redistribution. Redistribution and use in binary form, without modification, are permitted provided that the following conditions are met:
+
+* Redistributions must reproduce the above copyright notice and the following disclaimer in the documentation and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its suppliers may be used to endorse or promote products derived from this software without specific prior written permission.
+* No reverse engineering, decompilation, or disassembly of this software is permitted.
+
+Limited patent license.
+Intel Corporation grants a world-wide, royalty-free, non-exclusive license under patents it now or hereafter owns or controls to make, have made, use, import, offer to sell and sell ("Utilize") this software, but solely to the extent that any such patent is necessary to Utilize the software alone, or in combination with an operating system licensed under an approved Open Source license as listed by the Open Source Initiative at http://opensource.org/licenses. The patent license shall not apply to any other combinations which include this software. No hardware per se is licensed hereunder.
+
+
+DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/QuarkMicrocode.inf b/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/QuarkMicrocode.inf
new file mode 100644
index 0000000..904f75c
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/QuarkMicrocode.inf
@@ -0,0 +1,50 @@
+## @file
+# Chipset Microcode module inf file.
+#
+# Chipset Microcode module inf file, use PcdQuarkMicrocodeFile to find.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QuarkMicrocode
+ FILE_GUID = D75EEA8B-23D2-4ed4-BC4F-5751D4A18DCF
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Binaries]
+ BIN|RMU.bin|*
diff --git a/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin b/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
new file mode 100644
index 0000000..769b138
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
Binary files differ
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/DdrMemoryController.h b/QuarkSocPkg/QuarkNorthCluster/Include/DdrMemoryController.h
new file mode 100644
index 0000000..be15602
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/DdrMemoryController.h
@@ -0,0 +1,275 @@
+/**@file
+ Memory controller configuration.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef __DDR_MEMORY_CONTROLLER_H__
+#define __DDR_MEMORY_CONTROLLER_H__
+
+//
+// DDR timing data definitions.
+// These are used to create bitmaps of valid timing configurations.
+//
+
+#define DUAL_CHANNEL_DDR_TIMING_DATA_FREQUENCY_UNKNOWN 0xFF
+#define DUAL_CHANNEL_DDR_TIMING_DATA_REFRESH_RATE_UNKNOWN 0xFF
+
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TCL_20 0x01
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TCL_25 0x00
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TCL_30 0x02
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TCL_ALL 0x03
+
+
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRCD_02 0x02
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRCD_03 0x01
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRCD_04 0x00
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRCD_ALL 0x03
+
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRP_02 0x02
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRP_03 0x01
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRP_04 0x00
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRP_ALL 0x03
+
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_05 0x05
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_06 0x04
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_07 0x03
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_08 0x02
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_09 0x01
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_10 0x00
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_ALL 0x07
+
+#define DUAL_CHANNEL_DDR_DATA_TYPE_REGISTERED 0x01
+#define DUAL_CHANNEL_DDR_DATA_TYPE_UNREGISTERED 0x02
+#define DUAL_CHANNEL_DDR_DATA_TYPE_BUFFERED 0x04
+#define DUAL_CHANNEL_DDR_DATA_TYPE_UNBUFFERED 0x08
+#define DUAL_CHANNEL_DDR_DATA_TYPE_SDR 0x10
+#define DUAL_CHANNEL_DDR_DATA_TYPE_DDR 0x20
+
+
+//
+// Maximum number of SDRAM channels supported by the memory controller
+//
+#define MAX_CHANNELS 1
+
+//
+// Maximum number of DIMM sockets supported by the memory controller
+//
+#define MAX_SOCKETS 1
+
+//
+// Maximum number of sides supported per DIMM
+//
+#define MAX_SIDES 2
+
+//
+// Maximum number of "Socket Sets", where a "Socket Set is a set of matching
+// DIMM's from the various channels
+//
+#define MAX_SOCKET_SETS 2
+
+//
+// Maximum number of rows supported by the memory controller
+//
+#define MAX_ROWS (MAX_SIDES * MAX_SOCKETS)
+
+//
+// Maximum number of memory ranges supported by the memory controller
+//
+#define MAX_RANGES (MAX_ROWS + 5)
+
+//
+// Maximum Number of Log entries
+//
+#define MEMORY_LOG_MAX_INDEX 16
+
+
+typedef struct _MEMORY_LOG_ENTRY {
+ EFI_STATUS_CODE_VALUE Event;
+ EFI_STATUS_CODE_TYPE Severity;
+ UINT8 Data;
+} MEMORY_LOG_ENTRY;
+
+typedef struct _MEMORY_LOG {
+ UINT8 Index;
+ MEMORY_LOG_ENTRY Entry[MEMORY_LOG_MAX_INDEX];
+} MEMORY_LOG;
+
+
+
+//
+// Defined ECC types
+//
+#define DUAL_CHANNEL_DDR_ECC_TYPE_NONE 0x01 // No error checking
+#define DUAL_CHANNEL_DDR_ECC_TYPE_EC 0x02 // Error checking only
+#define DUAL_CHANNEL_DDR_ECC_TYPE_SECC 0x04 // Software Scrubbing ECC
+#define DUAL_CHANNEL_DDR_ECC_TYPE_HECC 0x08 // Hardware Scrubbing ECC
+#define DUAL_CHANNEL_DDR_ECC_TYPE_CKECC 0x10 // Chip Kill ECC
+
+//
+// Row configuration status values
+//
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_SUCCESS 0x00 // No error
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_UNKNOWN 0x01 // Pattern mismatch, no memory
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_UNSUPPORTED 0x02 // Memory type not supported
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_ADDRESS_ERROR 0x03 // Row/Col/Bnk mismatch
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_ECC_ERROR 0x04 // Received ECC error
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_NOT_PRESENT 0x05 // Row is not present
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_DISABLED 0x06 // Row is disabled
+
+
+//
+// Memory range types
+//
+typedef enum {
+ DualChannelDdrMainMemory,
+ DualChannelDdrSmramCacheable,
+ DualChannelDdrSmramNonCacheable,
+ DualChannelDdrGraphicsMemoryCacheable,
+ DualChannelDdrGraphicsMemoryNonCacheable,
+ DualChannelDdrReservedMemory,
+ DualChannelDdrMaxMemoryRangeType
+} DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE;
+
+//
+// Memory map range information
+//
+typedef struct {
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ EFI_PHYSICAL_ADDRESS CpuAddress;
+ EFI_PHYSICAL_ADDRESS RangeLength;
+ DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE Type;
+} DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE;
+typedef struct {
+ unsigned dramType :1; /**< Type: 0 = RESERVED; 1 = DDR2 */
+ unsigned dramWidth :1; /**< Width: 0 = x8; 1 = x16 */
+ unsigned dramDensity :2; /**< Density: 00b = 2Gb; 01b = 1Gb; 10b = 512Mb; 11b = 256Mb */
+ unsigned dramSpeed :1; /**< Speed Grade: 0 = RESERVED; 1 = 800MT/s;*/
+ unsigned dramTimings :3; /**< Timings: 4-4-4, 5-5-5, 6-6-6 */
+ unsigned dramRanks :1; /**< Ranks: 0 = Single Rank; 1 = Dual Rank */
+} DramGeometry; /**< DRAM Geometry Descriptor */
+
+typedef union _RegDRP {
+ UINT32 raw;
+ struct {
+ unsigned rank0Enabled :1; /**< Rank 0 Enable */
+ unsigned rank0DevWidth :2; /**< DRAM Device Width (x8,x16) */
+ unsigned rank0DevDensity :2; /**< DRAM Device Density (256Mb,512Mb,1Gb,2Gb) */
+ unsigned reserved2 :1;
+ unsigned rank1Enabled :1; /**< Rank 1 Enable */
+ unsigned reserved3 :5;
+ unsigned dramType :1; /**< DRAM Type (0=DDR2) */
+ unsigned reserved4 :5;
+ unsigned reserved5 :14;
+ } field;
+} RegDRP; /**< DRAM Rank Population and Interface Register */
+
+
+typedef union {
+ UINT32 raw;
+ struct {
+ unsigned dramFrequency :3; /**< DRAM Frequency (000=RESERVED,010=667,011=800) */
+ unsigned tRP :2; /**< Precharge to Activate Delay (3,4,5,6) */
+ unsigned reserved1 :1;
+ unsigned tRCD :2; /**< Activate to CAS Delay (3,4,5,6) */
+ unsigned reserved2 :1;
+ unsigned tCL :2; /**< CAS Latency (3,4,5,6) */
+ unsigned reserved3 :21;
+ } field;
+} RegDTR0; /**< DRAM Timing Register 0 */
+
+typedef union {
+ UINT32 raw;
+ struct {
+ unsigned tWRRD_dly :2; /**< Additional Write to Read Delay (0,1,2,3) */
+ unsigned reserved1 :1;
+ unsigned tRDWR_dly :2; /**< Additional Read to Write Delay (0,1,2,3) */
+ unsigned reserved2 :1;
+ unsigned tRDRD_dr_dly :1; /**< Additional Read to Read Delay (1,2) */
+ unsigned reserved3 :1;
+ unsigned tRD_dly :3; /**< Additional Read Data Sampling Delay (0-7) */
+ unsigned reserved4 :1;
+ unsigned tRCVEN_halfclk_dly :4; /**< Additional RCVEN Half Clock Delay Control */
+ unsigned reserved5 :1;
+ unsigned readDqDelay :2; /**< Read DQ Delay */
+ unsigned reserved6 :13;
+ } field;
+} RegDTR1; /**< DRAM Timing Register 1 */
+
+typedef union {
+ UINT32 raw;
+ struct {
+ unsigned ckStaticDisable :1; /**< CK/CK# Static Disable */
+ unsigned reserved1 :3;
+ unsigned ckeStaticDisable :2; /**< CKE Static Disable */
+ unsigned reserved2 :8;
+ unsigned refreshPeriod :2; /**< Refresh Period (disabled,128clks,3.9us,7.8us) */
+ unsigned refreshQueueDepth :2; /**< Refresh Queue Depth (1,2,4,8) */
+ unsigned reserved5 :13;
+ unsigned initComplete :1; /**< Initialization Complete */
+ } field;
+} RegDCO;
+
+//
+// MRC Data Structure
+//
+typedef struct {
+ RegDRP drp;
+ RegDTR0 dtr0;
+ RegDTR1 dtr1;
+ RegDCO dco;
+ UINT32 reg0104;
+ UINT32 reg0120;
+ UINT32 reg0121;
+ UINT32 reg0123;
+ UINT32 reg0111;
+ UINT32 reg0130;
+ UINT8 refreshPeriod; /**< Placeholder for the chosen refresh
+ * period. This value will NOT be
+ * programmed into DCO until all
+ * initialization is done.
+ */
+ UINT8 ddr2Odt; /**< 0 = Disabled, 1 = 75 ohm, 2 = 150ohm, 3 = 50ohm */
+ UINT8 sku; /**< Detected QuarkNcSocId SKU */
+ UINT8 capabilities; /**< Capabilities Available on this part */
+ UINT8 state; /**< NORMAL_BOOT, S3_RESUME */
+ UINT32 memSize; /**< Memory size */
+ UINT16 pmBase; /**< PM Base */
+ UINT16 mrcVersion; /**< MRC Version */
+ UINT32 hecbase; /**< HECBASE shifted left 16 bits */
+ DramGeometry geometry; /**< DRAM Geometry */
+} MRC_DATA_STRUCTURE; /**< QuarkNcSocId Memory Parameters for MRC */
+
+typedef struct _EFI_MEMINIT_CONFIG_DATA {
+ MRC_DATA_STRUCTURE MrcData;
+} EFI_MEMINIT_CONFIG_DATA;
+
+
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Guid/RedirectServicesHob.h b/QuarkSocPkg/QuarkNorthCluster/Include/Guid/RedirectServicesHob.h
new file mode 100644
index 0000000..1f71417
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Guid/RedirectServicesHob.h
@@ -0,0 +1,49 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ RedirectServicesHob.h
+
+Abstract:
+
+ GUID used for the redirect services hob in the HOB list.
+
+--*/
+
+#ifndef _REDIRECT_SERVICES_HOB_H_
+#define _REDIRECT_SERVICES_HOB_H_
+
+#define REDIRECT_SERVICES_HOB_GUID \
+ { 0x91f9a3af, 0x3df7, 0x4744, { 0x86, 0x13, 0x32, 0x79, 0x27, 0x7c, 0x35, 0x4a } }
+
+extern EFI_GUID gRedirectServicesHobGuid;
+
+#endif // _REDIRECT_SERVICES_HOB_H_
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCBase.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCBase.h
new file mode 100644
index 0000000..b613be6
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCBase.h
@@ -0,0 +1,41 @@
+/**@file
+ Public include file for the QNC Base
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __INTEL_QNC_BASE_H__
+#define __INTEL_QNC_BASE_H__
+
+#include <IntelQNCRegs.h>
+#include <IntelQNCConfig.h>
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCConfig.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCConfig.h
new file mode 100644
index 0000000..0034eb9
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCConfig.h
@@ -0,0 +1,124 @@
+/** @file
+ Some configuration of QNC Package
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __INTEL_QNC_CONFIG_H__
+#define __INTEL_QNC_CONFIG_H__
+
+//
+// QNC Fixed configurations.
+//
+
+//
+// Memory arbiter fixed config values.
+//
+#define QNC_FIXED_CONFIG_ASTATUS ((UINT32) (\
+ (ASTATUS_PRI_NORMAL << ASTATUS0_DEFAULT_BP) | \
+ (ASTATUS_PRI_NORMAL << ASTATUS1_DEFAULT_BP) | \
+ (ASTATUS_PRI_URGENT << ASTATUS0_RASISED_BP) | \
+ (ASTATUS_PRI_URGENT << ASTATUS1_RASISED_BP) \
+ ))
+
+//
+// Memory Manager fixed config values.
+//
+#define V_DRAM_NON_HOST_RQ_LIMIT 2
+
+//
+// RMU Thermal config fixed config values for TS in Vref Mode.
+//
+#define V_TSCGF1_CONFIG_ISNSCURRENTSEL_VREF_MODE 0x04
+#define V_TSCGF2_CONFIG2_ISPARECTRL_VREF_MODE 0x01
+#define V_TSCGF1_CONFIG_IBGEN_VREF_MODE 1
+#define V_TSCGF2_CONFIG_IDSCONTROL_VREF_MODE 0x011b
+#define V_TSCGF2_CONFIG2_ICALCOARSETUNE_VREF_MODE 0x34
+
+//
+// RMU Thermal config fixed config values for TS in Ratiometric mode.
+//
+#define V_TSCGF1_CONFIG_ISNSCURRENTSEL_RATIO_MODE 0x04
+#define V_TSCGF1_CONFIG_ISNSCHOPSEL_RATIO_MODE 0x02
+#define V_TSCGF1_CONFIG_ISNSINTERNALVREFEN_RATIO_MODE 1
+#define V_TSCGF2_CONFIG_IDSCONTROL_RATIO_MODE 0x011f
+#define V_TSCGF2_CONFIG_IDSTIMING_RATIO_MODE 0x0001
+#define V_TSCGF2_CONFIG2_ICALCONFIGSEL_RATIO_MODE 0x01
+#define V_TSCGF2_CONFIG2_ISPARECTRL_RATIO_MODE 0x00
+#define V_TSCGF1_CONFIG_IBGEN_RATIO_MODE 0
+#define V_TSCGF1_CONFIG_IBGCHOPEN_RATIO_MODE 0
+#define V_TSCGF3_CONFIG_ITSGAMMACOEFF_RATIO_MODE 0xC8
+#define V_TSCGF2_CONFIG2_ICALCOARSETUNE_RATIO_MODE 0x17
+
+//
+// iCLK fixed config values.
+//
+#define V_MUXTOP_FLEX2 3
+#define V_MUXTOP_FLEX1 1
+
+//
+// PCIe Root Port fixed config values.
+//
+#define V_PCIE_ROOT_PORT_SBIC_VALUE (B_QNC_PCIE_IOSFSBCTL_SBIC_IDLE_NEVER)
+
+//
+// QNC structures for configuration.
+//
+
+typedef union {
+ struct {
+ UINT32 PortErrorMask :8;
+ UINT32 SlotImplemented :1;
+ UINT32 Reserved1 :1;
+ UINT32 AspmEnable :1;
+ UINT32 AspmAutoEnable :1;
+ UINT32 AspmL0sEnable :2;
+ UINT32 AspmL1Enable :1;
+ UINT32 PmeInterruptEnable :1;
+ UINT32 PhysicalSlotNumber :13;
+ UINT32 Reserved2 :1;
+ UINT32 PmSciEnable :1;
+ UINT32 HotplugSciEnable :1;
+ } Bits;
+ UINT32 Uint32;
+} PCIEXP_ROOT_PORT_CONFIGURATION;
+
+typedef union {
+ UINT32 Uint32;
+ struct {
+ UINT32 Pcie_0 :1; // 0: Disabled; 1: Enabled*
+ UINT32 Pcie_1 :1; // 0: Disabled; 1: Enabled*
+ UINT32 Smbus :1; // 0: Disabled; 1: Enabled*
+ UINT32 Rsvd :29; // 0
+ } Bits;
+} QNC_DEVICE_ENABLES;
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCDxe.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCDxe.h
new file mode 100644
index 0000000..924946d
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCDxe.h
@@ -0,0 +1,41 @@
+/**@file
+ Public include file for the QNC Dxe
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __INTEL_QNC_DXE_H__
+#define __INTEL_QNC_DXE_H__
+
+#include <IntelQNCRegs.h>
+#include <IntelQNCConfig.h>
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCPeim.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCPeim.h
new file mode 100644
index 0000000..5bbd889
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCPeim.h
@@ -0,0 +1,41 @@
+/**@file
+ Public include file for the QNC Pei
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __INTEL_QNC_PEIM_H__
+#define __INTEL_QNC_PEIM_H__
+
+#include <IntelQNCRegs.h>
+#include <IntelQNCConfig.h>
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCRegs.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCRegs.h
new file mode 100644
index 0000000..16cdca1
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCRegs.h
@@ -0,0 +1,72 @@
+/** @file
+ Registers definition for Intel QuarkNcSocId.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __INTEL_QNC_REGS_H__
+#define __INTEL_QNC_REGS_H__
+
+#include <QNCAccess.h>
+
+//
+// PCI HostBridge Segment number
+//
+#define QNC_PCI_HOST_BRIDGE_SEGMENT_NUMBER 0
+
+//
+// PCI RootBridge resource allocation's attribute
+//
+#define QNC_PCI_ROOT_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTE \
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
+
+//
+// PCI HostBridge resource appeture
+//
+#define QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE 0x0
+#define QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT 0xff
+#define QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_TSEG_SIZE 0x10000000
+
+//
+// PCI RootBridge configure port
+//
+#define QNC_PCI_ROOT_BRIDGE_CONFIGURATION_ADDRESS_PORT 0xCF8
+#define QNC_PCI_ROOT_BRIDGE_CONFIGURATION_DATA_PORT 0xCFC
+
+//
+// PCI Rootbridge's support feature
+//
+#define QNC_PCI_ROOT_BRIDGE_SUPPORTED (EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | \
+ EFI_PCI_ATTRIBUTE_ISA_IO | \
+ EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | \
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
+ EFI_PCI_ATTRIBUTE_VGA_IO)
+
+#endif // __INTEL_QNC_REGS_H__
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Library/IntelQNCLib.h b/QuarkSocPkg/QuarkNorthCluster/Include/Library/IntelQNCLib.h
new file mode 100644
index 0000000..a6b3335
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Library/IntelQNCLib.h
@@ -0,0 +1,327 @@
+/** @file
+ Library that provides QNC specific library services in PEI phase
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __INTEL_QNC_LIB_H__
+#define __INTEL_QNC_LIB_H__
+
+
+/**
+ This function initializes the QNC register before MRC.
+ It sets RCBA, PMBASE, disable Watchdog timer and initialize QNC GPIO.
+ If the function cannot complete it'll ASSERT().
+**/
+VOID
+EFIAPI
+PeiQNCPreMemInit (
+ VOID
+ );
+
+
+/**
+ Used to check SCH if it's S3 state. Clear the register state after query.
+
+ @retval TRUE if it's S3 state.
+ @retval FALSE if it's not S3 state.
+
+**/
+BOOLEAN
+EFIAPI
+QNCCheckS3AndClearState (
+ VOID
+ );
+
+/**
+ Used to check SCH if system wakes up from power on reset. Clear the register state after query.
+
+ @retval TRUE if system wakes up from power on reset
+ @retval FALSE if system does not wake up from power on reset
+
+**/
+BOOLEAN
+EFIAPI
+QNCCheckPowerOnResetAndClearState (
+ VOID
+ );
+
+/**
+ This function is used to clear SMI and wake status.
+
+**/
+VOID
+EFIAPI
+QNCClearSmiAndWake (
+ VOID
+ );
+
+/**
+ Used to initialize the QNC register after MRC.
+
+**/
+VOID
+EFIAPI
+PeiQNCPostMemInit (
+ VOID
+ );
+
+/** Send DRAM Ready opcode.
+
+ @param[in] OpcodeParam Parameter to DRAM ready opcode.
+
+ @retval VOID
+**/
+VOID
+EFIAPI
+QNCSendOpcodeDramReady (
+ IN UINT32 OpcodeParam
+ );
+
+/**
+
+ Relocate RMU Main binary to memory after MRC to improve performance.
+
+ @param[in] DestBaseAddress - Specify the new memory address for the RMU Main binary.
+ @param[in] SrcBaseAddress - Specify the current memory address for the RMU Main binary.
+ @param[in] Size - Specify size of the RMU Main binary.
+
+ @retval VOID
+
+**/
+VOID
+EFIAPI
+RmuMainRelocation (
+ IN CONST UINT32 DestBaseAddress,
+ IN CONST UINT32 SrcBaseAddress,
+ IN CONST UINTN Size
+ );
+
+/**
+ Get the total memory size
+
+**/
+UINT32
+QNCGetTotalMemorysize (
+ VOID
+ );
+
+/**
+ Get the memory range of TSEG.
+ The TSEG's memory is below TOLM.
+
+ @param[out] BaseAddress The base address of TSEG's memory range
+ @param[out] MemorySize The size of TSEG's memory range
+
+**/
+VOID
+EFIAPI
+QNCGetTSEGMemoryRange (
+ OUT UINT64 *BaseAddress,
+ OUT UINT64 *MemorySize
+ );
+
+/**
+ This routine is the chipset code that accepts a request to "open" a region of SMRAM.
+ The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
+ The use of "open" means that the memory is visible from all boot-service
+ and SMM agents.
+
+ @retval FALSE Cannot open a locked SMRAM region
+ @retval TRUE Success to open SMRAM region.
+**/
+BOOLEAN
+EFIAPI
+QNCOpenSmramRegion (
+ VOID
+ );
+
+/**
+ This routine is the chipset code that accepts a request to "close" a region of SMRAM.
+ The region could be legacy AB or TSEG near top of physical memory.
+ The use of "close" means that the memory is only visible from SMM agents,
+ not from BS or RT code.
+
+ @retval FALSE Cannot open a locked SMRAM region
+ @retval TRUE Success to open SMRAM region.
+**/
+BOOLEAN
+EFIAPI
+QNCCloseSmramRegion (
+ VOID
+ );
+
+/**
+ This routine is the chipset code that accepts a request to "lock" SMRAM.
+ The region could be legacy AB or TSEG near top of physical memory.
+ The use of "lock" means that the memory can no longer be opened
+ to BS state.
+**/
+VOID
+EFIAPI
+QNCLockSmramRegion (
+ VOID
+ );
+
+/**
+ Updates the PAM registers in the MCH for the requested range and mode.
+
+ @param Start The start address of the memory region
+ @param Length The length, in bytes, of the memory region
+ @param ReadEnable Pointer to the boolean variable on whether to enable read for legacy memory section.
+ If NULL, then read attribute will not be touched by this call.
+ @param ReadEnable Pointer to the boolean variable on whether to enable write for legacy memory section.
+ If NULL, then write attribute will not be touched by this call.
+ @param Granularity A pointer to granularity, in bytes, that the PAM registers support
+
+ @retval RETURN_SUCCESS The PAM registers in the MCH were updated
+ @retval RETURN_INVALID_PARAMETER The memory range is not valid in legacy region.
+
+**/
+RETURN_STATUS
+EFIAPI
+QNCLegacyRegionManipulation (
+ IN UINT32 Start,
+ IN UINT32 Length,
+ IN BOOLEAN *ReadEnable,
+ IN BOOLEAN *WriteEnable,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Do early init of pci express rootports on Soc.
+
+**/
+VOID
+EFIAPI
+PciExpressEarlyInit (
+ VOID
+ );
+
+/**
+ Complete initialization of all the pci express rootports on Soc.
+**/
+EFI_STATUS
+EFIAPI
+PciExpressInit (
+ );
+
+/**
+ Determine if QNC is supported.
+
+ @retval FALSE QNC is not supported.
+ @retval TRUE QNC is supported.
+**/
+BOOLEAN
+IsQncSupported (
+ VOID
+ );
+
+/**
+ Enable SMI detection of legacy flash access violations.
+**/
+VOID
+EFIAPI
+QncEnableLegacyFlashAccessViolationSmi (
+ VOID
+ );
+
+/**
+ Setup RMU Thermal sensor registers for Vref mode.
+**/
+VOID
+EFIAPI
+QNCThermalSensorSetVRefMode (
+ VOID
+ );
+
+/**
+ Setup RMU Thermal sensor registers for Ratiometric mode.
+**/
+VOID
+EFIAPI
+QNCThermalSensorSetRatiometricMode (
+ VOID
+ );
+
+/**
+ Setup RMU Thermal sensor trip point values.
+
+ @param[in] CatastrophicTripOnDegreesCelsius - Catastrophic set trip point threshold.
+ @param[in] HotTripOnDegreesCelsius - Hot set trip point threshold.
+ @param[in] HotTripOffDegreesCelsius - Hot clear trip point threshold.
+
+ @retval VOID
+**/
+EFI_STATUS
+EFIAPI
+QNCThermalSensorSetTripValues (
+ IN CONST UINTN CatastrophicTripOnDegreesCelsius,
+ IN CONST UINTN HotTripOnDegreesCelsius,
+ IN CONST UINTN HotTripOffDegreesCelsius
+ );
+
+/**
+ Enable RMU Thermal sensor with a Catastrophic Trip point.
+
+ @retval EFI_SUCCESS Trip points setup.
+ @retval EFI_INVALID_PARAMETER Invalid trip point value.
+
+**/
+EFI_STATUS
+EFIAPI
+QNCThermalSensorEnableWithCatastrophicTrip (
+ IN CONST UINTN CatastrophicTripOnDegreesCelsius
+ );
+
+/**
+ Lock all RMU Thermal sensor control & trip point registers.
+
+**/
+VOID
+EFIAPI
+QNCThermalSensorLockAllRegisters (
+ VOID
+ );
+
+/**
+ Set chipset policy for double bit ECC error.
+
+ @param[in] PolicyValue Policy to config on double bit ECC error.
+
+**/
+VOID
+EFIAPI
+QNCPolicyDblEccBitErr (
+ IN CONST UINT32 PolicyValue
+ );
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCAccessLib.h b/QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCAccessLib.h
new file mode 100755
index 0000000..a8e552a
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCAccessLib.h
@@ -0,0 +1,179 @@
+/** @file
+ Library functions for Setting QNC internal network port
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __QNC_ACCESS_LIB_H__
+#define __QNC_ACCESS_LIB_H__
+
+#include <IntelQNCRegs.h>
+
+#define MESSAGE_READ_DW(Port, Reg) \
+ (UINT32)((QUARK_OPCODE_READ << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)
+
+#define MESSAGE_WRITE_DW(Port, Reg) \
+ (UINT32)((QUARK_OPCODE_WRITE << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)
+
+#define ALT_MESSAGE_READ_DW(Port, Reg) \
+ (UINT32)((QUARK_ALT_OPCODE_READ << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)
+
+#define ALT_MESSAGE_WRITE_DW(Port, Reg) \
+ (UINT32)((QUARK_ALT_OPCODE_WRITE << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)
+
+#define MESSAGE_IO_READ_DW(Port, Reg) \
+ (UINT32)((QUARK_OPCODE_IO_READ << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)
+
+#define MESSAGE_IO_WRITE_DW(Port, Reg) \
+ (UINT32)((QUARK_OPCODE_IO_WRITE << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)
+
+#define MESSAGE_SHADOW_DW(Port, Reg) \
+ (UINT32)((QUARK_DRAM_BASE_ADDR_READY << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)
+
+
+/**
+ Read required data from QNC internal message network
+**/
+UINT32
+EFIAPI
+QNCPortRead(
+ UINT8 Port,
+ UINT32 RegAddress
+ );
+
+/**
+ Write prepared data into QNC internal message network.
+
+**/
+VOID
+EFIAPI
+QNCPortWrite (
+ UINT8 Port,
+ UINT32 RegAddress,
+ UINT32 WriteValue
+ );
+
+/**
+ Read required data from QNC internal message network
+**/
+UINT32
+EFIAPI
+QNCAltPortRead(
+ UINT8 Port,
+ UINT32 RegAddress
+ );
+
+/**
+ Write prepared data into QNC internal message network.
+
+**/
+VOID
+EFIAPI
+QNCAltPortWrite (
+ UINT8 Port,
+ UINT32 RegAddress,
+ UINT32 WriteValue
+ );
+
+/**
+ Read required data from QNC internal message network
+**/
+UINT32
+EFIAPI
+QNCPortIORead(
+ UINT8 Port,
+ UINT32 RegAddress
+ );
+
+/**
+ Write prepared data into QNC internal message network.
+
+**/
+VOID
+EFIAPI
+QNCPortIOWrite (
+ UINT8 Port,
+ UINT32 RegAddress,
+ UINT32 WriteValue
+ );
+
+/**
+ This is for the special consideration for QNC MMIO write, as required by FWG,
+ a reading must be performed after MMIO writing to ensure the expected write
+ is processed and data is flushed into chipset
+
+**/
+EFI_STATUS
+EFIAPI
+QNCMmIoWrite (
+ UINT32 MmIoAddress,
+ QNC_MEM_IO_WIDTH Width,
+ UINT32 DataNumber,
+ VOID *pData
+ );
+
+VOID
+EFIAPI
+QncHsmmcWrite (
+ UINT32 WriteValue
+ );
+
+VOID
+EFIAPI
+QncImrWrite (
+ UINT32 ImrBaseOffset,
+ UINT32 ImrLow,
+ UINT32 ImrHigh,
+ UINT32 ImrReadMask,
+ UINT32 ImrWriteMask
+ );
+
+VOID
+EFIAPI
+QncIClkAndThenOr (
+ UINT32 RegAddress,
+ UINT32 AndValue,
+ UINT32 OrValue
+ );
+
+VOID
+EFIAPI
+QncIClkOr (
+ UINT32 RegAddress,
+ UINT32 OrValue
+ );
+
+UINTN
+EFIAPI
+QncGetPciExpressBaseAddress (
+ VOID
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Library/RedirectPeiServicesLib.h b/QuarkSocPkg/QuarkNorthCluster/Include/Library/RedirectPeiServicesLib.h
new file mode 100644
index 0000000..ffc5538
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Library/RedirectPeiServicesLib.h
@@ -0,0 +1,92 @@
+/** @file
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ RedirectPeiServicesLib.h
+
+Abstract:
+
+ Header file for RedirectPeiServicesLib.
+
+--*/
+
+#ifndef __REDIRECT_PEI_SERVICES_LIB_H__
+#define __REDIRECT_PEI_SERVICES_LIB_H__
+
+/**
+
+ Init RedirectedPeiServices Lib.
+
+**/
+VOID
+EFIAPI
+RedirectServicesInit (
+ VOID
+ );
+
+/**
+
+ Set memory pool to be used for redirected PEI memory alloc. services.
+
+ @param PoolBuffer Address of memory pool.
+ @param PoolBufferLength Length of memory pool.
+
+**/
+VOID
+EFIAPI
+RedirectMemoryServicesSetPool (
+ IN VOID *PoolBuffer,
+ IN CONST UINTN PoolBufferLength
+ );
+
+/**
+
+ Enable memory allocations from redirected memory pool.
+
+**/
+VOID
+EFIAPI
+RedirectMemoryServicesEnable (
+ VOID
+ );
+
+/**
+
+ Disable memory allocations from redirected memory pool.
+
+**/
+VOID
+EFIAPI
+RedirectMemoryServicesDisable (
+ VOID
+ );
+
+#endif // #ifndef __REDIRECT_PEI_SERVICES_LIB_H__
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Ppi/CltMemoryInit.h b/QuarkSocPkg/QuarkNorthCluster/Include/Ppi/CltMemoryInit.h
new file mode 100644
index 0000000..2e2caab
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Ppi/CltMemoryInit.h
@@ -0,0 +1,83 @@
+/**@file
+ Memory Initialization PPI used in EFI PEI interface
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __CLT_MEMORY_INIT_H__
+#define __CLT_MEMORY_INIT_H__
+
+#include "mrc.h"
+
+#define PEI_CLT_MEMORY_INIT_PPI_GUID \
+ {0x21ff1fee, 0xd33a, 0x4fce, {0xa6, 0x5e, 0x95, 0x5e, 0xa3, 0xc4, 0x1f, 0x40}}
+
+
+
+//
+// Memory range types
+//
+typedef enum {
+ DualChannelDdrMainMemory,
+ DualChannelDdrSmramCacheable,
+ DualChannelDdrSmramNonCacheable,
+ DualChannelDdrGraphicsMemoryCacheable,
+ DualChannelDdrGraphicsMemoryNonCacheable,
+ DualChannelDdrReservedMemory,
+ DualChannelDdrMaxMemoryRangeType
+} PEI_DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE;
+
+//
+// Memory map range information
+//
+typedef struct {
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ EFI_PHYSICAL_ADDRESS CpuAddress;
+ EFI_PHYSICAL_ADDRESS RangeLength;
+ PEI_DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE Type;
+} PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE;
+
+
+//
+// PPI Function Declarations
+//
+typedef
+VOID
+(EFIAPI *PEI_CLT_MEMORY_INIT) (
+ IN OUT MRCParams_t *MRCDATA
+ );
+
+typedef struct _PEI_CLT_MEMORY_INIT_PPI {
+ PEI_CLT_MEMORY_INIT MrcStart;
+}PEI_CLT_MEMORY_INIT_PPI;
+
+extern EFI_GUID gCltMemoryInitPpiGuid;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchInfo.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchInfo.h
new file mode 100755
index 0000000..f1df03e
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchInfo.h
@@ -0,0 +1,79 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PchInfo.h
+
+Abstract:
+
+ This file defines the QNC Info Protocol.
+
+--*/
+#ifndef _PCH_INFO_H_
+#define _PCH_INFO_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gEfiQncInfoProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _EFI_QNC_INFO_PROTOCOL EFI_QNC_INFO_PROTOCOL;
+
+//
+// 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: Original version
+// Revision 2: Add RCVersion item to EFI_QNC_INFO_PROTOCOL
+//
+#define QNC_INFO_PROTOCOL_REVISION_1 1
+#define QNC_INFO_PROTOCOL_REVISION_2 2
+
+//
+// RCVersion[7:0] is the release number.
+//
+#define QNC_RC_VERSION 0x01020000
+
+//
+// Protocol definition
+//
+struct _EFI_QNC_INFO_PROTOCOL {
+ UINT8 Revision;
+ UINT8 BusNumber;
+ UINT32 RCVersion;
+};
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchPlatformPolicy.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchPlatformPolicy.h
new file mode 100755
index 0000000..2e2d23d
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchPlatformPolicy.h
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PchPlatformPolicy.h
+
+Abstract:
+
+ QNC policy protocol produced by a platform driver specifying various
+ expected QNC settings. This protocol is consumed by the QNC drivers.
+
+--*/
+#ifndef _PCH_PLATFORM_POLICY_H_
+#define _PCH_PLATFORM_POLICY_H_
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _DXE_QNC_PLATFORM_POLICY_PROTOCOL DXE_QNC_PLATFORM_POLICY_PROTOCOL;
+
+//
+// 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: Original version
+
+#define DXE_QNC_PLATFORM_POLICY_PROTOCOL_REVISION_1 1
+
+//
+// ---------------------------- PCI Express Config ----------------------
+//
+// The values before AutoConfig match the setting of PCI Express Base Specification 1.1, please be careful for adding new feature
+//
+typedef enum {
+ QncPcieAspmDisabled,
+ QncPcieAspmL0s,
+ QncPcieAspmL1,
+ QncPcieAspmL0sL1,
+ QncPcieAspmAutoConfig,
+ QncPcieAspmMax
+} QNC_PCI_EXPRESS_ASPM_CONTROL;
+
+extern EFI_GUID gDxeQncPlatformPolicyProtocolGuid;
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PlatformPolicy.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PlatformPolicy.h
new file mode 100644
index 0000000..16fe4ce
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PlatformPolicy.h
@@ -0,0 +1,62 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ PlatformPolicy.h
+
+Abstract:
+
+ Protocol used for Platform Policy definition.
+
+--*/
+
+#ifndef _PLATFORM_POLICY_H_
+#define _PLATFORM_POLICY_H_
+
+typedef struct _EFI_PLATFORM_POLICY_PROTOCOL EFI_PLATFORM_POLICY_PROTOCOL;
+
+#define EFI_PLATFORM_POLICY_PROTOCOL_GUID \
+ { \
+ 0x2977064f, 0xab96, 0x4fa9, { 0x85, 0x45, 0xf9, 0xc4, 0x02, 0x51, 0xe0, 0x7f } \
+ }
+
+//
+// Protocol to describe various platform information. Add to this as needed.
+//
+struct _EFI_PLATFORM_POLICY_PROTOCOL {
+ UINT8 NumRsvdSmbusAddresses;
+ UINT8 *RsvdSmbusAddresses;
+};
+
+extern EFI_GUID gEfiPlatformPolicyProtocolGuid;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/QncS3Support.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/QncS3Support.h
new file mode 100644
index 0000000..66b14ae
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/QncS3Support.h
@@ -0,0 +1,115 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QncS3Support.h
+
+Abstract:
+
+ This file defines the QNC S3 support Protocol.
+
+--*/
+#ifndef _QNC_S3_SUPPORT_PROTOCOL_H_
+#define _QNC_S3_SUPPORT_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gEfiQncS3SupportProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _EFI_QNC_S3_SUPPORT_PROTOCOL EFI_QNC_S3_SUPPORT_PROTOCOL;
+
+typedef enum {
+ QncS3ItemTypeInitPcieRootPortDownstream,
+ QncS3ItemTypeMax
+} EFI_QNC_S3_DISPATCH_ITEM_TYPE;
+
+//
+// It's better not to use pointer here because the size of pointer in DXE is 8, but it's 4 in PEI
+// plug 4 to ParameterSize in PEIM if you really need it
+//
+typedef struct {
+ UINT32 Reserved;
+} EFI_QNC_S3_PARAMETER_INIT_PCIE_ROOT_PORT_DOWNSTREAM;
+
+typedef union {
+ EFI_QNC_S3_PARAMETER_INIT_PCIE_ROOT_PORT_DOWNSTREAM PcieRootPortData;
+} EFI_DISPATCH_CONTEXT_UNION;
+
+typedef struct {
+ EFI_QNC_S3_DISPATCH_ITEM_TYPE Type;
+ VOID *Parameter;
+} EFI_QNC_S3_DISPATCH_ITEM;
+
+//
+// Member functions
+//
+typedef
+EFI_STATUS
+(EFIAPI *EFI_QNC_S3_SUPPORT_SET_S3_DISPATCH_ITEM) (
+ IN EFI_QNC_S3_SUPPORT_PROTOCOL * This,
+ IN EFI_QNC_S3_DISPATCH_ITEM * DispatchItem,
+ OUT VOID **S3DispatchEntryPoint,
+ OUT VOID **Context
+ );
+
+/*++
+
+Routine Description:
+
+ Set an item to be dispatched at S3 resume time. At the same time, the entry point
+ of the QNC S3 support image is returned to be used in subsequent boot script save
+ call
+
+Arguments:
+
+ This - Pointer to the protocol instance.
+ DispatchItem - The item to be dispatched.
+ S3DispatchEntryPoint - The entry point of the QNC S3 support image.
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+
+//
+// Protocol definition
+//
+struct _EFI_QNC_S3_SUPPORT_PROTOCOL {
+ EFI_QNC_S3_SUPPORT_SET_S3_DISPATCH_ITEM SetDispatchItem;
+};
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmIchnDispatch2.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmIchnDispatch2.h
new file mode 100644
index 0000000..ee7ac72
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmIchnDispatch2.h
@@ -0,0 +1,139 @@
+/** @file
+ Intel-only SMM Child Dispatcher Protocol.
+
+ This protocol provides a parent dispatch service for a collection of
+ chipset-specific SMI source.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#ifndef __SMM_ICHN_DISPATCH2_H__
+#define __SMM_ICHN_DISPATCH2_H__
+
+//
+// Share some common definitions with Framework SMM
+//
+#include <Protocol/SmmIchnDispatch.h>
+
+#include <PiSmm.h>
+
+//
+// Global ID for the ICH SMI Protocol
+//
+#define EFI_SMM_ICHN_DISPATCH2_PROTOCOL_GUID \
+ { \
+ 0xadf3a128, 0x416d, 0x4060, {0x8d, 0xdf, 0x30, 0xa1, 0xd7, 0xaa, 0xb6, 0x99 } \
+ }
+
+typedef struct _EFI_SMM_ICHN_DISPATCH2_PROTOCOL EFI_SMM_ICHN_DISPATCH2_PROTOCOL;
+
+typedef struct {
+ EFI_SMM_ICHN_SMI_TYPE Type;
+} EFI_SMM_ICHN_REGISTER_CONTEXT;
+
+//
+// Member functions
+//
+/**
+ Register a child SMI source dispatch function with a parent SMM driver
+
+ @param This Protocol instance pointer.
+ @param DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the ICHN SMI source for which the dispatch
+ function should be invoked.
+ @param DispatchHandle Handle generated by the dispatcher to track the
+ function instance.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this
+ child.
+ @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The ICHN input value
+ is not within valid range.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SMM_ICHN_DISPATCH2_REGISTER) (
+ IN CONST EFI_SMM_ICHN_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN OUT EFI_SMM_ICHN_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param This Protocol instance pointer.
+ @param DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval other
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SMM_ICHN_DISPATCH2_UNREGISTER) (
+ IN EFI_SMM_ICHN_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+//
+// Interface structure for the SMM Ich n specific SMI Dispatch Protocol
+//
+/**
+ @par Protocol Description:
+ Provides a parent dispatch service for ICH SMI sources.
+
+ @param Register
+ Installs a child service to be dispatched by this protocol.
+
+ @param UnRegister
+ Removes a child service dispatched by this protocol.
+
+**/
+struct _EFI_SMM_ICHN_DISPATCH2_PROTOCOL {
+ EFI_SMM_ICHN_DISPATCH2_REGISTER Register;
+ EFI_SMM_ICHN_DISPATCH2_UNREGISTER UnRegister;
+};
+
+extern EFI_GUID gEfiSmmIchnDispatch2ProtocolGuid;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmRtProtocol.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmRtProtocol.h
new file mode 100644
index 0000000..ce8bb45
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmRtProtocol.h
@@ -0,0 +1,173 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmmRtProtocol.h
+
+Abstract:
+
+ This code abstracts SMM Runtime Protocol
+
+--*/
+
+#ifndef _SMM_RT_PROTOCOL_H_
+#define _SMM_RT_PROTOCOL_H_
+
+#include <Protocol/SmmBase2.h>
+
+#define EFI_SMM_RUNTIME_PROTOCOL_GUID \
+ { \
+ 0xa56897a1, 0xa77f, 0x4600, 0x84, 0xdb, 0x22, 0xb0, 0xa8, 0x1, 0xfa, 0x9a \
+ }
+
+typedef enum {
+ EfiSmmRtIdlePhase,
+ EfiSmmRtArgumentPhase,
+ EfiSmmDataFetchPhase,
+ EfiSmmCommandExecutePhase,
+ EfiSmmDataEmitPhase,
+ EfiSmmStatusPhase
+} EFI_SMM_RUNTIME_PHASE;
+
+typedef struct {
+ UINTN SimpleData[(2048 / 4)];
+} SMM_RUNTIME_UINTN_DATA;
+
+typedef struct {
+ UINTN SimpleData[2048];
+} SMM_RUNTIME_UINT8_DATA;
+
+typedef union {
+ SMM_RUNTIME_UINTN_DATA UintnData;
+ SMM_RUNTIME_UINT8_DATA Uint8Data;
+} SMM_RUNTIME_DATA;
+
+typedef struct {
+ EFI_SMM_RUNTIME_PHASE SmmRuntimePhase;
+ EFI_HANDLE SmmRuntimeCallHandle;
+ BOOLEAN ArgIsPointer;
+ UINT64 Argument;
+ SMM_RUNTIME_DATA Data;
+ UINTN TotalDataSize;
+ UINTN CurrentDataSize;
+} SMM_RUNTIME_COMMUNICATION_DATA;
+
+typedef struct {
+ EFI_GUID HeaderGuid;
+ UINTN MessageLength;
+ SMM_RUNTIME_COMMUNICATION_DATA PrivateData;
+} SMM_RUNTIME_COMMUNICATION_STRUCTURE;
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ENABLE_PROTOCOL_NOTIFY_EVENT) (
+ IN EFI_EVENT_NOTIFY CallbackFunction,
+ IN VOID *Context,
+ IN EFI_GUID * ProtocolGuid,
+ OUT EFI_EVENT * Event
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DISABLE_PROTOCOL_NOTIFY_EVENT) (
+ IN EFI_EVENT Event
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SMM_LOCATE_PROTOCOL_HANDLES) (
+ EFI_GUID * Protocol,
+ EFI_HANDLE **Handles,
+ UINTN *HandlesCount
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SMM_HANDLE_PROTOCOL) (
+ IN EFI_HANDLE Handle,
+ IN EFI_GUID * Protocol,
+ OUT VOID **Interface
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_VENDOR_CONFIG_TABLE) (
+ IN EFI_GUID * Guid,
+ OUT VOID **Table
+ );
+
+typedef
+VOID
+(EFIAPI *EFI_SMM_RUNTIME_CALLBACK) (
+ IN VOID *Context,
+ IN EFI_SMM_SYSTEM_TABLE2 * Smst,
+ IN VOID *ChildRuntimeBuffer
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REGISTER_SMM_RUNTIME_CHILD) (
+ IN EFI_SMM_RUNTIME_CALLBACK SmmRuntimeCallback,
+ IN VOID *Context,
+ OUT EFI_HANDLE * SmmRuntimeCallHandle
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UNREGISTER_SMM_RUNTIME_CHILD) (
+ IN EFI_SMM_RUNTIME_CALLBACK SmmRuntimeCallback
+ );
+
+//
+// SMM RUNTIME PROTOCOL
+//
+typedef struct {
+ EFI_LOCATE_PROTOCOL LocateProtocol;
+ EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface;
+ EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface;
+ EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface;
+ EFI_SIGNAL_EVENT SignalProtocol;
+ EFI_ENABLE_PROTOCOL_NOTIFY_EVENT EnableProtocolNotify;
+ EFI_DISABLE_PROTOCOL_NOTIFY_EVENT DisableProtocolNotify;
+ EFI_SMM_LOCATE_PROTOCOL_HANDLES LocateProtocolHandles;
+ EFI_SMM_HANDLE_PROTOCOL HandleProtocol;
+ EFI_INSTALL_CONFIGURATION_TABLE InstallVendorConfigTable;
+ EFI_GET_VENDOR_CONFIG_TABLE GetVendorConfigTable;
+ EFI_REGISTER_SMM_RUNTIME_CHILD RegisterSmmRuntimeChild;
+ EFI_UNREGISTER_SMM_RUNTIME_CHILD UnRegisterSmmRuntimeChild;
+ EFI_RUNTIME_SERVICES SmmRuntime;
+ SMM_RUNTIME_COMMUNICATION_STRUCTURE *ChildRuntimeBuffer;
+} EFI_SMM_RUNTIME_PROTOCOL;
+
+extern EFI_GUID gEfiSmmRuntimeProtocolGuid;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/Spi.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/Spi.h
new file mode 100644
index 0000000..7598a22
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/Spi.h
@@ -0,0 +1,376 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ Spi.h
+
+Abstract:
+
+ This file defines the EFI SPI Protocol which implements the
+ Intel(R) ICH SPI Host Controller Compatibility Interface.
+
+--*/
+#ifndef _SPI_H_
+#define _SPI_H_
+
+//
+// Define the SPI protocol GUID
+//
+// EDK and EDKII have different GUID formats
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define EFI_SPI_PROTOCOL_GUID \
+ { \
+ 0x1156efc6, 0xea32, 0x4396, 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 \
+ }
+#define EFI_SMM_SPI_PROTOCOL_GUID \
+ { \
+ 0xD9072C35, 0xEB8F, 0x43ad, 0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 \
+ }
+#else
+#define EFI_SPI_PROTOCOL_GUID \
+ { \
+ 0x1156efc6, 0xea32, 0x4396, \
+ { \
+ 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 \
+ } \
+ }
+#define EFI_SMM_SPI_PROTOCOL_GUID \
+ { \
+ 0xD9072C35, 0xEB8F, 0x43ad, \
+ { \
+ 0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 \
+ } \
+ }
+#endif
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gEfiSpiProtocolGuid;
+extern EFI_GUID gEfiSmmSpiProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _EFI_SPI_PROTOCOL EFI_SPI_PROTOCOL;
+
+//
+// SPI protocol data structures and definitions
+//
+//
+// Number of Prefix Opcodes allowed on the SPI interface
+//
+#define SPI_NUM_PREFIX_OPCODE 2
+
+//
+// Number of Opcodes in the Opcode Menu
+//
+#define SPI_NUM_OPCODE 8
+
+#ifdef SERVER_BIOS_FLAG
+//
+// SPI default opcode slots
+//
+#define SPI_OPCODE_JEDEC_ID_INDEX 0
+#endif // SERVER_BIOS_FLAG
+
+//
+// Opcode Type
+// EnumSpiOpcodeCommand: Command without address
+// EnumSpiOpcodeRead: Read with address
+// EnumSpiOpcodeWrite: Write with address
+//
+typedef enum {
+ EnumSpiOpcodeReadNoAddr,
+ EnumSpiOpcodeWriteNoAddr,
+ EnumSpiOpcodeRead,
+ EnumSpiOpcodeWrite,
+ EnumSpiOpcodeMax
+} SPI_OPCODE_TYPE;
+
+typedef enum {
+ EnumSpiCycle20MHz,
+ EnumSpiCycle33MHz,
+ EnumSpiCycle66MHz, // not supported by PCH
+ EnumSpiCycle50MHz,
+ EnumSpiCycleMax
+} SPI_CYCLE_FREQUENCY;
+
+typedef enum {
+ EnumSpiRegionAll,
+ EnumSpiRegionBios,
+ EnumSpiRegionMe,
+ EnumSpiRegionGbE,
+ EnumSpiRegionDescriptor,
+ EnumSpiRegionPlatformData,
+ EnumSpiRegionMax
+} SPI_REGION_TYPE;
+
+//
+// Hardware Sequencing required operations (as listed in CougarPoint EDS Table 5-55: "Hardware
+// Sequencing Commands and Opcode Requirements"
+//
+typedef enum {
+ EnumSpiOperationWriteStatus,
+ EnumSpiOperationProgramData_1_Byte,
+ EnumSpiOperationProgramData_64_Byte,
+ EnumSpiOperationReadData,
+ EnumSpiOperationWriteDisable,
+ EnumSpiOperationReadStatus,
+ EnumSpiOperationWriteEnable,
+ EnumSpiOperationFastRead,
+ EnumSpiOperationEnableWriteStatus,
+ EnumSpiOperationErase_256_Byte,
+ EnumSpiOperationErase_4K_Byte,
+ EnumSpiOperationErase_8K_Byte,
+ EnumSpiOperationErase_64K_Byte,
+ EnumSpiOperationFullChipErase,
+ EnumSpiOperationJedecId,
+ EnumSpiOperationDualOutputFastRead,
+ EnumSpiOperationDiscoveryParameters,
+ EnumSpiOperationOther,
+ EnumSpiOperationMax
+} SPI_OPERATION;
+
+//
+// Opcode menu entries
+// Type Operation Type (value to be programmed to the OPTYPE register)
+// Code The opcode (value to be programmed to the OPMENU register)
+// Frequency The expected frequency to be used (value to be programmed to the SSFC
+// Register)
+// Operation Which Hardware Sequencing required operation this opcode respoinds to.
+// The required operations are listed in EDS Table 5-55: "Hardware
+// Sequencing Commands and Opcode Requirements"
+// If the opcode does not corresponds to any operation listed, use
+// EnumSpiOperationOther
+//
+typedef struct _SPI_OPCODE_MENU_ENTRY {
+ SPI_OPCODE_TYPE Type;
+ UINT8 Code;
+ SPI_CYCLE_FREQUENCY Frequency;
+ SPI_OPERATION Operation;
+} SPI_OPCODE_MENU_ENTRY;
+
+//
+// Initialization data table loaded to the SPI host controller
+// VendorId Vendor ID of the SPI device
+// DeviceId0 Device ID0 of the SPI device
+// DeviceId1 Device ID1 of the SPI device
+// PrefixOpcode Prefix opcodes which are loaded into the SPI host controller
+// OpcodeMenu Opcodes which are loaded into the SPI host controller Opcode Menu
+// BiosStartOffset The offset of the start of the BIOS image relative to the flash device.
+// Please note this is a Flash Linear Address, NOT a memory space address.
+// This value is platform specific and depends on the system flash map.
+// This value is only used on non Descriptor mode.
+// BiosSize The the BIOS Image size in flash. This value is platform specific
+// and depends on the system flash map. Please note BIOS Image size may
+// be smaller than BIOS Region size (in Descriptor Mode) or the flash size
+// (in Non Descriptor Mode), and in this case, BIOS Image is supposed to be
+// placed at the top end of the BIOS Region (in Descriptor Mode) or the flash
+// (in Non Descriptor Mode)
+//
+typedef struct _SPI_INIT_TABLE {
+ UINT8 VendorId;
+ UINT8 DeviceId0;
+ UINT8 DeviceId1;
+ UINT8 PrefixOpcode[SPI_NUM_PREFIX_OPCODE];
+ SPI_OPCODE_MENU_ENTRY OpcodeMenu[SPI_NUM_OPCODE];
+ UINTN BiosStartOffset;
+ UINTN BiosSize;
+} SPI_INIT_TABLE;
+
+//
+// Public Info struct to show current initialized state of the spi interface.
+// OpcodeIndex must be less then SPI_NUM_OPCODE for operation to be supported.
+//
+typedef struct _SPI_INIT_INFO {
+ SPI_INIT_TABLE *InitTable;
+ UINT8 JedecIdOpcodeIndex;
+ UINT8 OtherOpcodeIndex;
+ UINT8 WriteStatusOpcodeIndex;
+ UINT8 ProgramOpcodeIndex;
+ UINT8 ReadOpcodeIndex;
+ UINT8 EraseOpcodeIndex;
+ UINT8 ReadStatusOpcodeIndex;
+ UINT8 FullChipEraseOpcodeIndex;
+} SPI_INIT_INFO;
+
+//
+// Protocol member functions
+//
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_INIT) (
+ IN EFI_SPI_PROTOCOL * This,
+ IN SPI_INIT_TABLE * InitTable
+ );
+/*++
+
+Routine Description:
+
+ Initializes the host controller to execute SPI commands.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ InitTable Pointer to caller-allocated buffer containing the SPI
+ interface initialization table.
+
+Returns:
+
+ EFI_SUCCESS Opcode initialization on the SPI host controller completed.
+ EFI_ACCESS_DENIED The SPI configuration interface is locked.
+ EFI_OUT_OF_RESOURCES Not enough resource available to initialize the device.
+ EFI_DEVICE_ERROR Device error, operation failed.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_LOCK) (
+ IN EFI_SPI_PROTOCOL * This
+ );
+/*++
+
+Routine Description:
+
+ Lock the SPI Static Configuration Interface.
+ Once locked, the interface is no longer open for configuration changes.
+ The lock state automatically clears on next system reset.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+
+Returns:
+
+ EFI_SUCCESS Lock operation succeed.
+ EFI_DEVICE_ERROR Device error, operation failed.
+ EFI_ACCESS_DENIED The interface has already been locked.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_EXECUTE) (
+ IN EFI_SPI_PROTOCOL * This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ );
+/*++
+
+Routine Description:
+
+ Execute SPI commands from the host controller.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ OpcodeIndex Index of the command in the OpCode Menu.
+ PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ DataCycle TRUE if the SPI cycle contains data
+ Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ DataByteCount Number of bytes in the data portion of the SPI cycle.
+ Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+ SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+Returns:
+
+ EFI_SUCCESS Command succeed.
+ EFI_INVALID_PARAMETER The parameters specified are not valid.
+ EFI_UNSUPPORTED Command not supported.
+ EFI_DEVICE_ERROR Device error, command aborts abnormally.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_INFO) (
+ IN EFI_SPI_PROTOCOL *This,
+ OUT SPI_INIT_INFO **InitInfoPtr
+ );
+/*++
+
+Routine Description:
+
+ Return info about SPI host controller, to help callers usage of Execute
+ service.
+
+ If 0xff is returned as an opcode index in init info struct
+ then device does not support the operation.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ InitInfoPtr Pointer to init info written to this memory location.
+
+Returns:
+
+ EFI_SUCCESS Information returned.
+ EFI_INVALID_PARAMETER Invalid parameter.
+ EFI_NOT_READY Required resources not setup.
+ Others Unexpected error happened.
+
+--*/
+
+//
+// Protocol definition
+//
+struct _EFI_SPI_PROTOCOL {
+ EFI_SPI_INIT Init;
+ EFI_SPI_LOCK Lock;
+ EFI_SPI_EXECUTE Execute;
+ EFI_SPI_INFO Info;
+};
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/QNCAccess.h b/QuarkSocPkg/QuarkNorthCluster/Include/QNCAccess.h
new file mode 100644
index 0000000..814739e
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/QNCAccess.h
@@ -0,0 +1,208 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCAccess.h
+
+Abstract:
+
+ Macros to simplify and abstract the interface to PCI configuration.
+
+--*/
+
+#ifndef _QNC_ACCESS_H_
+#define _QNC_ACCESS_H_
+
+#include "QuarkNcSocId.h"
+#include "QNCCommonDefinitions.h"
+
+#define EFI_LPC_PCI_ADDRESS( Register ) \
+ EFI_PCI_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, Register)
+
+//
+// QNC Controller PCI access macros
+//
+#define QNC_RCRB_BASE (QNCMmio32 (PciDeviceMmBase (0, PCI_DEVICE_NUMBER_QNC_LPC, 0), R_QNC_LPC_RCBA) & B_QNC_LPC_RCBA_MASK)
+
+//
+// Device 0x1f, Function 0
+//
+
+#define LpcPciCfg32( Register ) \
+ QNCMmPci32(0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register )
+
+#define LpcPciCfg32Or( Register, OrData ) \
+ QNCMmPci32Or( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, OrData )
+
+#define LpcPciCfg32And( Register, AndData ) \
+ QNCMmPci32And( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData )
+
+#define LpcPciCfg32AndThenOr( Register, AndData, OrData ) \
+ QNCMmPci32AndThenOr( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData, OrData )
+
+#define LpcPciCfg16( Register ) \
+ QNCMmPci16( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register )
+
+#define LpcPciCfg16Or( Register, OrData ) \
+ QNCMmPci16Or( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, OrData )
+
+#define LpcPciCfg16And( Register, AndData ) \
+ QNCMmPci16And( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData )
+
+#define LpcPciCfg16AndThenOr( Register, AndData, OrData ) \
+ QNCMmPci16AndThenOr( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData, OrData )
+
+#define LpcPciCfg8( Register ) \
+ QNCMmPci8( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register )
+
+#define LpcPciCfg8Or( Register, OrData ) \
+ QNCMmPci8Or( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, OrData )
+
+#define LpcPciCfg8And( Register, AndData ) \
+ QNCMmPci8And( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData )
+
+#define LpcPciCfg8AndThenOr( Register, AndData, OrData ) \
+ QNCMmPci8AndThenOr( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData, OrData )
+
+//
+// Root Complex Register Block
+//
+
+#define MmRcrb32( Register ) \
+ QNCMmio32( QNC_RCRB_BASE, Register )
+
+#define MmRcrb32Or( Register, OrData ) \
+ QNCMmio32Or( QNC_RCRB_BASE, Register, OrData )
+
+#define MmRcrb32And( Register, AndData ) \
+ QNCMmio32And( QNC_RCRB_BASE, Register, AndData )
+
+#define MmRcrb32AndThenOr( Register, AndData, OrData ) \
+ QNCMmio32AndThenOr( QNC_RCRB_BASE, Register, AndData, OrData )
+
+#define MmRcrb16( Register ) \
+ QNCMmio16( QNC_RCRB_BASE, Register )
+
+#define MmRcrb16Or( Register, OrData ) \
+ QNCMmio16Or( QNC_RCRB_BASE, Register, OrData )
+
+#define MmRcrb16And( Register, AndData ) \
+ QNCMmio16And( QNC_RCRB_BASE, Register, AndData )
+
+#define MmRcrb16AndThenOr( Register, AndData, OrData ) \
+ QNCMmio16AndThenOr( QNC_RCRB_BASE, Register, AndData, OrData )
+
+#define MmRcrb8( Register ) \
+ QNCMmio8( QNC_RCRB_BASE, Register )
+
+#define MmRcrb8Or( Register, OrData ) \
+ QNCMmio8Or( QNC_RCRB_BASE, Register, OrData )
+
+#define MmRcrb8And( Register, AndData ) \
+ QNCMmio8And( QNC_RCRB_BASE, Register, AndData )
+
+#define MmRcrb8AndThenOr( Register, AndData, OrData ) \
+ QNCMmio8AndThenOr( QNC_RCRB_BASE, Register, AndData, OrData )
+
+//
+// Memory Controller PCI access macros
+//
+
+//
+// Device 0, Function 0
+//
+
+#define McD0PciCfg64(Register) QNCMmPci32 (0, MC_BUS, 0, 0, Register)
+#define McD0PciCfg64Or(Register, OrData) QNCMmPci32Or (0, MC_BUS, 0, 0, Register, OrData)
+#define McD0PciCfg64And(Register, AndData) QNCMmPci32And (0, MC_BUS, 0, 0, Register, AndData)
+#define McD0PciCfg64AndThenOr(Register, AndData, OrData) QNCMmPci32AndThenOr (0, MC_BUS, 0, 0, Register, AndData, OrData)
+
+#define McD0PciCfg32(Register) QNCMmPci32 (0, MC_BUS, 0, 0, Register)
+#define McD0PciCfg32Or(Register, OrData) QNCMmPci32Or (0, MC_BUS, 0, 0, Register, OrData)
+#define McD0PciCfg32And(Register, AndData) QNCMmPci32And (0, MC_BUS, 0, 0, Register, AndData)
+#define McD0PciCfg32AndThenOr(Register, AndData, OrData) QNCMmPci32AndThenOr (0, MC_BUS, 0, 0, Register, AndData, OrData)
+
+#define McD0PciCfg16(Register) QNCMmPci16 (0, MC_BUS, 0, 0, Register)
+#define McD0PciCfg16Or(Register, OrData) QNCMmPci16Or (0, MC_BUS, 0, 0, Register, OrData)
+#define McD0PciCfg16And(Register, AndData) QNCMmPci16And (0, MC_BUS, 0, 0, Register, AndData)
+#define McD0PciCfg16AndThenOr(Register, AndData, OrData) QNCMmPci16AndThenOr (0, MC_BUS, 0, 0, Register, AndData, OrData)
+
+#define McD0PciCfg8(Register) QNCMmPci8 (0, MC_BUS, 0, 0, Register)
+#define McD0PciCfg8Or(Register, OrData) QNCMmPci8Or (0, MC_BUS, 0, 0, Register, OrData)
+#define McD0PciCfg8And(Register, AndData) QNCMmPci8And (0, MC_BUS, 0, 0, Register, AndData)
+#define McD0PciCfg8AndThenOr( Register, AndData, OrData ) QNCMmPci8AndThenOr (0, MC_BUS, 0, 0, Register, AndData, OrData)
+
+
+//
+// Memory Controller Hub Memory Mapped IO register access ???
+//
+#define MCH_REGION_BASE (McD0PciCfg64 (MC_MCHBAR_OFFSET) & ~BIT0)
+#define McMmioAddress(Register) ((UINTN) MCH_REGION_BASE + (UINTN) (Register))
+
+#define McMmio32Ptr(Register) ((volatile UINT32*) McMmioAddress (Register))
+#define McMmio64Ptr(Register) ((volatile UINT64*) McMmioAddress (Register))
+
+#define McMmio64(Register) *McMmio64Ptr( Register )
+#define McMmio64Or(Register, OrData) (McMmio64 (Register) |= (UINT64)(OrData))
+#define McMmio64And(Register, AndData) (McMmio64 (Register) &= (UINT64)(AndData))
+#define McMmio64AndThenOr(Register, AndData, OrData) (McMmio64 ( Register ) = (McMmio64( Register ) & (UINT64)(AndData)) | (UINT64)(OrData))
+
+#define McMmio32(Register) *McMmio32Ptr (Register)
+#define McMmio32Or(Register, OrData) (McMmio32 (Register) |= (UINT32)(OrData))
+#define McMmio32And(Register, AndData) (McMmio32 (Register) &= (UINT32)(AndData))
+#define McMmio32AndThenOr(Register, AndData, OrData) (McMmio32 (Register) = (McMmio32 (Register) & (UINT32) (AndData)) | (UINT32) (OrData))
+
+#define McMmio16Ptr(Register) ((volatile UINT16*) McMmioAddress (Register))
+#define McMmio16(Register) *McMmio16Ptr (Register)
+#define McMmio16Or(Register, OrData) (McMmio16 (Register) |= (UINT16) (OrData))
+#define McMmio16And(Register, AndData) (McMmio16 (Register) &= (UINT16) (AndData))
+#define McMmio16AndThenOr(Register, AndData, OrData) (McMmio16 (Register) = (McMmio16 (Register) & (UINT16) (AndData)) | (UINT16) (OrData))
+
+#define McMmio8Ptr(Register) ((volatile UINT8 *)McMmioAddress (Register))
+#define McMmio8(Register) *McMmio8Ptr (Register)
+#define McMmio8Or(Register, OrData) (McMmio8 (Register) |= (UINT8) (OrData))
+#define McMmio8And(Register, AndData) (McMmio8 (Register) &= (UINT8) (AndData))
+#define McMmio8AndThenOr(Register, AndData, OrData) (McMmio8 (Register) = (McMmio8 (Register) & (UINT8) (AndData)) | (UINT8) (OrData))
+
+//
+// QNC memory mapped related data structure deifinition
+//
+typedef enum {
+ QNCMmioWidthUint8 = 0,
+ QNCMmioWidthUint16 = 1,
+ QNCMmioWidthUint32 = 2,
+ QNCMmioWidthUint64 = 3,
+ QNCMmioWidthMaximum
+} QNC_MEM_IO_WIDTH;
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/QNCCommonDefinitions.h b/QuarkSocPkg/QuarkNorthCluster/Include/QNCCommonDefinitions.h
new file mode 100644
index 0000000..adb7d49
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/QNCCommonDefinitions.h
@@ -0,0 +1,381 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ QNCCommonDefinitions.h
+
+Abstract:
+
+ This header file provides common definitions just for MCH using to avoid including extra module's file.
+
+--*/
+
+#ifndef _QNC_COMMON_DEFINITIONS_H_
+#define _QNC_COMMON_DEFINITIONS_H_
+
+//
+// PCI CONFIGURATION MAP REGISTER OFFSETS
+//
+#ifndef PCI_VID
+#define PCI_VID 0x0000 // Vendor ID Register
+#define PCI_DID 0x0002 // Device ID Register
+#define PCI_CMD 0x0004 // PCI Command Register
+#define PCI_STS 0x0006 // PCI Status Register
+#define PCI_RID 0x0008 // Revision ID Register
+#define PCI_IFT 0x0009 // Interface Type
+#define PCI_SCC 0x000A // Sub Class Code Register
+#define PCI_BCC 0x000B // Base Class Code Register
+#define PCI_CLS 0x000C // Cache Line Size
+#define PCI_PMLT 0x000D // Primary Master Latency Timer
+#define PCI_HDR 0x000E // Header Type Register
+#define PCI_BIST 0x000F // Built in Self Test Register
+#define PCI_BAR0 0x0010 // Base Address Register 0
+#define PCI_BAR1 0x0014 // Base Address Register 1
+#define PCI_BAR2 0x0018 // Base Address Register 2
+#define PCI_PBUS 0x0018 // Primary Bus Number Register
+#define PCI_SBUS 0x0019 // Secondary Bus Number Register
+#define PCI_SUBUS 0x001A // Subordinate Bus Number Register
+#define PCI_SMLT 0x001B // Secondary Master Latency Timer
+#define PCI_BAR3 0x001C // Base Address Register 3
+#define PCI_IOBASE 0x001C // I/O base Register
+#define PCI_IOLIMIT 0x001D // I/O Limit Register
+#define PCI_SECSTATUS 0x001E // Secondary Status Register
+#define PCI_BAR4 0x0020 // Base Address Register 4
+#define PCI_MEMBASE 0x0020 // Memory Base Register
+#define PCI_MEMLIMIT 0x0022 // Memory Limit Register
+#define PCI_BAR5 0x0024 // Base Address Register 5
+#define PCI_PRE_MEMBASE 0x0024 // Prefetchable memory Base register
+#define PCI_PRE_MEMLIMIT 0x0026 // Prefetchable memory Limit register
+#define PCI_PRE_MEMBASE_U 0x0028 // Prefetchable memory base upper 32 bits
+#define PCI_PRE_MEMLIMIT_U 0x002C // Prefetchable memory limit upper 32 bits
+#define PCI_SVID 0x002C // Subsystem Vendor ID
+#define PCI_SID 0x002E // Subsystem ID
+#define PCI_IOBASE_U 0x0030 // I/O base Upper Register
+#define PCI_IOLIMIT_U 0x0032 // I/O Limit Upper Register
+#define PCI_CAPP 0x0034 // Capabilities Pointer
+#define PCI_EROM 0x0038 // Expansion ROM Base Address
+#define PCI_INTLINE 0x003C // Interrupt Line Register
+#define PCI_INTPIN 0x003D // Interrupt Pin Register
+#define PCI_MAXGNT 0x003E // Max Grant Register
+#define PCI_BRIDGE_CNTL 0x003E // Bridge Control Register
+#define PCI_MAXLAT 0x003F // Max Latency Register
+#endif
+//
+// Bit Difinitions
+//
+#ifndef BIT0
+#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
+#endif
+
+
+//
+// Common Memory mapped Io access macros ------------------------------------------
+//
+#define QNCMmioAddress( BaseAddr, Register ) \
+ ( (UINTN)BaseAddr + \
+ (UINTN)(Register) \
+ )
+
+//
+// UINT64
+//
+#define QNCMmio64Ptr( BaseAddr, Register ) \
+ ( (volatile UINT64 *)QNCMmioAddress( BaseAddr, Register ) )
+
+#define QNCMmio64( BaseAddr, Register ) \
+ *QNCMmio64Ptr( BaseAddr, Register )
+
+#define QNCMmio64Or( BaseAddr, Register, OrData ) \
+ QNCMmio64( BaseAddr, Register ) = \
+ (UINT64) ( \
+ QNCMmio64( BaseAddr, Register ) | \
+ (UINT64)(OrData) \
+ )
+
+#define QNCMmio64And( BaseAddr, Register, AndData ) \
+ QNCMmio64( BaseAddr, Register ) = \
+ (UINT64) ( \
+ QNCMmio64( BaseAddr, Register ) & \
+ (UINT64)(AndData) \
+ )
+
+#define QNCMmio64AndThenOr( BaseAddr, Register, AndData, OrData ) \
+ QNCMmio64( BaseAddr, Register ) = \
+ (UINT64) ( \
+ ( QNCMmio64( BaseAddr, Register ) & \
+ (UINT64)(AndData) \
+ ) | \
+ (UINT64)(OrData) \
+ )
+
+//
+// UINT32
+//
+#define QNCMmio32Ptr( BaseAddr, Register ) \
+ ( (volatile UINT32 *)QNCMmioAddress( BaseAddr, Register ) )
+
+#define QNCMmio32( BaseAddr, Register ) \
+ *QNCMmio32Ptr( BaseAddr, Register )
+
+#define QNCMmio32Or( BaseAddr, Register, OrData ) \
+ QNCMmio32( BaseAddr, Register ) = \
+ (UINT32) ( \
+ QNCMmio32( BaseAddr, Register ) | \
+ (UINT32)(OrData) \
+ )
+
+#define QNCMmio32And( BaseAddr, Register, AndData ) \
+ QNCMmio32( BaseAddr, Register ) = \
+ (UINT32) ( \
+ QNCMmio32( BaseAddr, Register ) & \
+ (UINT32)(AndData) \
+ )
+
+#define QNCMmio32AndThenOr( BaseAddr, Register, AndData, OrData ) \
+ QNCMmio32( BaseAddr, Register ) = \
+ (UINT32) ( \
+ ( QNCMmio32( BaseAddr, Register ) & \
+ (UINT32)(AndData) \
+ ) | \
+ (UINT32)(OrData) \
+ )
+//
+// UINT16
+//
+
+#define QNCMmio16Ptr( BaseAddr, Register ) \
+ ( (volatile UINT16 *)QNCMmioAddress( BaseAddr, Register ) )
+
+#define QNCMmio16( BaseAddr, Register ) \
+ *QNCMmio16Ptr( BaseAddr, Register )
+
+#define QNCMmio16Or( BaseAddr, Register, OrData ) \
+ QNCMmio16( BaseAddr, Register ) = \
+ (UINT16) ( \
+ QNCMmio16( BaseAddr, Register ) | \
+ (UINT16)(OrData) \
+ )
+
+#define QNCMmio16And( BaseAddr, Register, AndData ) \
+ QNCMmio16( BaseAddr, Register ) = \
+ (UINT16) ( \
+ QNCMmio16( BaseAddr, Register ) & \
+ (UINT16)(AndData) \
+ )
+
+#define QNCMmio16AndThenOr( BaseAddr, Register, AndData, OrData ) \
+ QNCMmio16( BaseAddr, Register ) = \
+ (UINT16) ( \
+ ( QNCMmio16( BaseAddr, Register ) & \
+ (UINT16)(AndData) \
+ ) | \
+ (UINT16)(OrData) \
+ )
+//
+// UINT8
+//
+#define QNCMmio8Ptr( BaseAddr, Register ) \
+ ( (volatile UINT8 *)QNCMmioAddress( BaseAddr, Register ) )
+
+#define QNCMmio8( BaseAddr, Register ) \
+ *QNCMmio8Ptr( BaseAddr, Register )
+
+#define QNCMmio8Or( BaseAddr, Register, OrData ) \
+ QNCMmio8( BaseAddr, Register ) = \
+ (UINT8) ( \
+ QNCMmio8( BaseAddr, Register ) | \
+ (UINT8)(OrData) \
+ )
+
+#define QNCMmio8And( BaseAddr, Register, AndData ) \
+ QNCMmio8( BaseAddr, Register ) = \
+ (UINT8) ( \
+ QNCMmio8( BaseAddr, Register ) & \
+ (UINT8)(AndData) \
+ )
+
+#define QNCMmio8AndThenOr( BaseAddr, Register, AndData, OrData ) \
+ QNCMmio8( BaseAddr, Register ) = \
+ (UINT8) ( \
+ ( QNCMmio8( BaseAddr, Register ) & \
+ (UINT8)(AndData) \
+ ) | \
+ (UINT8)(OrData) \
+ )
+
+//
+// Common Memory mapped Pci access macros ------------------------------------------
+//
+
+#define QNCMmPciAddress( Segment, Bus, Device, Function, Register ) \
+ ( (UINTN) QncGetPciExpressBaseAddress() + \
+ (UINTN)(Bus << 20) + \
+ (UINTN)(Device << 15) + \
+ (UINTN)(Function << 12) + \
+ (UINTN)(Register) \
+ )
+
+//
+// Macro to calculate the Pci device's base memory mapped address
+//
+#define PciDeviceMmBase( Bus, Device, Function) \
+ ( (UINTN) QncGetPciExpressBaseAddress () + \
+ (UINTN)(Bus << 20) + \
+ (UINTN)(Device << 15) + \
+ (UINTN)(Function << 12) \
+ )
+
+//
+// UINT32
+//
+#define QNCMmPci32Ptr( Segment, Bus, Device, Function, Register ) \
+ ( (volatile UINT32 *)QNCMmPciAddress( Segment, Bus, Device, Function, Register ) )
+
+#define QNCMmPci32( Segment, Bus, Device, Function, Register ) \
+ *QNCMmPci32Ptr( Segment, Bus, Device, Function, Register )
+
+#define QNCMmPci32Or( Segment, Bus, Device, Function, Register, OrData ) \
+ QNCMmPci32( Segment, Bus, Device, Function, Register ) = \
+ (UINT32) ( \
+ QNCMmPci32( Segment, Bus, Device, Function, Register ) | \
+ (UINT32)(OrData) \
+ )
+
+#define QNCMmPci32And( Segment, Bus, Device, Function, Register, AndData ) \
+ QNCMmPci32( Segment, Bus, Device, Function, Register ) = \
+ (UINT32) ( \
+ QNCMmPci32( Segment, Bus, Device, Function, Register ) & \
+ (UINT32)(AndData) \
+ )
+
+#define QNCMmPci32AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \
+ QNCMmPci32( Segment, Bus, Device, Function, Register ) = \
+ (UINT32) ( \
+ ( QNCMmPci32( Segment, Bus, Device, Function, Register ) & \
+ (UINT32)(AndData) \
+ ) | \
+ (UINT32)(OrData) \
+ )
+//
+// UINT16
+//
+#define QNCMmPci16Ptr( Segment, Bus, Device, Function, Register ) \
+ ( (volatile UINT16 *)QNCMmPciAddress( Segment, Bus, Device, Function, Register ) )
+
+#define QNCMmPci16( Segment, Bus, Device, Function, Register ) \
+ *QNCMmPci16Ptr( Segment, Bus, Device, Function, Register )
+
+#define QNCMmPci16Or( Segment, Bus, Device, Function, Register, OrData ) \
+ QNCMmPci16( Segment, Bus, Device, Function, Register ) = \
+ (UINT16) ( \
+ QNCMmPci16( Segment, Bus, Device, Function, Register ) | \
+ (UINT16)(OrData) \
+ )
+
+#define QNCMmPci16And( Segment, Bus, Device, Function, Register, AndData ) \
+ QNCMmPci16( Segment, Bus, Device, Function, Register ) = \
+ (UINT16) ( \
+ QNCMmPci16( Segment, Bus, Device, Function, Register ) & \
+ (UINT16)(AndData) \
+ )
+
+#define QNCMmPci16AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \
+ QNCMmPci16( Segment, Bus, Device, Function, Register ) = \
+ (UINT16) ( \
+ ( QNCMmPci16( Segment, Bus, Device, Function, Register ) & \
+ (UINT16)(AndData) \
+ ) | \
+ (UINT16)(OrData) \
+ )
+//
+// UINT8
+//
+#define QNCMmPci8Ptr( Segment, Bus, Device, Function, Register ) \
+ ( (volatile UINT8 *)QNCMmPciAddress( Segment, Bus, Device, Function, Register ) )
+
+#define QNCMmPci8( Segment, Bus, Device, Function, Register ) \
+ *QNCMmPci8Ptr( Segment, Bus, Device, Function, Register )
+
+#define QNCMmPci8Or( Segment, Bus, Device, Function, Register, OrData ) \
+ QNCMmPci8( Segment, Bus, Device, Function, Register ) = \
+ (UINT8) ( \
+ QNCMmPci8( Segment, Bus, Device, Function, Register ) | \
+ (UINT8)(OrData) \
+ )
+
+#define QNCMmPci8And( Segment, Bus, Device, Function, Register, AndData ) \
+ QNCMmPci8( Segment, Bus, Device, Function, Register ) = \
+ (UINT8) ( \
+ QNCMmPci8( Segment, Bus, Device, Function, Register ) & \
+ (UINT8)(AndData) \
+ )
+
+#define QNCMmPci8AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \
+ QNCMmPci8( Segment, Bus, Device, Function, Register ) = \
+ (UINT8) ( \
+ ( QNCMmPci8( Segment, Bus, Device, Function, Register ) & \
+ (UINT8)(AndData) \
+ ) | \
+ (UINT8)(OrData) \
+ )
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/QuarkNcSocId.h b/QuarkSocPkg/QuarkNorthCluster/Include/QuarkNcSocId.h
new file mode 100755
index 0000000..4f99ed7
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Include/QuarkNcSocId.h
@@ -0,0 +1,780 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ QuarkNcSocId.h
+
+Abstract:
+
+ QuarkNcSocId Register Definitions
+
+ 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
+
+--*/
+
+#ifndef _QUARK_NC_SOC_ID_H_
+#define _QUARK_NC_SOC_ID_H_
+
+//
+// QNC GMCH Equates
+//
+
+//
+// DEVICE 0 (Memroy Controller Hub)
+//
+#define MC_BUS PCI_BUS_NUMBER_QNC
+#define MC_DEV 0x00
+#define MC_FUN 0x00
+
+#define QUARK_MC_VENDOR_ID V_INTEL_VENDOR_ID
+#define QUARK_MC_DEVICE_ID 0x0958
+#define QUARK2_MC_DEVICE_ID 0x12C0
+#define QNC_MC_REV_ID_A0 0x00
+
+
+//
+// MCR - B0:D0:F0:RD0h (WO)- Message control register
+// [31:24] Message opcode - D0 read; E0 write;
+// [23:16] Message port
+// [15:8 ] Message target register address
+// [ 7:4 ] Message write byte enable : F is enable
+// [ 3:0 ] Reserved
+//
+#define QNC_ACCESS_PORT_MCR 0xD0 // Message Control Register
+// Always Set to 0xF0
+
+//
+//MDR - B0:D0:F0:RD4h (RW)- Message data register
+//
+#define QNC_ACCESS_PORT_MDR 0xD4 // Message Data Register
+
+//
+//MEA - B0:D0:F0:RD8h (RW)- Message extended address register
+//
+#define QNC_ACCESS_PORT_MEA 0xD8 // Message Extended Address Register
+
+#define QNC_MCR_OP_OFFSET 24 // Offset of the opcode field in MCR
+#define QNC_MCR_PORT_OFFSET 16 // Offset of the port field in MCR
+#define QNC_MCR_REG_OFFSET 8 // Offset of the register field in MCR
+
+//
+// Misc Useful Macros
+//
+
+#define LShift16(value) (value << 16)
+
+//
+// QNC Message OpCodes and Attributes
+//
+#define QUARK_OPCODE_READ 0x10 // Quark message bus "read" opcode
+#define QUARK_OPCODE_WRITE 0x11 // Quark message bus "write" opcode
+
+//
+// Alternative opcodes for the SCSS block
+//
+#define QUARK_ALT_OPCODE_READ 0x06 // Quark message bus "read" opcode
+#define QUARK_ALT_OPCODE_WRITE 0x07 // Quark message bus "write" opcode
+
+//
+// QNC Message OpCodes and Attributes for IO
+//
+#define QUARK_OPCODE_IO_READ 0x02 // Quark message bus "IO read" opcode
+#define QUARK_OPCODE_IO_WRITE 0x03 // Quark message bus "IO write" opcode
+
+
+#define QUARK_DRAM_BASE_ADDR_READY 0x78 // Quark message bus "RMU Main binary shadow" opcode
+
+#define QUARK_ECC_SCRUB_RESUME 0xC2 // Quark Remote Management Unit "scrub resume" opcode
+#define QUARK_ECC_SCRUB_PAUSE 0xC3 // Quark Remote Management Unit "scrub pause" opcode
+
+//
+// QNC Message Ports and Registers
+//
+// Start of SB Port IDs
+#define QUARK_NC_MEMORY_ARBITER_SB_PORT_ID 0x00
+#define QUARK_NC_MEMORY_CONTROLLER_SB_PORT_ID 0x01
+#define QUARK_NC_HOST_BRIDGE_SB_PORT_ID 0x03
+#define QUARK_NC_RMU_SB_PORT_ID 0x04
+#define QUARK_NC_MEMORY_MANAGER_SB_PORT_ID 0x05
+#define QUARK_SC_USB_AFE_SB_PORT_ID 0x14
+#define QUARK_SC_PCIE_AFE_SB_PORT_ID 0x16
+#define QUARK_SCSS_SOC_UNIT_SB_PORT_ID 0x31
+#define QUARK_SCSS_FUSE_SB_PORT_ID 0x33
+#define QUARK_ICLK_SB_PORT_ID 0x32
+#define QUARK_SCSS_CRU_SB_PORT_ID 0x34
+
+//
+// Quark Memory Arbiter Registers.
+//
+#define QUARK_NC_MEMORY_ARBITER_REG_ASTATUS 0x21 // Memory Arbiter PRI Status encodings register.
+#define ASTATUS_PRI_CASUAL 0x0 // Serviced only if convenient
+#define ASTATUS_PRI_IMPENDING 0x1 // Serviced if the DRAM is in Self-Refresh.
+#define ASTATUS_PRI_NORMAL 0x2 // Normal request servicing.
+#define ASTATUS_PRI_URGENT 0x3 // Urgent request servicing.
+#define ASTATUS1_RASISED_BP (10)
+#define ASTATUS1_RASISED_BP_MASK (0x03 << ASTATUS1_RASISED_BP)
+#define ASTATUS0_RASISED_BP (8)
+#define ASTATUS0_RASISED_BP_MASK (0x03 << ASTATUS1_RASISED_BP)
+#define ASTATUS1_DEFAULT_BP (2)
+#define ASTATUS1_DEFAULT_BP_MASK (0x03 << ASTATUS1_RASISED_BP)
+#define ASTATUS0_DEFAULT_BP (0)
+#define ASTATUS0_DEFAULT_BP_MASK (0x03 << ASTATUS1_RASISED_BP)
+
+//
+// Quark Memory Controller Registers.
+//
+#define QUARK_NC_MEMORY_CONTROLLER_REG_DFUSESTAT 0x70 // Fuse status register.
+#define B_DFUSESTAT_ECC_DIS (BIT0) // Disable ECC.
+
+//
+// Quark Remote Management Unit Registers.
+//
+#define QNC_MSG_TMPM_REG_PMBA 0x70 // Power Management I/O Base Address
+
+#define QUARK_NC_RMU_REG_CONFIG 0x71 // Remote Management Unit configuration register.
+#define TS_LOCK_AUX_TRIP_PT_REGS_ENABLE (BIT6)
+#define TS_LOCK_THRM_CTRL_REGS_ENABLE (BIT5)
+
+#define QUARK_NC_RMU_REG_OPTIONS_1 0x72 // Remote Management Unit Options register 1.
+#define OPTIONS_1_DMA_DISABLE (BIT0)
+
+#define QUARK_NC_RMU_REG_WDT_CONTROL 0x74 // Remote Management Unit Watchdog control register.
+#define B_WDT_CONTROL_DBL_ECC_BIT_ERR_MASK (BIT19 | BIT18)
+#define B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP 18
+#define V_WDT_CONTROL_DBL_ECC_BIT_ERR_NONE (0x0 << B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP)
+#define V_WDT_CONTROL_DBL_ECC_BIT_ERR_CAT (0x1 << B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP)
+#define V_WDT_CONTROL_DBL_ECC_BIT_ERR_WARM (0x2 << B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP)
+#define V_WDT_CONTROL_DBL_ECC_BIT_ERR_SERR (0x3 << B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP)
+
+#define QUARK_NC_RMU_REG_SDMA 0x7A // Remote Management Unit SPI DMA config register
+#define QUARK_NC_RMU_REG_TS_MODE 0xB0 // Remote Management Unit Thermal sensor mode register.
+#define TS_ENABLE (BIT15)
+#define QUARK_NC_RMU_REG_TS_TRIP 0xB2 // Remote Management Unit Thermal sensor programmable trip point register.
+#define TS_HOT_TRIP_CLEAR_THOLD_BP 24
+#define TS_HOT_TRIP_CLEAR_THOLD_MASK (0xFF << TS_HOT_TRIP_CLEAR_THOLD_BP)
+#define TS_CAT_TRIP_CLEAR_THOLD_BP 16
+#define TS_CAT_TRIP_CLEAR_THOLD_MASK (0xFF << TS_CAT_TRIP_CLEAR_THOLD_BP)
+#define TS_HOT_TRIP_SET_THOLD_BP 8
+#define TS_HOT_TRIP_SET_THOLD_MASK (0xFF << TS_HOT_TRIP_SET_THOLD_BP)
+#define TS_CAT_TRIP_SET_THOLD_BP 0
+#define TS_CAT_TRIP_SET_THOLD_MASK (0xFF << TS_CAT_TRIP_SET_THOLD_BP)
+
+#define QUARK_NC_ECC_SCRUB_CONFIG_REG 0x50
+#define SCRUB_CFG_INTERVAL_SHIFT 0x00
+#define SCRUB_CFG_INTERVAL_MASK 0xFF
+#define SCRUB_CFG_BLOCKSIZE_SHIFT 0x08
+#define SCRUB_CFG_BLOCKSIZE_MASK 0x1F
+#define SCRUB_CFG_ACTIVE (BIT13)
+#define SCRUB_CFG_INVALID 0x00000FFF
+
+#define QUARK_NC_ECC_SCRUB_START_MEM_REG 0x76
+#define QUARK_NC_ECC_SCRUB_END_MEM_REG 0x77
+#define QUARK_NC_ECC_SCRUB_NEXT_READ_REG 0x7C
+
+#define SCRUB_RESUME_MSG() ((UINT32)( \
+ (QUARK_ECC_SCRUB_RESUME << QNC_MCR_OP_OFFSET) | \
+ (QUARK_NC_RMU_SB_PORT_ID << QNC_MCR_PORT_OFFSET) | \
+ 0xF0))
+
+#define SCRUB_PAUSE_MSG() ((UINT32)( \
+ (QUARK_ECC_SCRUB_PAUSE << QNC_MCR_OP_OFFSET) | \
+ (QUARK_NC_RMU_SB_PORT_ID << QNC_MCR_PORT_OFFSET) | \
+ 0xF0))
+
+//
+// Quark Memory Manager Registers
+//
+#define QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK 0x82
+#define BLOCK_ENABLE_PG (1 << 28)
+#define BLOCK_DISABLE_PG (1 << 29)
+#define QUARK_NC_MEMORY_MANAGER_BIMRVCTL 0x19
+#define EnableIMRInt BIT31
+#define QUARK_NC_MEMORY_MANAGER_BSMMVCTL 0x1C
+#define EnableSMMInt BIT31
+#define QUARK_NC_MEMORY_MANAGER_BTHCTRL 0x20
+#define DRAM_NON_HOST_RQ_LIMIT_BP 0
+#define DRAM_NON_HOST_RQ_LIMIT_MASK (0x3f << DRAM_NON_HOST_RQ_LIMIT_BP)
+
+#define QUARK_NC_MEMORY_MANAGER_IMR0 0x40
+#define QUARK_NC_MEMORY_MANAGER_IMR1 0x44
+#define QUARK_NC_MEMORY_MANAGER_IMR2 0x48
+#define QUARK_NC_MEMORY_MANAGER_IMR3 0x4C
+#define QUARK_NC_MEMORY_MANAGER_IMR4 0x50
+#define QUARK_NC_MEMORY_MANAGER_IMR5 0x54
+#define QUARK_NC_MEMORY_MANAGER_IMR6 0x58
+#define QUARK_NC_MEMORY_MANAGER_IMR7 0x5C
+ #define QUARK_NC_MEMORY_MANAGER_IMRXL 0x00
+ #define IMR_LOCK BIT31
+ #define IMR_EN BIT30
+ #define IMRL_MASK 0x00FFFFFC
+ #define IMRL_RESET 0x00000000
+ #define QUARK_NC_MEMORY_MANAGER_IMRXH 0x01
+ #define IMRH_MASK 0x00FFFFFC
+ #define IMRH_RESET 0x00000000
+ #define QUARK_NC_MEMORY_MANAGER_IMRXRM 0x02
+ #define QUARK_NC_MEMORY_MANAGER_IMRXWM 0x03
+ #define IMRX_ALL_ACCESS 0xFFFFFFFF
+ #define CPU_SNOOP BIT30
+ #define RMU BIT29
+ #define CPU0_NON_SMM BIT0
+
+//
+// Quark Host Bridge Registers
+//
+#define QNC_MSG_FSBIC_REG_HMISC 0x03 // Host Misellaneous Controls
+#define SMI_EN (BIT19) // SMI Global Enable (from Legacy Bridge)
+#define QNC_MSG_FSBIC_REG_HSMMC 0x04 // Host SMM Control
+#define NON_HOST_SMM_WR_OPEN (BIT18) // SMM Writes OPEN
+#define NON_HOST_SMM_RD_OPEN (BIT17) // SMM Writes OPEN
+#define SMM_CODE_RD_OPEN (BIT16) // SMM Code read OPEN
+#define SMM_CTL_EN (BIT3) // SMM enable
+#define SMM_WRITE_OPEN (BIT2) // SMM Writes OPEN
+#define SMM_READ_OPEN (BIT1) // SMM Reads OPEN
+#define SMM_LOCKED (BIT0) // SMM Locked
+#define SMM_START_MASK 0x0000FFF0
+#define SMM_END_MASK 0xFFF00000
+#define QUARK_NC_HOST_BRIDGE_HMBOUND_REG 0x08
+#define HMBOUND_MASK 0x0FFFFF000
+#define HMBOUND_LOCK BIT0
+#define QUARK_NC_HOST_BRIDGE_HLEGACY_REG 0x0A
+#define HLEGACY_SMI_PIN_VALUE BIT12
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP 0x40
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE 0x41
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000 0x42
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000 0x44
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_A0000 0x46
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C0000 0x48
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C8000 0x4A
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D0000 0x4C
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D8000 0x4E
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E0000 0x50
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E8000 0x52
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F0000 0x54
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000 0x56
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSBASE 0x58
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK 0x59
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0 0x5A
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK0 0x5B
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE1 0x5C
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK1 0x5D
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE2 0x5E
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK2 0x5F
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE3 0x60
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK3 0x61
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE4 0x62
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK4 0x63
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE5 0x64
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK5 0x65
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE6 0x66
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK6 0x67
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE7 0x68
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK7 0x69
+
+//
+// System On Chip Unit (SOCUnit) Registers.
+//
+#define QUARK_SCSS_SOC_UNIT_STPDDRCFG 0x00
+#define B_STPDDRCFG_FORCE_RECOVERY BIT0
+
+#define QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG 0x31
+#define B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK (BIT5 | BIT4 | BIT3)
+#define B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP 3
+#define B_TSCGF1_CONFIG_ISNSCHOPSEL_MASK (BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define B_TSCGF1_CONFIG_ISNSCHOPSEL_BP 8
+#define B_TSCGF1_CONFIG_IBGEN BIT17
+#define B_TSCGF1_CONFIG_IBGEN_BP 17
+#define B_TSCGF1_CONFIG_IBGCHOPEN BIT18
+#define B_TSCGF1_CONFIG_IBGCHOPEN_BP 18
+#define B_TSCGF1_CONFIG_ISNSINTERNALVREFEN BIT14
+#define B_TSCGF1_CONFIG_ISNSINTERNALVREFEN_BP 14
+
+#define QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG 0x32
+#define B_TSCGF2_CONFIG_IDSCONTROL_MASK 0x0000FFFF
+#define B_TSCGF2_CONFIG_IDSCONTROL_BP 0
+#define B_TSCGF2_CONFIG_IDSTIMING_MASK 0xFFFF0000
+#define B_TSCGF2_CONFIG_IDSTIMING_BP 16
+
+#define QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2 0x33
+#define B_TSCGF2_CONFIG2_ISPARECTRL_MASK 0xFF000000
+#define B_TSCGF2_CONFIG2_ISPARECTRL_BP 24
+#define B_TSCGF2_CONFIG2_ICALCONFIGSEL_MASK (BIT9 | BIT8)
+#define B_TSCGF2_CONFIG2_ICALCONFIGSEL_BP 8
+#define B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK 0x000000FF
+#define B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP 0
+
+#define QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG 0x34
+#define B_TSCGF3_CONFIG_ITSRST BIT0
+#define B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP 11
+#define B_TSCGF3_CONFIG_ITSGAMMACOEFF_MASK (0xFFF << B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP)
+
+#define QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG 0x36
+#define SOCCLKEN_CONFIG_PHY_I_SIDE_RST_L BIT20
+#define SOCCLKEN_CONFIG_PHY_I_CMNRESET_L BIT19
+#define SOCCLKEN_CONFIG_SBI_BB_RST_B BIT18
+#define SOCCLKEN_CONFIG_SBI_RST_100_CORE_B BIT17
+#define SOCCLKEN_CONFIG_BB_RST_B BIT16
+
+#define QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG 0x36
+
+#define QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW 0x51
+#define B_CFG_STICKY_RW_SMM_VIOLATION BIT0
+#define B_CFG_STICKY_RW_HMB_VIOLATION BIT1
+#define B_CFG_STICKY_RW_IMR_VIOLATION BIT2
+#define B_CFG_STICKY_RW_DECC_VIOLATION BIT3
+#define B_CFG_STICKY_RW_WARM_RST BIT4
+#define B_CFG_STICKY_RW_FORCE_RECOVERY BIT9
+#define B_CFG_STICKY_RW_VIOLATION (B_CFG_STICKY_RW_SMM_VIOLATION | B_CFG_STICKY_RW_HMB_VIOLATION | B_CFG_STICKY_RW_IMR_VIOLATION | B_CFG_STICKY_RW_DECC_VIOLATION)
+#define B_CFG_STICKY_RW_ALL (B_CFG_STICKY_RW_VIOLATION | B_CFG_STICKY_RW_WARM_RST)
+
+//
+// iCLK Registers.
+//
+#define QUARK_ICLK_MUXTOP 0x0140
+#define B_MUXTOP_FLEX2_MASK (BIT25 | BIT24 | BIT23)
+#define B_MUXTOP_FLEX2_BP 23
+#define B_MUXTOP_FLEX1_MASK (BIT22 | BIT21 | BIT20)
+#define B_MUXTOP_FLEX1_BP 20
+
+#define QUARK_ICLK_SSC1 0x0314
+#define QUARK_ICLK_SSC2 0x0414
+#define QUARK_ICLK_SSC3 0x0514
+#define QUARK_ICLK_REF2_DBUFF0 0x2000
+
+//
+// PCIe AFE Unit Registers (QUARK_SC_PCIE_AFE_SB_PORT_ID).
+//
+#define QUARK_PCIE_AFE_PCIE_RXPICTRL0_L0 0x2080
+#define QUARK_PCIE_AFE_PCIE_RXPICTRL0_L1 0x2180
+#define OCFGPIMIXLOAD_1_0 BIT6
+#define OCFGPIMIXLOAD_1_0_MASK 0xFFFFFF3F
+
+//
+// QNC ICH Equates
+//
+#define V_INTEL_VENDOR_ID 0x8086
+
+#define PCI_BUS_NUMBER_QNC 0x00
+
+//
+// PCI to LPC Bridge Registers (D31:F0)
+//
+#define PCI_DEVICE_NUMBER_QNC_LPC 31
+#define PCI_FUNCTION_NUMBER_QNC_LPC 0
+
+#define R_QNC_LPC_VENDOR_ID 0x00
+#define V_LPC_VENDOR_ID V_INTEL_VENDOR_ID
+#define R_QNC_LPC_DEVICE_ID 0x02
+#define QUARK_V_LPC_DEVICE_ID_0 0x095E
+#define R_QNC_LPC_REV_ID 0x08
+
+#define R_QNC_LPC_SMBUS_BASE 0x40 //~0x43
+#define B_QNC_LPC_SMBUS_BASE_EN (BIT31)
+#define B_QNC_LPC_SMBUS_BASE_MASK 0x0000FFC0 //[15:6]
+//
+// SMBus register offsets from SMBA - "SMBA" (D31:F0:R40h)
+// Suggested Value for SMBA = 0x1040
+//
+#define R_QNC_SMBUS_HCTL 0x00 // Host Control Register R/W
+#define B_QNC_SMBUS_START (BIT4) // Start/Stop
+#define V_QNC_SMBUS_HCTL_CMD_QUICK 0
+#define V_QNC_SMBUS_HCTL_CMD_BYTE 1
+#define V_QNC_SMBUS_HCTL_CMD_BYTE_DATA 2
+#define V_QNC_SMBUS_HCTL_CMD_WORD_DATA 3
+#define V_QNC_SMBUS_HCTL_CMD_PROCESS_CALL 4
+#define V_QNC_SMBUS_HCTL_CMD_BLOCK 5
+
+#define R_QNC_SMBUS_HSTS 0x01 // Host Status Register R/W
+#define B_QNC_SMBUS_BERR (BIT2) // BUS Error
+#define B_QNC_SMBUS_DERR (BIT1) // Device Error
+#define B_QNC_SMBUS_BYTE_DONE_STS (BIT0) // Completion Status
+#define B_QNC_SMBUS_HSTS_ALL 0x07
+
+#define R_QNC_SMBUS_HCLK 0x02 // Host Clock Divider Register R/W
+#define V_QNC_SMBUS_HCLK_100KHZ 0x0054
+
+#define R_QNC_SMBUS_TSA 0x04 // Transmit Slave Address Register R/W
+#define V_QNC_SMBUS_RW_SEL_READ 1
+#define V_QNC_SMBUS_RW_SEL_WRITE 0
+
+#define R_QNC_SMBUS_HCMD 0x05 // Host Command Register R/W
+#define R_QNC_SMBUS_HD0 0x06 // Data 0 Register R/W
+#define R_QNC_SMBUS_HD1 0x07 // Data 1 Register R/W
+#define R_QNC_SMBUS_HBD 0x20 // Host Block Data Register R/W [255:0] ~ 3Fh
+
+#define R_QNC_LPC_GBA_BASE 0x44
+#define B_QNC_LPC_GPA_BASE_MASK 0x0000FFC0
+//
+// GPIO register offsets from GBA - "GPIO" (D31:F0:R44h)
+// Suggested Value for GBA = 0x1080
+//
+#define R_QNC_GPIO_CGEN_CORE_WELL 0x00
+#define R_QNC_GPIO_CGIO_CORE_WELL 0x04
+#define R_QNC_GPIO_CGLVL_CORE_WELL 0x08
+#define R_QNC_GPIO_CGTPE_CORE_WELL 0x0C // Core well GPIO Trigger Positive Edge Enable
+#define R_QNC_GPIO_CGTNE_CORE_WELL 0x10 // Core well GPIO Trigger Negative Edge Enable
+#define R_QNC_GPIO_CGGPE_CORE_WELL 0x14 // Core well GPIO GPE Enable
+#define R_QNC_GPIO_CGSMI_CORE_WELL 0x18 // Core well GPIO SMI Enable
+#define R_QNC_GPIO_CGTS_CORE_WELL 0x1C // Core well GPIO Trigger Status
+#define R_QNC_GPIO_RGEN_RESUME_WELL 0x20
+#define R_QNC_GPIO_RGIO_RESUME_WELL 0x24
+#define R_QNC_GPIO_RGLVL_RESUME_WELL 0x28
+#define R_QNC_GPIO_RGTPE_RESUME_WELL 0x2C // Resume well GPIO Trigger Positive Edge Enable
+#define R_QNC_GPIO_RGTNE_RESUME_WELL 0x30 // Resume well GPIO Trigger Negative Edge Enable
+#define R_QNC_GPIO_RGGPE_RESUME_WELL 0x34 // Resume well GPIO GPE Enable
+#define R_QNC_GPIO_RGSMI_RESUME_WELL 0x38 // Resume well GPIO SMI Enable
+#define R_QNC_GPIO_RGTS_RESUME_WELL 0x3C // Resume well GPIO Trigger Status
+#define R_QNC_GPIO_CNMIEN_CORE_WELL 0x40 // Core well GPIO NMI Enable
+#define R_QNC_GPIO_RNMIEN_RESUME_WELL 0x44 // Resume well GPIO NMI Enable
+
+#define R_QNC_LPC_PM1BLK 0x48
+#define B_QNC_LPC_PM1BLK_MASK 0x0000FFF0
+//
+// ACPI register offsets from PM1BLK - "ACPI PM1 Block" (D31:F0:R48h)
+// Suggested Value for PM1BLK = 0x1000
+//
+#define R_QNC_PM1BLK_PM1S 0x00
+#define S_QNC_PM1BLK_PM1S 2
+#define B_QNC_PM1BLK_PM1S_ALL (BIT15+BIT14+BIT10+BIT5+BIT0)
+#define B_QNC_PM1BLK_PM1S_WAKE (BIT15)
+#define B_QNC_PM1BLK_PM1S_PCIEWSTS (BIT14)
+#define B_QNC_PM1BLK_PM1S_RTC (BIT10)
+#define B_QNC_PM1BLK_PM1S_GLOB (BIT5)
+#define B_QNC_PM1BLK_PM1S_TO (BIT0)
+#define N_QNC_PM1BLK_PM1S_RTC 10
+
+
+#define R_QNC_PM1BLK_PM1E 0x02
+#define S_QNC_PM1BLK_PM1E 2
+#define B_QNC_PM1BLK_PM1E_PWAKED (BIT14)
+#define B_QNC_PM1BLK_PM1E_RTC (BIT10)
+#define B_QNC_PM1BLK_PM1E_GLOB (BIT5)
+#define N_QNC_PM1BLK_PM1E_RTC 10
+
+#define R_QNC_PM1BLK_PM1C 0x04
+#define B_QNC_PM1BLK_PM1C_SLPEN (BIT13)
+#define B_QNC_PM1BLK_PM1C_SLPTP (BIT12+BIT11+BIT10)
+#define V_S0 0x00000000
+#define V_S3 0x00001400
+#define V_S4 0x00001800
+#define V_S5 0x00001C00
+#define B_QNC_PM1BLK_PM1C_SCIEN (BIT0)
+
+#define R_QNC_PM1BLK_PM1T 0x08
+
+#define R_QNC_LPC_GPE0BLK 0x4C
+#define B_QNC_LPC_GPE0BLK_MASK 0x0000FFC0
+// Suggested Value for GPE0BLK = 0x10C0
+//
+#define R_QNC_GPE0BLK_GPE0S 0x00 // General Purpose Event 0 Status
+#define S_QNC_GPE0BLK_GPE0S 4
+#define B_QNC_GPE0BLK_GPE0S_ALL 0x00003F800 // used to clear the status reg
+#define B_QNC_GPE0BLK_GPE0S_PCIE (BIT17) // PCIE
+#define B_QNC_GPE0BLK_GPE0S_GPIO (BIT14) // GPIO
+#define B_QNC_GPE0BLK_GPE0S_EGPE (BIT13) // External GPE
+#define N_QNC_GPE0BLK_GPE0S_THRM 12
+
+#define R_QNC_GPE0BLK_GPE0E 0x04 // General Purpose Event 0 Enable
+#define S_QNC_GPE0BLK_GPE0E 4
+#define B_QNC_GPE0BLK_GPE0E_PCIE (BIT17) // PCIE
+#define B_QNC_GPE0BLK_GPE0E_GPIO (BIT14) // GPIO
+#define B_QNC_GPE0BLK_GPE0E_EGPE (BIT13) // External GPE
+#define N_QNC_GPE0BLK_GPE0E_THRM 12
+
+#define R_QNC_GPE0BLK_SMIE 0x10 // SMI_B Enable
+#define S_QNC_GPE0BLK_SMIE 4
+#define B_QNC_GPE0BLK_SMIE_ALL 0x0003871F
+#define B_QNC_GPE0BLK_SMIE_APM (BIT4) // APM
+#define B_QNC_GPE0BLK_SMIE_SLP (BIT2) // Sleep
+#define B_QNC_GPE0BLK_SMIE_SWT (BIT1) // Software Timer
+#define N_QNC_GPE0BLK_SMIE_GPIO 9
+#define N_QNC_GPE0BLK_SMIE_ESMI 8
+#define N_QNC_GPE0BLK_SMIE_APM 4
+#define N_QNC_GPE0BLK_SMIE_SPI 3
+#define N_QNC_GPE0BLK_SMIE_SLP 2
+#define N_QNC_GPE0BLK_SMIE_SWT 1
+
+#define R_QNC_GPE0BLK_SMIS 0x14 // SMI Status Register.
+#define S_QNC_GPE0BLK_SMIS 4
+#define B_QNC_GPE0BLK_SMIS_ALL 0x0003871F
+#define B_QNC_GPE0BLK_SMIS_EOS (BIT31) // End of SMI
+#define B_QNC_GPE0BLK_SMIS_APM (BIT4) // APM
+#define B_QNC_GPE0BLK_SMIS_SPI (BIT3) // SPI
+#define B_QNC_GPE0BLK_SMIS_SLP (BIT2) // Sleep
+#define B_QNC_GPE0BLK_SMIS_SWT (BIT1) // Software Timer
+#define B_QNC_GPE0BLK_SMIS_BIOS (BIT0) // BIOS
+#define N_QNC_GPE0BLK_SMIS_GPIO 9
+#define N_QNC_GPE0BLK_SMIS_APM 4
+#define N_QNC_GPE0BLK_SMIS_SPI 3
+#define N_QNC_GPE0BLK_SMIS_SLP 2
+#define N_QNC_GPE0BLK_SMIS_SWT 1
+
+#define R_QNC_GPE0BLK_PMCW 0x28 // Power Management Configuration Core Well
+#define B_QNC_GPE0BLK_PMCW_PSE (BIT31) // Periodic SMI Enable
+
+#define R_QNC_GPE0BLK_PMSW 0x2C // Power Management Configuration Suspend/Resume Well
+#define B_QNC_GPE0BLK_PMSW_DRAM_INIT (BIT0) // Dram Initialization Sctrachpad
+
+#define R_QNC_LPC_ACTL 0x58
+#define V_QNC_LPC_ACTL_SCIS_IRQ9 0x00
+
+//
+// Number of PIRQs supported. PIRQA~PIRQH
+//
+#define QNC_NUMBER_PIRQS 8
+#define R_QNC_LPC_PIRQA_ROUT 0x60
+#define R_QNC_LPC_PIRQB_ROUT 0x61
+#define R_QNC_LPC_PIRQC_ROUT 0x62
+#define R_QNC_LPC_PIRQD_ROUT 0x63
+#define R_QNC_LPC_PIRQE_ROUT 0x64
+#define R_QNC_LPC_PIRQF_ROUT 0x65
+#define R_QNC_LPC_PIRQG_ROUT 0x66
+#define R_QNC_LPC_PIRQH_ROUT 0x67
+
+//
+// Bit values are the same for R_TNC_LPC_PIRQA_ROUT to
+// R_TNC_LPC_PIRQH_ROUT
+#define B_QNC_LPC_PIRQX_ROUT (BIT3+BIT2+BIT1+BIT0)
+
+#define R_QNC_LPC_WDTBA 0x84
+// Watchdog Timer register offsets from WDTBASE (in R_QNC_LPC_WDTBA)------------BEGIN
+#define R_QNC_LPC_WDT_WDTCR 0x10
+#define R_QNC_LPC_WDT_WDTLR 0x18
+// Watchdog Timer register offsets from WDTBASE (in R_QNC_LPC_WDTBA)--------------END
+
+#define R_QNC_LPC_FWH_BIOS_DEC 0xD4
+#define B_QNC_LPC_FWH_BIOS_DEC_F8 (BIT31)
+#define B_QNC_LPC_FWH_BIOS_DEC_F0 (BIT30)
+#define B_QNC_LPC_FWH_BIOS_DEC_E8 (BIT29)
+#define B_QNC_LPC_FWH_BIOS_DEC_E0 (BIT28)
+#define B_QNC_LPC_FWH_BIOS_DEC_D8 (BIT27)
+#define B_QNC_LPC_FWH_BIOS_DEC_D0 (BIT26)
+#define B_QNC_LPC_FWH_BIOS_DEC_C8 (BIT25)
+#define B_QNC_LPC_FWH_BIOS_DEC_C0 (BIT24)
+
+#define R_QNC_LPC_BIOS_CNTL 0xD8
+#define S_QNC_LPC_BIOS_CNTL 4
+#define B_QNC_LPC_BIOS_CNTL_PFE (BIT8)
+#define B_QNC_LPC_BIOS_CNTL_SMM_BWP (BIT5)
+#define B_QNC_LPC_BIOS_CNTL_BCD (BIT2)
+#define B_QNC_LPC_BIOS_CNTL_BLE (BIT1)
+#define B_QNC_LPC_BIOS_CNTL_BIOSWE (BIT0)
+#define N_QNC_LPC_BIOS_CNTL_BLE 1
+#define N_QNC_LPC_BIOS_CNTL_BIOSWE 0
+
+#define R_QNC_LPC_RCBA 0xF0
+#define B_QNC_LPC_RCBA_MASK 0xFFFFC000
+#define B_QNC_LPC_RCBA_EN (BIT0)
+
+//---------------------------------------------------------------------------
+// Fixed IO Decode on QuarkNcSocId
+//
+// 20h(2B) 24h(2B) 28h(2B) 2Ch(2B) 30h(2B) 34h(2B) 38h(2B) 3Ch(2B) : R/W 8259 master
+// 40h(3B): R/W 8254
+// 43h(1B): W 8254
+// 50h(3B): R/W 8254
+// 53h(1B): W 8254
+// 61h(1B): R/W NMI Controller
+// 63h(1B): R/W NMI Controller - can be disabled
+// 65h(1B): R/W NMI Controller - can be disabled
+// 67h(1B): R/W NMI Controller - can be disabled
+// 70h(1B): W NMI & RTC
+// 71h(1B): R/W RTC
+// 72h(1B): R RTC; W NMI&RTC
+// 73h(1B): R/W RTC
+// 74h(1B): R RTC; W NMI&RTC
+// 75h(1B): R/W RTC
+// 76h(1B): R RTC; W NMI&RTC
+// 77h(1B): R/W RTC
+// 84h(3B): R/W Internal/LPC
+// 88h(1B): R/W Internal/LPC
+// 8Ch(3B): R/W Internal/LPC
+// A0h(2B) A4h(2B) A8h(2B) ACh(2B) B0h(2B) B4h(2B) B8h(2B) BCh(2B): R/W 8259 slave
+// B2h(1B) B3h(1B): R/W Power management
+// 3B0h-3BBh: R/W VGA
+// 3C0h-3DFh: R/W VGA
+// CF8h(4B): R/W Internal
+// CF9h(1B): R/W LPC
+// CFCh(4B): R/W Internal
+//---------------------------------------------------------------------------
+
+#define R_APM_CNT 0xB2
+
+//
+// Reset Generator I/O Port
+//
+#define RST_CNT 0xCF9
+#define B_RST_CNT_COLD_RST (BIT3) // Cold reset
+#define B_RST_CNT_WARM_RST (BIT1) // Warm reset
+
+//
+// Processor interface registers (NMI)
+//
+
+#define PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0 20
+#define PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1 21
+#define PCI_FUNCTION_NUMBER_QNC_IOSF2AHB 0
+
+//
+// Pci Express Root Ports (D23:F0/F1)
+//
+#define PCI_DEVICE_NUMBER_PCIE_ROOTPORT 23
+#define PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 0
+#define PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1 1
+
+#define MAX_PCI_EXPRESS_ROOT_PORTS 2
+
+#define R_QNC_PCIE_BNUM 0x18
+#define R_QNC_PCIE_CAP_PTR 0x34
+
+#define PCIE_CAPID 0x10 //PCIE Capability ID
+#define PCIE_CAP_EXT_HEARDER_OFFSET 0x100 //PCIE Capability ID
+#define PCIE_DEV_CAP_OFFSET 0x04 //PCIE Device Capability reg offset
+#define PCIE_LINK_CAP_OFFSET 0x0C //PCIE Link Capability reg offset
+#define PCIE_LINK_CNT_OFFSET 0x10 //PCIE Link control reg offset
+#define PCIE_LINK_STS_OFFSET 0x12 //PCIE Link status reg offset
+#define PCIE_SLOT_CAP_OFFSET 0x14 //PCIE Link Capability reg offset
+
+#define R_QNC_PCIE_XCAP 0x42 //~ 43h
+#define B_QNC_PCIE_XCAP_SI (BIT8) //slot implemented
+#define R_QNC_PCIE_DCAP 0x44 //~ 47h
+#define B_QNC_PCIE_DCAP_E1AL (BIT11 | BIT10 | BIT9) // L1 Acceptable exit latency
+#define B_QNC_PCIE_DCAP_E0AL (BIT8 | BIT7 | BIT6) // L0 Acceptable exit latency
+#define R_QNC_PCIE_DCTL 0x48 //~ 49h
+#define B_QNC_PCIE_DCTL_URE (BIT3) //Unsupported Request Reporting Enable
+#define B_QNC_PCIE_DCTL_FEE (BIT2) //Fatal error Reporting Enable
+#define B_QNC_PCIE_DCTL_NFE (BIT1) //Non Fatal error Reporting Enable
+#define B_QNC_PCIE_DCTL_CEE (BIT0) //Correctable error Reporting Enable
+#define R_QNC_PCIE_LCAP 0x4C //~ 4Fh
+#define B_QNC_PCIE_LCAP_CPM (BIT18) //clock power management supported
+#define B_QNC_PCIE_LCAP_EL1_MASK (BIT17 | BIT16 | BIT15) //L1 Exit latency mask
+#define B_QNC_PCIE_LCAP_EL0_MASK (BIT14 | BIT13 | BIT12) //L0 Exit latency mask
+#define B_QNC_PCIE_LCAP_APMS_MASK (BIT11 | BIT10) //Active state link PM support mask
+#define V_QNC_PCIE_LCAP_APMS_OFFSET 10 //Active state link PM support mask
+#define R_QNC_PCIE_LCTL 0x50 //~ 51h
+#define B_QNC_PCIE_LCTL_CCC (BIT6) // Clock clock configuration
+#define B_QNC_PCIE_LCTL_RL (BIT5) // Retrain link
+#define R_QNC_PCIE_LSTS 0x52 //~ 53h
+#define B_QNC_PCIE_LSTS_SCC (BIT12) //Slot clock configuration
+#define B_QNC_PCIE_LSTS_LT (BIT11) //Link training
+#define R_QNC_PCIE_SLCAP 0x54 //~ 57h
+#define B_QNC_PCIE_SLCAP_MASK_RSV_VALUE 0x0006007F
+#define V_QNC_PCIE_SLCAP_SLV 0x0A //Slot power limit value [14:7]
+#define V_QNC_PCIE_SLCAP_SLV_OFFSET 7 //Slot power limit value offset is 7 [14:7]
+#define V_QNC_PCIE_SLCAP_PSN_OFFSET 19 //Slot number offset is 19 [31:19]
+#define R_QNC_PCIE_SLCTL 0x58 //~ 59h
+#define B_QNC_PCIE_SLCTL_HPE (BIT5) // Hot plug interrupt enable
+#define B_QNC_PCIE_SLCTL_PDE (BIT3) // Presense detect change enable
+#define B_QNC_PCIE_SLCTL_ABE (BIT0) // Attention Button Pressed Enable
+#define R_QNC_PCIE_SLSTS 0x5A //~ 5Bh
+#define B_QNC_PCIE_SLSTS_PDS (BIT6) // Present Detect State = 1b : has device connected
+#define B_QNC_PCIE_SLSTS_PDC (BIT3) // Present Detect changed = 1b : PDS state has changed
+#define B_QNC_PCIE_SLSTS_ABP (BIT0) // Attention Button Pressed
+#define R_QNC_PCIE_RCTL 0x5C //~ 5Dh
+#define B_QNC_PCIE_RCTL_PIE (BIT3) //Root PCI-E PME Interrupt Enable
+#define B_QNC_PCIE_RCTL_SFE (BIT2) //Root PCI-E System Error on Fatal Error Enable
+#define B_QNC_PCIE_RCTL_SNE (BIT1) //Root PCI-E System Error on Non-Fatal Error Enable
+#define B_QNC_PCIE_RCTL_SCE (BIT0) //Root PCI-E System Error on Correctable Error Enable
+#define R_QNC_PCIE_SVID 0x94 //~ 97h
+#define R_QNC_PCIE_CCFG 0xD0 //~ D3h
+#define B_QNC_PCIE_CCFG_UPSD (BIT24) // Upstream Posted Split Disable
+#define B_QNC_PCIE_CCFG_UNRS (BIT15) // Upstream Non-Posted Request Size
+#define B_QNC_PCIE_CCFG_UPRS (BIT14) // Upstream Posted Request Size
+#define R_QNC_PCIE_MPC2 0xD4 //~ D7h
+#define B_QNC_PCIE_MPC2_IPF (BIT11) // ISOF Packet Fast Transmit Mode
+#define R_QNC_PCIE_MPC 0xD8 //~ DBh
+#define B_QNC_PCIE_MPC_PMCE (BIT31) // PM SCI Enable
+#define B_QNC_PCIE_MPC_HPCE (BIT30) // Hot plug SCI enable
+
+#define B_QNC_PCIE_MPC_HPME (BIT1) // Hot plug SMI enable
+#define B_QNC_PCIE_MPC_PMME (BIT0) // PM SMI Enable
+#define R_QNC_PCIE_IOSFSBCTL 0xF6
+#define B_QNC_PCIE_IOSFSBCTL_SBIC_MASK (BIT1 | BIT0) // IOSF Sideband ISM Idle Counter.
+#define B_QNC_PCIE_IOSFSBCTL_SBIC_IDLE_NEVER (BIT1 | BIT0) // Never transition to IDLE.
+
+#define V_PCIE_MAX_TRY_TIMES 200
+
+//
+// Misc PCI register offsets and sizes
+//
+#define R_EFI_PCI_SVID 0x2C
+
+//
+// IO_APIC
+//
+#define IOAPIC_BASE 0xFEC00000
+#define IOAPIC_SIZE 0x1000
+
+//
+// Chipset configuration registers RCBA - "Root Complex Base Address" (D31:F0:RF0h)
+// Suggested Value for RCBA = 0xFED1C000
+//
+
+#define R_QNC_RCRB_SPIBASE 0x3020 // SPI (Serial Peripheral Interface) in RCRB
+#define R_QNC_RCRB_SPIS (R_QNC_RCRB_SPIBASE + 0x00) // SPI Status
+#define B_QNC_RCRB_SPIS_SCL (BIT15) // SPI Configuration Lockdown
+#define B_QNC_RCRB_SPIS_BAS (BIT3) // Blocked Access Status
+#define B_QNC_RCRB_SPIS_CDS (BIT2) // Cycle Done Status
+#define B_QNC_RCRB_SPIS_SCIP (BIT0) // SPI Cycle in Progress
+
+#define R_QNC_RCRB_SPIC (R_QNC_RCRB_SPIBASE + 0x02) // SPI Control
+#define B_QNC_RCRB_SPIC_DC (BIT14) // SPI Data Cycle Enable
+#define B_QNC_RCRB_SPIC_DBC 0x3F00 // SPI Data Byte Count (1..8,16,24,32,40,48,56,64)
+#define B_QNC_RCRB_SPIC_COP (BIT6+BIT5+BIT4) // SPI Cycle Opcode Pointer
+#define B_QNC_RCRB_SPIC_SPOP (BIT3) // Sequence Prefix Opcode Pointer
+#define B_QNC_RCRB_SPIC_ACS (BIT2) // SPI Atomic Cycle Sequence
+#define B_QNC_RCRB_SPIC_SCGO (BIT1) // SPI Cycle Go
+
+#define R_QNC_RCRB_SPIA (R_QNC_RCRB_SPIBASE + 0x04) // SPI Address
+#define B_QNC_RCRB_SPIA_MASK 0x00FFFFFF // SPI Address mask
+#define R_QNC_RCRB_SPID0 (R_QNC_RCRB_SPIBASE + 0x08) // SPI Data 0
+#define R_QNC_RCRB_SPIPREOP (R_QNC_RCRB_SPIBASE + 0x54) // Prefix Opcode Configuration
+#define R_QNC_RCRB_SPIOPTYPE (R_QNC_RCRB_SPIBASE + 0x56) // Opcode Type Configuration
+#define B_QNC_RCRB_SPIOPTYPE_NOADD_READ 0
+#define B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE (BIT0)
+#define B_QNC_RCRB_SPIOPTYPE_ADD_READ (BIT1)
+#define B_QNC_RCRB_SPIOPTYPE_ADD_WRITE (BIT0 + BIT1)
+#define R_QNC_RCRB_SPIOPMENU (R_QNC_RCRB_SPIBASE + 0x58) // Opcode Menu Configuration //R_OPMENU
+
+#define R_QNC_RCRB_SPIPBR0 (R_QNC_RCRB_SPIBASE + 0x60) // Protected BIOS Range 0.
+#define R_QNC_RCRB_SPIPBR1 (R_QNC_RCRB_SPIBASE + 0x64) // Protected BIOS Range 1.
+#define R_QNC_RCRB_SPIPBR2 (R_QNC_RCRB_SPIBASE + 0x68) // Protected BIOS Range 2.
+#define B_QNC_RCRB_SPIPBRn_WPE (BIT31) // Write Protection Enable for above 3 registers.
+
+#define R_QNC_RCRB_AGENT0IR 0x3140 // AGENT0 interrupt route
+#define R_QNC_RCRB_AGENT1IR 0x3142 // AGENT1 interrupt route
+#define R_QNC_RCRB_AGENT2IR 0x3144 // AGENT2 interrupt route
+#define R_QNC_RCRB_AGENT3IR 0x3146 // AGENT3 interrupt route
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.c
new file mode 100644
index 0000000..3181815
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.c
@@ -0,0 +1,246 @@
+/** @file
+ QNC ACPI Timer implements one instance of Timer Library.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+//
+// Include common header file for this module.
+//
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+
+#define V_ACPI_TMR_FREQUENCY 3579545
+#define V_ACPI_TMR_COUNT_SIZE 0x01000000
+#define LPC_PCI_BUS 0x00
+#define LPC_PCI_DEV 0x1F
+#define LPC_PCI_FUNC 0x00
+#define R_LPC_PM1BLK 0x48
+#define R_PM1BLK_PM1T 0x08
+
+/**
+ The constructor function enables ACPI IO space.
+
+ If ACPI I/O space not enabled, this function will enable it.
+ It will always return RETURN_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+RETURN_STATUS
+ EFIAPI
+ IntelQNCAcpiTimerLibConstructor (
+ VOID
+ )
+{
+ if ((PciRead32 (PCI_LIB_ADDRESS (LPC_PCI_BUS, LPC_PCI_DEV, LPC_PCI_FUNC, R_LPC_PM1BLK)) & BIT31) == 0) {
+ //
+ // If ACPI I/O space is not enabled, program ACPI I/O base address and enable it.
+ //
+ PciWrite32 (PCI_LIB_ADDRESS (LPC_PCI_BUS, LPC_PCI_DEV, LPC_PCI_FUNC, R_LPC_PM1BLK), BIT31 | PcdGet16 (PcdPm1blkIoBaseAddress));
+ }
+ return RETURN_SUCCESS;
+}
+
+/**
+ Internal function to read the current tick counter of ACPI.
+
+ Internal function to read the current tick counter of ACPI.
+
+ @return The tick counter read.
+
+**/
+STATIC
+ UINT32
+ InternalAcpiGetTimerTick (
+ VOID
+ )
+{
+ return IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_PM1BLK_PM1T);
+}
+
+/**
+ Stalls the CPU for at least the given number of ticks.
+
+ Stalls the CPU for at least the given number of ticks. It's invoked by
+ MicroSecondDelay() and NanoSecondDelay().
+
+ @param Delay A period of time to delay in ticks.
+
+**/
+STATIC
+ VOID
+ InternalAcpiDelay (
+ IN UINT32 Delay
+ )
+{
+ UINT32 Ticks;
+ UINT32 Times;
+
+ Times = Delay >> 22;
+ Delay &= BIT22 - 1;
+ do {
+ //
+ // The target timer count is calculated here
+ //
+ Ticks = InternalAcpiGetTimerTick () + Delay;
+ Delay = BIT22;
+ //
+ // Wait until time out
+ // Delay >= 2^23 could not be handled by this function
+ // Timer wrap-arounds are handled correctly by this function
+ //
+ while ( ((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0 ) {
+ CpuPause ();
+ }
+ } while ( Times-- > 0 );
+}
+
+/**
+ Stalls the CPU for at least the given number of microseconds.
+
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param MicroSeconds The minimum number of microseconds to delay.
+
+ @return MicroSeconds
+
+**/
+UINTN
+ EFIAPI
+ MicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+ InternalAcpiDelay (
+ (UINT32)DivU64x32 (
+ MultU64x32 (
+ MicroSeconds,
+ V_ACPI_TMR_FREQUENCY
+ ),
+ 1000000u
+ )
+ );
+ return MicroSeconds;
+}
+
+/**
+ Stalls the CPU for at least the given number of nanoseconds.
+
+ Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+ @param NanoSeconds The minimum number of nanoseconds to delay.
+
+ @return NanoSeconds
+
+**/
+UINTN
+ EFIAPI
+ NanoSecondDelay (
+ IN UINTN NanoSeconds
+ )
+{
+ InternalAcpiDelay (
+ (UINT32)DivU64x32 (
+ MultU64x32 (
+ NanoSeconds,
+ V_ACPI_TMR_FREQUENCY
+ ),
+ 1000000000u
+ )
+ );
+ return NanoSeconds;
+}
+
+/**
+ Retrieves the current value of a 64-bit free running performance counter.
+
+ Retrieves the current value of a 64-bit free running performance counter. The
+ counter can either count up by 1 or count down by 1. If the physical
+ performance counter counts by a larger increment, then the counter values
+ must be translated. The properties of the counter can be retrieved from
+ GetPerformanceCounterProperties().
+
+ @return The current value of the free running performance counter.
+
+**/
+UINT64
+ EFIAPI
+ GetPerformanceCounter (
+ VOID
+ )
+{
+ return AsmReadTsc();
+}
+
+/**
+ Retrieves the 64-bit frequency in Hz and the range of performance counter
+ values.
+
+ If StartValue is not NULL, then the value that the performance counter starts
+ with immediately after is it rolls over is returned in StartValue. If
+ EndValue is not NULL, then the value that the performance counter end with
+ immediately before it rolls over is returned in EndValue. The 64-bit
+ frequency of the performance counter in Hz is always returned. If StartValue
+ is less than EndValue, then the performance counter counts up. If StartValue
+ is greater than EndValue, then the performance counter counts down. For
+ example, a 64-bit free running counter that counts up would have a StartValue
+ of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+ that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+ @param StartValue The value the performance counter starts with when it
+ rolls over.
+ @param EndValue The value that the performance counter ends with before
+ it rolls over.
+
+ @return The frequency in Hz.
+
+**/
+UINT64
+ EFIAPI
+ GetPerformanceCounterProperties (
+ OUT UINT64 *StartValue, OPTIONAL
+ OUT UINT64 *EndValue OPTIONAL
+ )
+{
+ if ( StartValue != NULL ) {
+ *StartValue = 0;
+ }
+
+ if ( EndValue != NULL ) {
+ *EndValue = V_ACPI_TMR_COUNT_SIZE - 1;
+ }
+
+ return V_ACPI_TMR_FREQUENCY;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.inf
new file mode 100644
index 0000000..4c60276
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.inf
@@ -0,0 +1,68 @@
+## @file
+# Intel QNC Acpi Timer Instance
+#
+# QNC Acpi timer implements one instance of Timer Library. Acpi timer cannot be programmed,
+# so it could be used by any types of drivers, including SMM drivers and Runtime drivers.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IntelQNCAcpiTimerLib
+ FILE_GUID = 276191B6-5272-44f7-9462-3D94B00B2D76
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TimerLib
+
+ CONSTRUCTOR = IntelQNCAcpiTimerLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ IntelQNCAcpiTimerLib.c
+
+[Packages]
+ QuarkSocPkg/QuarkSocPkg.dec
+ MdePkg/MdePkg.dec
+
+
+[LibraryClasses]
+ PcdLib
+ PciLib
+ IoLib
+ BaseLib
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/CommonHeader.h b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/CommonHeader.h
new file mode 100644
index 0000000..cfdf371
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/CommonHeader.h
@@ -0,0 +1,56 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+
+#include <PiPei.h>
+#include <IntelQNCBase.h>
+
+#include <Library/IntelQNCLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CpuLib.h>
+#include <Library/PciCf8Lib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <Library/QNCAccessLib.h>
+#include <IndustryStandard/Pci22.h>
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c
new file mode 100755
index 0000000..5877299
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c
@@ -0,0 +1,870 @@
+/** @file
+ Lib function for Pei QNC.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "CommonHeader.h"
+
+/**
+ This function provides the necessary SOC initialization
+ before MRC running. It sets RCBA, GPIO, PMBASE
+ and some parts of SOC through SOC message method.
+ If the function cannot complete it'll ASSERT().
+**/
+VOID
+EFIAPI
+PeiQNCPreMemInit (
+ VOID
+ )
+{
+ UINT32 RegValue;
+
+ // QNCPortWrite(Port#, Offset, Value)
+
+ //
+ // Set the fixed PRI Status encodings config.
+ //
+ QNCPortWrite (
+ QUARK_NC_MEMORY_ARBITER_SB_PORT_ID,
+ QUARK_NC_MEMORY_ARBITER_REG_ASTATUS,
+ QNC_FIXED_CONFIG_ASTATUS
+ );
+
+ // Sideband register write to Remote Management Unit
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QNC_MSG_TMPM_REG_PMBA, (BIT31 | PcdGet16 (PcdPmbaIoBaseAddress)));
+
+ // Sideband register write to Remote Management Unit
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_SDMA, (BIT31 | PcdGet16 (PcdSpiDmaIoBaseAddress)));
+
+ // Configurable I/O address in iLB (legacy block)
+
+ LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) = BIT31 | PcdGet16 (PcdSmbaIoBaseAddress);
+ LpcPciCfg32 (R_QNC_LPC_GBA_BASE) = BIT31 | PcdGet16 (PcdGbaIoBaseAddress);
+ LpcPciCfg32 (R_QNC_LPC_PM1BLK) = BIT31 | PcdGet16 (PcdPm1blkIoBaseAddress);
+ LpcPciCfg32 (R_QNC_LPC_GPE0BLK) = BIT31 | PcdGet16 (PcdGpe0blkIoBaseAddress);
+ LpcPciCfg32 (R_QNC_LPC_WDTBA) = BIT31 | PcdGet16 (PcdWdtbaIoBaseAddress);
+
+ //
+ // Program RCBA Base Address
+ //
+ LpcPciCfg32AndThenOr (R_QNC_LPC_RCBA, (~B_QNC_LPC_RCBA_MASK), (((UINT32)(PcdGet64 (PcdRcbaMmioBaseAddress))) | B_QNC_LPC_RCBA_EN));
+
+ //
+ // Program Memory Manager fixed config values.
+ //
+
+ RegValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BTHCTRL);
+ RegValue &= ~(DRAM_NON_HOST_RQ_LIMIT_MASK);
+ RegValue |= (V_DRAM_NON_HOST_RQ_LIMIT << DRAM_NON_HOST_RQ_LIMIT_BP);
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BTHCTRL, RegValue);
+
+ //
+ // Program iCLK fixed config values.
+ //
+ QncIClkAndThenOr (
+ QUARK_ICLK_MUXTOP,
+ (UINT32) ~(B_MUXTOP_FLEX2_MASK | B_MUXTOP_FLEX1_MASK),
+ (V_MUXTOP_FLEX2 << B_MUXTOP_FLEX2_BP) | (V_MUXTOP_FLEX1 << B_MUXTOP_FLEX1_BP)
+ );
+ QncIClkAndThenOr (
+ QUARK_ICLK_REF2_DBUFF0,
+ (UINT32) ~(BIT0), // bit[0] cleared
+ 0
+ );
+ QncIClkOr (
+ QUARK_ICLK_SSC1,
+ BIT0 // bit[0] set
+ );
+ QncIClkOr (
+ QUARK_ICLK_SSC2,
+ BIT0 // bit[0] set
+ );
+ QncIClkOr (
+ QUARK_ICLK_SSC3,
+ BIT0 // bit[0] set
+ );
+
+ //
+ // Set RMU DMA disable bit post boot.
+ //
+ if(FeaturePcdGet(PcdRmuDmaLock)) {
+ RegValue = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_OPTIONS_1);
+ RegValue |= OPTIONS_1_DMA_DISABLE;
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_OPTIONS_1, RegValue);
+ }
+}
+
+/**
+ Do north cluster init which needs to be done AFTER MRC init.
+
+ @param VOID
+
+ @retval VOID
+**/
+
+VOID
+EFIAPI
+PeiQNCPostMemInit (
+ VOID
+ )
+{
+ //
+ // Program SVID/SID the same as VID/DID for all devices except root ports.
+ //
+ QNCMmPci32(0, MC_BUS, MC_DEV, MC_FUN, R_EFI_PCI_SVID) = QNCMmPci32(0, MC_BUS, MC_DEV, MC_FUN, PCI_VENDOR_ID_OFFSET);
+ QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, PCI_VENDOR_ID_OFFSET);
+ QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, PCI_VENDOR_ID_OFFSET);
+ QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, PCI_VENDOR_ID_OFFSET);
+ return;
+}
+
+/**
+ Used to check QNC if it's S3 state. Clear the register state after query.
+
+ @retval TRUE if it's S3 state.
+ @retval FALSE if it's not S3 state.
+
+**/
+BOOLEAN
+EFIAPI
+QNCCheckS3AndClearState (
+ VOID
+ )
+{
+ BOOLEAN S3WakeEventFound;
+ UINT16 Pm1Sts;
+ UINT16 Pm1En;
+ UINT16 Pm1Cnt;
+ UINT32 Gpe0Sts;
+ UINT32 Gpe0En;
+ UINT32 NewValue;
+
+ S3WakeEventFound = FALSE;
+
+ //
+ // Read the ACPI registers,
+ //
+ Pm1Sts = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S);
+ Pm1En = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);
+ Pm1Cnt = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
+ Gpe0Sts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S);
+ Gpe0En = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E);
+
+ //
+ // Clear Power Management 1 Enable Register and
+ // General Purpost Event 0 Enables Register
+ //
+ IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, 0);
+ IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E, 0);
+
+ if ((Pm1Sts & B_QNC_PM1BLK_PM1S_WAKE) != 0 && (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) == V_S3) {
+
+ //
+ // Detect the actual WAKE event
+ //
+ if ((Pm1Sts & B_QNC_PM1BLK_PM1S_RTC) && (Pm1En & B_QNC_PM1BLK_PM1E_RTC)) {
+ DEBUG ((EFI_D_INFO, "S3 Wake Event - RTC Alarm event detected\n"));
+ S3WakeEventFound = TRUE;
+ }
+ if ((Pm1Sts & B_QNC_PM1BLK_PM1S_PCIEWSTS) && !(Pm1En & B_QNC_PM1BLK_PM1E_PWAKED)) {
+ DEBUG ((EFI_D_INFO, "S3 Wake Event - PCIe WAKE detected\n"));
+ S3WakeEventFound = TRUE;
+ }
+ if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_PCIE) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_PCIE)) {
+ DEBUG ((EFI_D_INFO, "S3 Wake Event - PCIe event detected\n"));
+ S3WakeEventFound = TRUE;
+ }
+ if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_GPIO) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_GPIO)) {
+ DEBUG ((EFI_D_INFO, "S3 Wake Event - GPIO event detected\n"));
+ S3WakeEventFound = TRUE;
+ }
+ if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_EGPE) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_EGPE)) {
+ DEBUG ((EFI_D_INFO, "S3 Wake Event - External GPE event detected\n"));
+ S3WakeEventFound = TRUE;
+ }
+ if (S3WakeEventFound == FALSE) {
+ DEBUG ((EFI_D_INFO, "S3 Wake Event - Unknown event detected!!!!!\n"));
+ }
+
+ //
+ // If no Power Button Override event occurs and one enabled wake event occurs,
+ // just do S3 resume and clear the state.
+ //
+ IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, (Pm1Cnt & (~B_QNC_PM1BLK_PM1C_SLPTP)));
+
+ //
+ // Set EOS to de Assert SMI
+ //
+ IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);
+
+ //
+ // Enable SMI globally
+ //
+ NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ NewValue |= SMI_EN;
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Used to check QNC if system wakes up from power on reset. Clear the register state after query.
+
+ @retval TRUE if system wakes up from power on reset
+ @retval FALSE if system does not wake up from power on reset
+
+**/
+BOOLEAN
+EFIAPI
+QNCCheckPowerOnResetAndClearState (
+ VOID
+ )
+{
+ UINT16 Pm1Sts;
+ UINT16 Pm1Cnt;
+
+ //
+ // Read the ACPI registers,
+ // PM1_STS information cannot be lost after power down, unless CMOS is cleared.
+ //
+ Pm1Sts = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S);
+ Pm1Cnt = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
+
+ //
+ // If B_SLP_TYP is S5
+ //
+ if ((Pm1Sts & B_QNC_PM1BLK_PM1S_WAKE) != 0 && (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) == V_S5) {
+ IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, (Pm1Cnt & (~B_QNC_PM1BLK_PM1C_SLPTP)));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ This function is used to clear SMI and wake status.
+
+**/
+VOID
+EFIAPI
+QNCClearSmiAndWake (
+ VOID
+ )
+{
+ UINT32 Gpe0Sts;
+ UINT32 SmiSts;
+
+ //
+ // Read the ACPI registers
+ //
+ Gpe0Sts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S);
+ SmiSts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);
+
+ //
+ // Clear any SMI or wake state from the boot
+ //
+ Gpe0Sts |= B_QNC_GPE0BLK_GPE0S_ALL;
+ SmiSts |= B_QNC_GPE0BLK_SMIS_ALL;
+
+ //
+ // Write them back
+ //
+ IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S, Gpe0Sts);
+ IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, SmiSts);
+}
+
+/** Send DRAM Ready opcode.
+
+ @param[in] OpcodeParam Parameter to DRAM ready opcode.
+
+ @retval VOID
+**/
+VOID
+EFIAPI
+QNCSendOpcodeDramReady (
+ IN UINT32 OpcodeParam
+ )
+{
+
+ //
+ // Before sending DRAM ready place invalid value in Scrub Config.
+ //
+ QNCPortWrite (
+ QUARK_NC_RMU_SB_PORT_ID,
+ QUARK_NC_ECC_SCRUB_CONFIG_REG,
+ SCRUB_CFG_INVALID
+ );
+
+ //
+ // Send opcode and use param to notify HW of new RMU firmware location.
+ //
+ McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = OpcodeParam;
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_SHADOW_DW (QUARK_NC_RMU_SB_PORT_ID, 0);
+
+ //
+ // HW completed tasks on DRAM ready when scrub config read back as zero.
+ //
+ while (QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG) != 0) {
+ MicroSecondDelay (10);
+ }
+}
+
+/**
+
+ Relocate RMU Main binary to memory after MRC to improve performance.
+
+ @param[in] DestBaseAddress - Specify the new memory address for the RMU Main binary.
+ @param[in] SrcBaseAddress - Specify the current memory address for the RMU Main binary.
+ @param[in] Size - Specify size of the RMU Main binary.
+
+ @retval VOID
+
+**/
+VOID
+EFIAPI
+RmuMainRelocation (
+ IN CONST UINT32 DestBaseAddress,
+ IN CONST UINT32 SrcBaseAddress,
+ IN CONST UINTN Size
+ )
+{
+ //
+ // Shadow RMU Main binary into main memory.
+ //
+ CopyMem ((VOID *)(UINTN)DestBaseAddress,(VOID *)(UINTN) SrcBaseAddress, Size);
+}
+
+
+/**
+ Get the total memory size
+
+**/
+UINT32
+QNCGetTotalMemorysize (
+ VOID
+ )
+{
+ return QNCPortRead(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG) && HMBOUND_MASK;
+
+}
+
+
+/**
+ Get the memory range of TSEG.
+ The TSEG's memory is below TOLM.
+
+ @param[out] BaseAddress The base address of TSEG's memory range
+ @param[out] MemorySize The size of TSEG's memory range
+
+**/
+VOID
+EFIAPI
+QNCGetTSEGMemoryRange (
+ OUT UINT64 *BaseAddress,
+ OUT UINT64 *MemorySize
+ )
+{
+ UINT64 Register = 0;
+ UINT64 SMMAddress = 0;
+
+ Register = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
+
+ //
+ // Get the SMRAM Base address
+ //
+ SMMAddress = Register & SMM_START_MASK;
+ *BaseAddress = LShift16 (SMMAddress);
+
+ //
+ // Get the SMRAM size
+ //
+ SMMAddress = ((Register & SMM_END_MASK) | (~SMM_END_MASK)) + 1;
+ *MemorySize = SMMAddress - (*BaseAddress);
+
+ DEBUG ((
+ EFI_D_INFO,
+ "TSEG's memory range: BaseAddress = 0x%x, Size = 0x%x\n",
+ (UINT32)*BaseAddress,
+ (UINT32)*MemorySize
+ ));
+}
+
+
+/**
+ This routine is the chipset code that accepts a request to "open" a region of SMRAM.
+ The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
+ The use of "open" means that the memory is visible from all boot-service
+ and SMM agents.
+
+ @retval FALSE Cannot open a locked SMRAM region
+ @retval TRUE Success to open SMRAM region.
+**/
+BOOLEAN
+EFIAPI
+QNCOpenSmramRegion (
+ VOID
+ )
+{
+ UINT32 Smram;
+ UINT32 SmmOpen;
+
+ SmmOpen = (SMM_WRITE_OPEN | SMM_READ_OPEN);
+
+ // Read the SMRAM register
+ Smram = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
+
+ //
+ // Is the platform locked?
+ //
+ if (Smram & SMM_LOCKED) {
+ // Cannot Open a locked region
+ DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n"));
+ return FALSE;
+ }
+
+ //
+ // Open all SMRAM regions for Host access only
+ //
+ Smram |= SmmOpen;
+ Smram &= ~(NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN);
+
+ //
+ // Write the SMRAM register
+ //
+ QncHsmmcWrite (Smram);
+
+ return TRUE;
+}
+
+/**
+ This routine is the chipset code that accepts a request to "close" a region of SMRAM.
+ The region could be legacy AB or TSEG near top of physical memory.
+ The use of "close" means that the memory is only visible from SMM agents,
+ not from BS or RT code.
+
+ @retval FALSE Cannot open a locked SMRAM region
+ @retval TRUE Success to open SMRAM region.
+**/
+BOOLEAN
+EFIAPI
+QNCCloseSmramRegion (
+ VOID
+ )
+{
+ UINT32 Smram;
+ UINT32 SmmOpen;
+
+ SmmOpen = (SMM_WRITE_OPEN | SMM_READ_OPEN | NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN);
+
+ // Read the SMRAM register
+ Smram = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
+
+ //
+ // Is the platform locked?
+ //
+ if(Smram & SMM_LOCKED) {
+ // Cannot Open a locked region
+ DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n"));
+ return FALSE;
+ }
+
+ Smram &= (~SmmOpen);
+
+ QncHsmmcWrite (Smram);
+
+ return TRUE;
+}
+
+/**
+ This routine is the chipset code that accepts a request to "lock" SMRAM.
+ The region could be legacy AB or TSEG near top of physical memory.
+ The use of "lock" means that the memory can no longer be opened
+ to BS state.
+**/
+VOID
+EFIAPI
+QNCLockSmramRegion (
+ VOID
+ )
+{
+ UINT32 Smram;
+
+ // Read the SMRAM register
+ Smram = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
+ Smram |= SMM_LOCKED;
+
+ QncHsmmcWrite (Smram);
+
+ return;
+}
+
+
+/**
+ Updates the PAM registers in the MCH for the requested range and mode.
+
+ @param Start The start address of the memory region
+ @param Length The length, in bytes, of the memory region
+ @param ReadEnable Pointer to the boolean variable on whether to enable read for legacy memory section.
+ If NULL, then read attribute will not be touched by this call.
+ @param ReadEnable Pointer to the boolean variable on whether to enable write for legacy memory section.
+ If NULL, then write attribute will not be touched by this call.
+ @param Granularity A pointer to granularity, in bytes, that the PAM registers support
+
+ @retval RETURN_SUCCESS The PAM registers in the MCH were updated
+ @retval RETURN_INVALID_PARAMETER The memory range is not valid in legacy region.
+
+**/
+EFI_STATUS
+EFIAPI
+QNCLegacyRegionManipulation (
+ IN UINT32 Start,
+ IN UINT32 Length,
+ IN BOOLEAN *ReadEnable,
+ IN BOOLEAN *WriteEnable,
+ OUT UINT32 *Granularity
+ )
+{
+ //
+ // Do nothing cos no such support on QNC
+ //
+ return RETURN_SUCCESS;
+}
+
+/**
+ Determine if QNC is supported.
+
+ @retval FALSE QNC is not supported.
+ @retval TRUE QNC is supported.
+**/
+BOOLEAN
+IsQncSupported (
+ VOID
+ )
+{
+ UINT16 SocVendorId;
+ UINT16 SocDeviceId;
+
+ SocVendorId = MmioRead16 (
+ PciDeviceMmBase (MC_BUS,
+ MC_DEV,
+ MC_FUN) + PCI_VENDOR_ID_OFFSET
+ );
+
+ SocDeviceId = MmioRead16 (
+ PciDeviceMmBase (MC_BUS,
+ MC_DEV,
+ MC_FUN) + PCI_DEVICE_ID_OFFSET
+ );
+
+ //
+ // Verify that this is a supported chipset
+ //
+ if ((SocVendorId != QUARK_MC_VENDOR_ID) || ((SocDeviceId != QUARK_MC_DEVICE_ID) && (SocDeviceId != QUARK2_MC_DEVICE_ID))) {
+ DEBUG ((DEBUG_ERROR, "QNC code doesn't support the Soc VendorId:0x%04x Soc DeviceId:0x%04x!\n", SocVendorId, SocDeviceId));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Enable SMI detection of legacy flash access violations.
+**/
+VOID
+EFIAPI
+QncEnableLegacyFlashAccessViolationSmi (
+ VOID
+ )
+{
+ UINT32 BcValue;
+
+ BcValue = LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL);
+
+ //
+ // Clear BIOSWE & set BLE.
+ //
+ BcValue &= (~B_QNC_LPC_BIOS_CNTL_BIOSWE);
+ BcValue |= (B_QNC_LPC_BIOS_CNTL_BLE);
+
+ LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL) = BcValue;
+
+ DEBUG ((EFI_D_INFO, "BIOS Control Lock Enabled!\n"));
+}
+
+/**
+ Setup RMU Thermal sensor registers for Vref mode.
+**/
+VOID
+EFIAPI
+QNCThermalSensorSetVRefMode (
+ VOID
+ )
+{
+ UINT32 Tscgf1Config;
+ UINT32 Tscgf2Config;
+ UINT32 Tscgf2Config2;
+
+ Tscgf1Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG);
+ Tscgf2Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG);
+ Tscgf2Config2 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2);
+
+ Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK);
+ Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCURRENTSEL_VREF_MODE << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP);
+
+ Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGEN);
+ Tscgf1Config |= (V_TSCGF1_CONFIG_IBGEN_VREF_MODE << B_TSCGF1_CONFIG_IBGEN_BP);
+
+ Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ISPARECTRL_MASK);
+ Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ISPARECTRL_VREF_MODE << B_TSCGF2_CONFIG2_ISPARECTRL_BP);
+
+ Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK);
+ Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCOARSETUNE_VREF_MODE << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP);
+
+ Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK);
+ Tscgf2Config |= (V_TSCGF2_CONFIG_IDSCONTROL_VREF_MODE << B_TSCGF2_CONFIG_IDSCONTROL_BP);
+
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, Tscgf1Config);
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, Tscgf2Config);
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, Tscgf2Config2);
+}
+
+/**
+ Setup RMU Thermal sensor registers for Ratiometric mode.
+**/
+VOID
+EFIAPI
+QNCThermalSensorSetRatiometricMode (
+ VOID
+ )
+{
+ UINT32 Tscgf1Config;
+ UINT32 Tscgf2Config;
+ UINT32 Tscgf2Config2;
+ UINT32 Tscgf3Config;
+
+ Tscgf1Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG);
+ Tscgf2Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG);
+ Tscgf2Config2 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2);
+ Tscgf3Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG);
+
+ Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK);
+ Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCURRENTSEL_RATIO_MODE << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP);
+
+ Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCHOPSEL_MASK);
+ Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCHOPSEL_RATIO_MODE << B_TSCGF1_CONFIG_ISNSCHOPSEL_BP);
+
+ Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSINTERNALVREFEN);
+ Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSINTERNALVREFEN_RATIO_MODE << B_TSCGF1_CONFIG_ISNSINTERNALVREFEN_BP);
+
+ Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGEN);
+ Tscgf1Config |= (V_TSCGF1_CONFIG_IBGEN_RATIO_MODE << B_TSCGF1_CONFIG_IBGEN_BP);
+
+ Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGCHOPEN);
+ Tscgf1Config |= (V_TSCGF1_CONFIG_IBGCHOPEN_RATIO_MODE << B_TSCGF1_CONFIG_IBGCHOPEN_BP);
+
+ Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCONFIGSEL_MASK);
+ Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCONFIGSEL_RATIO_MODE << B_TSCGF2_CONFIG2_ICALCONFIGSEL_BP);
+
+ Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ISPARECTRL_MASK);
+ Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ISPARECTRL_RATIO_MODE << B_TSCGF2_CONFIG2_ISPARECTRL_BP);
+
+ Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK);
+ Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCOARSETUNE_RATIO_MODE << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP);
+
+ Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK);
+ Tscgf2Config |= (V_TSCGF2_CONFIG_IDSCONTROL_RATIO_MODE << B_TSCGF2_CONFIG_IDSCONTROL_BP);
+
+ Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSTIMING_MASK);
+ Tscgf2Config |= (V_TSCGF2_CONFIG_IDSTIMING_RATIO_MODE << B_TSCGF2_CONFIG_IDSTIMING_BP);
+
+ Tscgf3Config &= ~(B_TSCGF3_CONFIG_ITSGAMMACOEFF_MASK);
+ Tscgf3Config |= (V_TSCGF3_CONFIG_ITSGAMMACOEFF_RATIO_MODE << B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP);
+
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, Tscgf1Config);
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, Tscgf2Config);
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, Tscgf2Config2);
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, Tscgf3Config);
+}
+
+/**
+ Setup RMU Thermal sensor trip point values.
+
+ @param[in] CatastrophicTripOnDegreesCelsius - Catastrophic set trip point threshold.
+ @param[in] HotTripOnDegreesCelsius - Hot set trip point threshold.
+ @param[in] HotTripOffDegreesCelsius - Hot clear trip point threshold.
+
+ @retval EFI_SUCCESS Trip points setup.
+ @retval EFI_INVALID_PARAMETER Invalid trip point value.
+
+**/
+EFI_STATUS
+EFIAPI
+QNCThermalSensorSetTripValues (
+ IN CONST UINTN CatastrophicTripOnDegreesCelsius,
+ IN CONST UINTN HotTripOnDegreesCelsius,
+ IN CONST UINTN HotTripOffDegreesCelsius
+ )
+{
+ UINT32 RegisterValue;
+
+ //
+ // Register fields are 8-bit temperature values of granularity 1 degree C
+ // where 0x00 corresponds to -50 degrees C
+ // and 0xFF corresponds to 205 degrees C.
+ //
+ // User passes unsigned values in degrees Celsius so trips < 0 not supported.
+ //
+ // Add 50 to user values to get values for register fields.
+ //
+
+ if ((CatastrophicTripOnDegreesCelsius > 205) || (HotTripOnDegreesCelsius > 205) || (HotTripOffDegreesCelsius > 205)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set new values.
+ //
+ RegisterValue =
+ ((0 + 50) << TS_CAT_TRIP_CLEAR_THOLD_BP) | // Cat Trip Clear value must be less than Cat Trip Set Value.
+ ((CatastrophicTripOnDegreesCelsius + 50) << TS_CAT_TRIP_SET_THOLD_BP) |
+ ((HotTripOnDegreesCelsius + 50) << TS_HOT_TRIP_SET_THOLD_BP) |
+ ((HotTripOffDegreesCelsius + 50) << TS_HOT_TRIP_CLEAR_THOLD_BP)
+ ;
+
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP, RegisterValue);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enable RMU Thermal sensor with a Catastrophic Trip point.
+
+ @retval EFI_SUCCESS Trip points setup.
+ @retval EFI_INVALID_PARAMETER Invalid trip point value.
+
+**/
+EFI_STATUS
+EFIAPI
+QNCThermalSensorEnableWithCatastrophicTrip (
+ IN CONST UINTN CatastrophicTripOnDegreesCelsius
+ )
+{
+ UINT32 Tscgf3Config;
+ UINT32 TsModeReg;
+ UINT32 TsTripReg;
+
+ //
+ // Trip Register fields are 8-bit temperature values of granularity 1 degree C
+ // where 0x00 corresponds to -50 degrees C
+ // and 0xFF corresponds to 205 degrees C.
+ //
+ // User passes unsigned values in degrees Celsius so trips < 0 not supported.
+ //
+ // Add 50 to user values to get values for register fields.
+ //
+
+ if (CatastrophicTripOnDegreesCelsius > 205) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Tscgf3Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG);
+ TsModeReg = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_MODE);
+ TsTripReg = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP);
+
+ //
+ // Setup Catastrophic Trip point.
+ //
+ TsTripReg &= ~(TS_CAT_TRIP_SET_THOLD_MASK);
+ TsTripReg |= ((CatastrophicTripOnDegreesCelsius + 50) << TS_CAT_TRIP_SET_THOLD_BP);
+ TsTripReg &= ~(TS_CAT_TRIP_CLEAR_THOLD_MASK);
+ TsTripReg |= ((0 + 50) << TS_CAT_TRIP_CLEAR_THOLD_BP); // Cat Trip Clear value must be less than Cat Trip Set Value.
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP, TsTripReg);
+
+ //
+ // To enable the TS do the following:
+ // 1) Take the TS out of reset by setting itsrst to 0x0.
+ // 2) Enable the TS using RMU Thermal sensor mode register.
+ //
+
+ Tscgf3Config &= ~(B_TSCGF3_CONFIG_ITSRST);
+ TsModeReg |= TS_ENABLE;
+
+ QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, Tscgf3Config);
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_MODE, TsModeReg);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Lock all RMU Thermal sensor control & trip point registers.
+
+**/
+VOID
+EFIAPI
+QNCThermalSensorLockAllRegisters (
+ VOID
+ )
+{
+ UINT32 RegValue;
+ UINT32 LockMask;
+
+ LockMask = TS_LOCK_THRM_CTRL_REGS_ENABLE | TS_LOCK_AUX_TRIP_PT_REGS_ENABLE;
+
+ RegValue = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG);
+ RegValue |= LockMask;
+ QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG, RegValue);
+
+ ASSERT ((LockMask == (QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG) & LockMask)));
+}
+
+/**
+ Set chipset policy for double bit ECC error.
+
+ @param[in] PolicyValue Policy to config on double bit ECC error.
+
+**/
+VOID
+EFIAPI
+QNCPolicyDblEccBitErr (
+ IN CONST UINT32 PolicyValue
+ )
+{
+ UINT32 Register;
+ Register = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_WDT_CONTROL);
+ Register &= ~(B_WDT_CONTROL_DBL_ECC_BIT_ERR_MASK);
+ Register |= PolicyValue;
+ QNCPortWrite (
+ QUARK_NC_RMU_SB_PORT_ID,
+ QUARK_NC_RMU_REG_WDT_CONTROL,
+ Register
+ );
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf
new file mode 100755
index 0000000..fb85f1d
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf
@@ -0,0 +1,87 @@
+## @file
+# Intel QNC Library Instance
+#
+# Intel QNC Library Instance
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IntelQNCLib
+ FILE_GUID = F5B2EA6C-8148-4a4e-88EA-38A4A51F389F
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = IntelQNCLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# HOB Guid C Name: gEfiPciGInfoHobGuid Hob Type: GUID_EXTENSION
+#
+
+[Sources]
+ PciExpress.c
+ IntelQNCLib.c
+ CommonHeader.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ TimerLib
+ DebugLib
+ PcdLib
+ PciLib
+ IoLib
+ PciCf8Lib
+ BaseLib
+ CpuLib
+ QNCAccessLib
+
+[FeaturePcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRmuDmaLock
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSpiDmaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdWdtbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPcieRootPortConfiguration
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c
new file mode 100755
index 0000000..a5e99c9
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c
@@ -0,0 +1,967 @@
+/** @file
+ QNC PCI Express initialization entry
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+
+#define PCIEXP_ROOT_PORT_URE_ENABLE BIT0 // unsupported request reporting enable
+#define PCIEXP_ROOT_PORT_FEE_ENABLE BIT1 // Fatal Error Reporting Enable
+#define PCIEXP_ROOT_PORT_NFE_ENABLE BIT2 // Non-Fatal Error Reporting Enable
+#define PCIEXP_ROOT_PORT_CEE_ENABLE BIT3 // Correctable Error Reporting Enable
+#define PCIEXP_ROOT_PORT_SFE_ENABLE BIT4 // System Error on Fatal Error Enable
+#define PCIEXP_ROOT_PORT_SNE_ENABLE BIT5 // System Error on Non-Fatal Error Enable
+#define PCIEXP_ROOT_PORT_SCE_ENABLE BIT6 // System Error on Correctable Error Enable
+
+EFI_STATUS
+PcieStall (
+ IN UINTN Microseconds
+ )
+{
+ MicroSecondDelay (Microseconds);
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Bus Bus number of the interested device
+ @param[in] Device Device number of the interested device
+ @param[in] Function Function number of the interested device
+ @param[in] CapId Capability ID to be scanned
+
+ @retval Offset of desired CAPID
+
+**/
+UINT32
+PcieFindCapId (
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Function,
+ UINT8 CapId
+ )
+{
+ UINT8 CapHeader;
+
+ //
+ // Always start at Offset 0x34
+ //
+ CapHeader = QNCMmPci8 (0, Bus, Device, Function, R_QNC_PCIE_CAP_PTR);
+
+ if (CapHeader == 0xFF) {
+ return 0;
+ }
+
+ while (CapHeader != 0) {
+ if (QNCMmPci8 (0, Bus, Device, Function, CapHeader) == CapId) {
+ return CapHeader;
+ }
+ CapHeader = QNCMmPci8 (0, Bus, Device, Function, CapHeader + 1);
+ }
+ return 0;
+}
+
+/**
+
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Rreporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Bus Bus number of the interested device
+ @param[in] Device Device number of the interested device
+ @param[in] Function Function number of the interested device
+ @param[in] CapId Capability ID to be scanned
+
+ @retval Offset of desired CAPID
+
+**/
+UINT32
+PcieFindExtendedCapId (
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Function,
+ UINT16 CapId
+ )
+{
+ UINT16 CapHeaderOffset;
+ UINT16 CapHeaderId;
+
+ // Start to search at Offset 0x100
+ // Get Capability Header
+ CapHeaderId = 0;
+ CapHeaderOffset = PCIE_CAP_EXT_HEARDER_OFFSET;
+
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) {
+ CapHeaderId = QNCMmPci16 (0, Bus, Device, Function, CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ return CapHeaderOffset;
+ }
+ CapHeaderOffset = (QNCMmPci16 (0, Bus, Device, Function, CapHeaderOffset + 2) >> 4);
+ }
+ return 0;
+}
+
+/**
+
+ Map Vc on both root port and downstream device
+
+ @param[in] Bus1 Bus number of the root port
+ @param[in] Device1 Device number of the root port
+ @param[in] Function1 Function number of the root port
+ @param[in] Bus2 Bus number of the downstream device
+ @param[in] Device2 Device number of the downstream device
+ @param[in] Function2 Function number of the downstream device
+
+ @retval EFI_SUCCESS Map Vc successful
+
+**/
+EFI_STATUS
+PcieInitTcxVc0 (
+ IN UINT8 Bus1,
+ IN UINT8 Device1,
+ IN UINT8 Function1,
+ IN UINT8 Bus2,
+ IN UINT8 Device2,
+ IN UINT8 Function2
+ )
+{
+ UINT32 Offset;
+
+ //
+ // Initialize TCx-VC0 value on the port to only use TC0
+ //
+ Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2);
+ if (Offset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ QNCMmPci8AndThenOr (0, Bus1, Device1, Function1, (Offset + PCIE_SLOT_CAP_OFFSET), ~0xF, 1);
+
+ // Set TCx-VC0 value on the Endpoint
+
+ Offset = PcieFindExtendedCapId (Bus2, Device2, Function2, 2);
+ if (Offset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ QNCMmPci8AndThenOr (0, Bus2, Device2, Function2, (Offset + PCIE_SLOT_CAP_OFFSET), ~0xF, 1);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Map Traffic Class x to Vc0 on both root port and downstream device
+
+ @param[in] Bus1 Bus number of the root port
+ @param[in] Device1 Device number of the root port
+ @param[in] Function1 Function number of the root port
+ @param[in] Bus2 Bus number of the downstream device
+ @param[in] Device2 Device number of the downstream device
+ @param[in] Function2 Function number of the downstream device
+ @param[in] TCx Traffic Class to be mapped to vc0
+
+ @retval EFI_SUCCESS Map Tcx to Vc0 successful
+
+**/
+EFI_STATUS
+PcieMapTcxVc0 (
+ IN UINT8 Bus1,
+ IN UINT8 Device1,
+ IN UINT8 Function1,
+ IN UINT8 Bus2,
+ IN UINT8 Device2,
+ IN UINT8 Function2,
+ IN UINT8 TCx
+ )
+{
+ UINT32 Offset;
+
+ //
+ // Set TCx-VC0 value on the port
+ //
+
+ Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2);
+ if (Offset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ QNCMmPci8 (0, Bus1, Device1, Function1, (Offset + PCIE_SLOT_CAP_OFFSET)) = (UINT8)(1 << TCx);
+
+ // Set TCx-VC0 value on the Endpoint
+
+ Offset = PcieFindExtendedCapId (Bus2, Device2, Function2, 2);
+ if (Offset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ QNCMmPci8 (0, Bus2, Device2, Function2, (Offset + PCIE_SLOT_CAP_OFFSET)) = (UINT8)(1 << TCx);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Set common clock for both root port and downstream device.
+
+ @param[in] Bus1 Bus number of the root port
+ @param[in] Device1 Device number of the root port
+ @param[in] Function1 Function number of the root port
+ @param[in] Bus2 Device number of the downstream device
+ @param[in] Device2 Function number of the downstream device
+
+ @retval EFI_SUCCESS Set common clock successful
+
+**/
+EFI_STATUS
+PcieSetCommonClock (
+ IN UINT8 Bus1,
+ IN UINT8 Device1,
+ IN UINT8 Function1,
+ IN UINT8 Bus2,
+ IN UINT8 Device2
+ )
+{
+ UINT32 CapOffset1;
+ UINT32 CapOffset2;
+ UINT8 Function2;
+ UINT8 CommonClock;
+ EFI_STATUS Status;
+
+ //
+ // Get the pointer to the Port PCI Express Capability Structure.
+ //
+ CommonClock = 0;
+ CapOffset1 = PcieFindCapId (Bus1, Device1, Function1, PCIE_CAPID);
+ if (CapOffset1 == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Step 1
+ // Read the Slot Clock Configuration bit of the Link status register of the root port and the endpoint device connected to the port
+ // If both components have this bit set to 1, then System BIOS should set the "Common Clock Configuration" bit in the Link Control Registers
+ // for both components at both sides of the link to indicate that components at both ends
+ // of the link use a common clock source
+ //
+
+ //
+ // Check the Port Slot Clock Configuration Bit.
+ //
+ if ((QNCMmPci16 (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_SCC) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Function2 = 0; Function2 < 8; Function2++) {
+ //
+ // Check the Endpoint Slot Clock Configuration Bit.
+ //
+ CapOffset2 = PcieFindCapId (Bus2, Device2, Function2, PCIE_CAPID);
+ if ((CapOffset2 != 0) &&
+ ((QNCMmPci16 (0, Bus2, Device2, Function2, (CapOffset2 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_SCC) != 0)) {
+
+ //
+ // Common clock is supported, set common clock bit on root port
+ // and the endpoint
+ //
+ if (CommonClock == 0) {
+ QNCMmPci8Or (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_CCC);
+ CommonClock++;
+ }
+ QNCMmPci8Or (0, Bus2, Device2, Function2, (CapOffset2 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_CCC);
+ }
+ }
+
+ //
+ // Step 2 If the Common Clock Configuration bit was changed by BIOS in step 1,
+ // System BIOS should initiate a link training by setting the Retrain Link bit
+ // in the Link Control register of the root port (D28:F0/F1 offset
+ // 50h [5]) to "1b" and then poll the Link Training bit in the Link Status
+ // register of the root port (D28:F0/F1/F2/F3/F4/F5 offset 52h [11]) until it is
+ // "0b".
+ //
+ if (CommonClock == 0) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ //
+ // Retrain the Link per PCI Express Specification.
+ //
+ QNCMmPci8Or (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_RL);
+
+ //
+ // Wait until Re-Training has completed.
+ //
+ while ((QNCMmPci16 (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_LT) != 0);
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+
+ Enables the CLKREQ# PM on all the end point functions
+
+ @param[in] Bus Bus number of the downstream device
+ @param[in] Device Device number of the downstream device
+
+ @retval None
+
+**/
+VOID
+PcieSetClkreq (
+ IN UINT8 Bus,
+ IN UINT8 Device
+ )
+{
+ UINT8 Function;
+ UINT32 CapOffset;
+
+ //
+ // Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if
+ // exists then enable the CLKREQ# bit (BIT8) on that function
+ //
+ for (Function = 0; Function < 8; Function++) {
+ //
+ // Find the PCIe Cap Id (offset 10h)
+ //
+ CapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ //
+ // Check if CLKREQ# is supported by the endpoints
+ //
+ if ((QNCMmPci32 (0, Bus, Device, Function, (CapOffset + PCIE_LINK_CAP_OFFSET))
+ && B_QNC_PCIE_LCAP_CPM) != B_QNC_PCIE_LCAP_CPM) {
+ //
+ // CLKREQ# is not supported so dont do anything
+ //
+ return;
+ }
+ }
+
+ //
+ // Now enable the CLKREQ#
+ //
+ for (Function = 0; Function < 8; Function++) {
+ //
+ // Find the PCIe Cap Id (offset 10h)
+ //
+ CapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ QNCMmPci16Or (0, Bus, Device, Function, (CapOffset + PCIE_LINK_CNT_OFFSET), BIT8);
+ }
+}
+
+/**
+
+ Configure ASPM automatically for both root port and downstream device.
+
+ @param[in] RootBus Bus number of the root port
+ @param[in] RootDevice Device number of the root port
+ @param[in] RootFunction Function number of the root port
+ @param[in] EndpointBus Bus number of the downstream device
+ @param[in] EndpointDevice Device number of the downstream device
+ @param[in] EndpointFunction Function number of the downstream device
+ @param[in] LinkAspmVal Currently used ASPM setting
+
+ @retval EFI_SUCCESS Configure ASPM successful
+
+**/
+EFI_STATUS
+PcieSetAspmAuto (
+ IN UINT8 RootBus,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction,
+ IN UINT8 EndpointBus,
+ IN UINT8 EndpointDevice,
+ IN UINT8 EndpointFunction,
+ OUT UINT16 *LinkAspmVal
+ )
+{
+ UINT32 RootPcieCapOffset;
+ UINT32 EndpointPcieCapOffset;
+ UINT16 RootPortAspm;
+ UINT16 EndPointAspm;
+ UINT16 EndPointVendorId;
+ UINT16 EndPointDeviceId;
+ UINT8 EndPointRevId;
+ UINT16 AspmVal;
+ UINT32 PortLxLat;
+ UINT32 EndPointLxLat;
+ UINT32 LxLat;
+
+ //
+ // Get the pointer to the Port PCI Express Capability Structure.
+ //
+ RootPcieCapOffset = PcieFindCapId (RootBus, RootDevice, RootFunction, PCIE_CAPID);
+ if (RootPcieCapOffset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the pointer to the Endpoint PCI Express Capability Structure.
+ //
+ EndpointPcieCapOffset = PcieFindCapId (EndpointBus, EndpointDevice, EndpointFunction, PCIE_CAPID);
+ if (EndpointPcieCapOffset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Obtain initial ASPM settings from respective port capability registers.
+ //
+ RootPortAspm = (QNCMmPci16 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;
+
+ //
+ // Configure downstream device if present.
+ //
+ EndPointAspm = (QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;
+
+ //
+ // Mask APMC with values from lookup table.
+ // RevID of 0xFF applies to all steppings.
+ //
+
+ EndPointVendorId = QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, 0);
+ EndPointDeviceId = QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, 2);
+ EndPointRevId = QNCMmPci8 (0, EndpointBus, EndpointDevice, EndpointFunction, 8);
+
+ // TODO: Mask with latency/acceptable latency comparison results.
+
+ AspmVal = RootPortAspm;
+ if (RootPortAspm > EndPointAspm) {
+ AspmVal = EndPointAspm;
+ }
+
+ //
+ // Check if L1 should be enabled based on port and endpoint L1 exit latency.
+ //
+ if(AspmVal & BIT1) {
+ PortLxLat = QNCMmPci32 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL1_MASK;
+ EndPointLxLat = QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL1_MASK;
+
+ LxLat = PortLxLat;
+ if(PortLxLat < EndPointLxLat) {
+ LxLat = EndPointLxLat;
+ }
+
+ //
+ // check if the value is bigger than endpoint L1 acceptable exit latency, if it is
+ // larger than accepted value, then we should disable L1
+ //
+ LxLat >>= 6;
+ if(LxLat > (QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_DEV_CAP_OFFSET)) & B_QNC_PCIE_DCAP_E1AL)) {
+ AspmVal &= ~BIT1;
+ }
+ }
+
+ //
+ // Check if L0s should be enabled based on port and endpoint L0s exit latency.
+ //
+ if(AspmVal & BIT0) {
+ PortLxLat = QNCMmPci32 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset+ PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL0_MASK;
+ EndPointLxLat = QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL0_MASK;
+
+ LxLat = PortLxLat;
+ if(PortLxLat < EndPointLxLat) {
+ LxLat = EndPointLxLat;
+ }
+
+ //
+ // check if the value is bigger than endpoint L0s acceptable exit latency, if it is
+ // larger than accepted value, then we should disable L0s
+ //
+ LxLat >>= 6;
+ if(LxLat > (QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_DEV_CAP_OFFSET)) & B_QNC_PCIE_DCAP_E0AL)) {
+ AspmVal &= ~BIT0;
+ }
+ }
+
+ RootPortAspm = AspmVal;
+
+ *LinkAspmVal = AspmVal;
+ //
+ // Set Endpoint Aspm
+ //
+ QNCMmPci16AndThenOr (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, AspmVal);
+
+
+ //
+ // Set Root Port Aspm
+ //
+ QNCMmPci16AndThenOr (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, RootPortAspm);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Configure ASPM based on the given setting for the interested device.
+
+ @param[in] Bus Bus number of the interested device
+ @param[in] Device Device number of the interested device
+ @param[in] Function Function number of the interested device
+ @param[in] AspmSetting Aspm setting
+ @param[in] LinkAspmVal Currently used ASPM setting
+
+ @retval EFI_SUCCESS Configure ASPM successful
+
+**/
+EFI_STATUS
+PcieSetAspmManual (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 AspmSetting,
+ OUT UINT16 *LinkAspmVal
+ )
+{
+ UINT32 PcieCapOffset;
+ UINT16 PortAspm;
+
+ //
+ // Get the pointer to the Port PCI Express Capability Structure.
+ //
+ PcieCapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);
+ if (PcieCapOffset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Read the Link Capability register's ASPM setting
+ PortAspm = (QNCMmPci16 (0, Bus, Device, Function, (PcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;
+ // Mask it with the Setup selection
+ PortAspm &= AspmSetting;
+
+ *LinkAspmVal = PortAspm;
+ // Write it to the Link Control register
+ QNCMmPci16AndThenOr (0, Bus, Device, Function, (PcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, PortAspm);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Perform Initialization on one PCI Express root port.
+
+ @param[in] RootPortIndex Index of PCI Express root port
+ @param[in] RootPortConfig Pointer to the given pcie root port configuration
+ @param[in] PciExpressBar Base address of pcie space
+ @param[in] QNCRootComplexBar Base address of root complex
+ @param[in] QNCPmioBase Base address of PM IO space
+ @param[in] QNCGpeBase Base address of gpe IO space
+
+ @retval EFI_SUCCESS Initialization successful
+
+**/
+EFI_STATUS
+QNCRootPortInit (
+ IN UINT32 RootPortIndex,
+ IN PCIEXP_ROOT_PORT_CONFIGURATION *RootPortConfig,
+ IN UINT64 PciExpressBar,
+ IN UINT32 QNCRootComplexBar,
+ IN UINT32 QNCPmioBase,
+ IN UINT32 QNCGpeBase
+ )
+{
+ UINT64 RPBase;
+ UINT64 EndPointBase;
+ UINT64 LpcBase;
+ UINT16 AspmVal;
+ UINT16 SlotStatus;
+ UINTN Index;
+ UINT32 CapOffset;
+ UINT32 DwordReg;
+
+ RPBase = PciExpressBar + (((PCI_BUS_NUMBER_QNC << 8) + ((PCI_DEVICE_NUMBER_PCIE_ROOTPORT) << 3) + ((PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex) << 0)) << 12);
+ LpcBase = PciExpressBar + (((PCI_BUS_NUMBER_QNC << 8) + (31 << 3) + (0 << 0)) << 12);
+ CapOffset = PcieFindCapId (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), PCIE_CAPID);
+
+ if (CapOffset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Initialize "Slot Implmemented Bit" for this root port
+ //
+ if (RootPortConfig[RootPortIndex].Bits.SlotImplemented) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_XCAP, B_QNC_PCIE_XCAP_SI);
+ }
+
+ //
+ // For Root Port Slots Numbering on the CRBs.
+ // Root Port 0 = Slot 1
+ // Root Port 1 = Slot 2
+ // Root Port 2 = Slot 3
+ // Root Port 3 = Slot 4
+ //
+ DwordReg = QNCMmio32 (RPBase, R_QNC_PCIE_SLCAP);
+ DwordReg &= B_QNC_PCIE_SLCAP_MASK_RSV_VALUE;
+ DwordReg |= (V_QNC_PCIE_SLCAP_SLV << V_QNC_PCIE_SLCAP_SLV_OFFSET);
+ DwordReg |= ((RootPortConfig[RootPortIndex].Bits.PhysicalSlotNumber) << V_QNC_PCIE_SLCAP_PSN_OFFSET) ;
+ QNCMmio32 (RPBase, R_QNC_PCIE_SLCAP) = DwordReg;
+
+ //
+ // Check for a Presence Detect Change.
+ //
+ SlotStatus = QNCMmio16 (RPBase, R_QNC_PCIE_SLSTS);
+ if ((SlotStatus & (B_QNC_PCIE_SLSTS_PDS + B_QNC_PCIE_SLSTS_PDC)) == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Temporarily Hardcode the Root Port Bridge Number to 2.
+ //
+ // This Endpoint check should immediately pass. Howerver, a 900ms delay
+ // has been added to match the timing requirements of the PCI Express Base
+ // Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s
+ // after a reset of a device, before it may determine that a device which
+ // fails to return a Successful Completion status for a valid Configuration
+ // Request is a broken device"). Note that a 100ms delay was already added
+ // after the Root Ports were first taken out of reset.
+ //
+ QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF, 0x00020200);
+ //
+ // Only do this when a downstream device is present
+ //
+ EndPointBase = PciExpressBar + (((2 << 8) + (0 << 3) + (0 << 0)) << 12);
+ if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {
+ for (Index = 0; Index < V_PCIE_MAX_TRY_TIMES; Index++){
+ if (QNCMmio16 (EndPointBase, 0x0) != 0xFFFF) {
+ break;
+ }
+ PcieStall (15);
+ }
+ if (Index >= V_PCIE_MAX_TRY_TIMES) {
+ //
+ // Clear Bus Numbers.
+ //
+ QNCMmio32And (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ //
+ // PCI Express* Virtual Channels
+ // Clear TC1-7 Traffic classes.
+ // Map TC0-VC0
+ //
+ PcieInitTcxVc0 (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0);
+ PcieMapTcxVc0 (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0, 0x0);
+
+ //
+ // Set Common Clock for inserted cards
+ //
+ if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {
+ PcieSetCommonClock (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0);
+ }
+
+ //
+ // Flow for Enabling ASPM
+ //
+ if (RootPortConfig[RootPortIndex].Bits.AspmEnable) {
+ if (RootPortConfig[RootPortIndex].Bits.AspmAutoEnable) {
+ PcieSetAspmAuto (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0, &AspmVal);
+ } else {
+ //
+ // Set ASPM values according to setup selections, masked by capabilities
+ //
+ PcieSetAspmManual (
+ PCI_BUS_NUMBER_QNC,
+ (UINT8) (PCI_DEVICE_NUMBER_PCIE_ROOTPORT),
+ (UINT8) (PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex),
+ (UINT8) ((RootPortConfig[RootPortIndex].Bits.AspmL0sEnable & 0x01) | (RootPortConfig[RootPortIndex].Bits.AspmL1Enable << 1)),
+ &AspmVal
+ );
+ }
+ }
+
+ //
+ // Enable the PCIe CLKREQ#
+ //
+ if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {
+ PcieSetClkreq (2, 0);
+ }
+
+ //
+ // Clear Bus Numbers
+ //
+ QNCMmio32And (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF);
+
+ //
+ // Additional configurations
+ //
+
+ //
+ // PCI-E Unsupported Request Reporting Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_URE_ENABLE) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_URE);
+ }
+
+ //
+ // Device Fatal Error Reporting Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_FEE_ENABLE) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_FEE);
+ }
+
+ //
+ // Device Non Fatal Error Reporting Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_NFE_ENABLE) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_NFE);
+ }
+
+ //
+ // Device Correctable Error Reporting Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_CEE_ENABLE) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_CEE);
+ }
+ //
+ // Root PCI-E PME Interrupt Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PmeInterruptEnable) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_PIE);
+ }
+ //
+ // Root PCI-E System Error on Fatal Error Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SFE_ENABLE) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SFE);
+ }
+
+ //
+ // Root PCI-E System Error on Non-Fatal Error Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SNE_ENABLE) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SNE);
+ }
+
+ //
+ // Root PCI-E System Error on Correctable Error Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SCE_ENABLE) {
+ QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SCE);
+ }
+
+ //
+ // Root PCI-E Powermanagement SCI Enabled
+ //
+ if (RootPortConfig[RootPortIndex].Bits.PmSciEnable) {
+ //
+ // Make sure that PME Interrupt Enable bit of Root Control register
+ // of PCI Express Capability struceture is cleared
+ //
+ QNCMmio32And (RPBase, R_QNC_PCIE_RCTL, (~B_QNC_PCIE_RCTL_PIE));
+ QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_MPC, (~B_QNC_PCIE_MPC_PMME), B_QNC_PCIE_MPC_PMCE);
+
+ //
+ // Make sure GPE0 Stutus RW1C Bit is clear.
+ //
+ DwordReg = IoRead32 (QNCGpeBase + R_QNC_GPE0BLK_GPE0S);
+ if ((DwordReg & B_QNC_GPE0BLK_GPE0S_PCIE) != 0) {
+ IoWrite32 (QNCGpeBase + R_QNC_GPE0BLK_GPE0S, B_QNC_GPE0BLK_GPE0S_PCIE);
+ }
+ }
+
+ //
+ // PCIe Hot Plug SCI Enable
+ //
+ if (RootPortConfig[RootPortIndex].Bits.HotplugSciEnable) {
+ //
+ // Write clear for :
+ // Attention Button Pressed (bit0)
+ // Presence Detect Changed (bit3)
+ //
+ QNCMmio32Or (RPBase, R_QNC_PCIE_SLSTS, (B_QNC_PCIE_SLSTS_PDC | B_QNC_PCIE_SLSTS_ABP));
+
+ //
+ // Sequence 2: Program the following bits in Slot Control register at offset 18h
+ // of PCI Express* Capability structure:
+ // Attention Button Pressed Enable (bit0) = 1b
+ // Presence Detect Changed Enable (bit3) = 1b
+ // Hot Plug Interrupt Enable (bit5) = 0b
+ //
+ QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_SLCTL, (~B_QNC_PCIE_SLCTL_HPE), (B_QNC_PCIE_SLCTL_PDE | B_QNC_PCIE_SLCTL_ABE));
+
+ //
+ // Sequence 3: Program Misc Port Config (MPC) register at PCI config space offset
+ // D8h as follows:
+ // Hot Plug SCI Enable (HPCE, bit30) = 1b
+ // Hot Plug SMI Enable (HPME, bit1) = 0b
+ //
+ QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_MPC, (~B_QNC_PCIE_MPC_HPME), B_QNC_PCIE_MPC_HPCE);
+ }
+
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Perform Initialization of the Downstream Root Ports
+**/
+VOID
+QNCDownStreamPortsInit (
+ IN PCIEXP_ROOT_PORT_CONFIGURATION *RootPortConfig,
+ IN QNC_DEVICE_ENABLES *QNCDeviceEnables,
+ IN UINT64 PciExpressBar,
+ IN UINT32 QNCRootComplexBar,
+ IN UINT32 QNCPmioBase,
+ IN UINT32 QNCGpeBase,
+ OUT UINTN *RpEnableMask
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ //
+ // Initialize every root port and downstream device
+ //
+ for (Index = 0;Index < MAX_PCI_EXPRESS_ROOT_PORTS;Index++) {
+ if ((QNCDeviceEnables->Uint32 & (1 << Index)) != 0) {
+ Status = QNCRootPortInit (
+ Index,
+ RootPortConfig,
+ PciExpressBar,
+ QNCRootComplexBar,
+ QNCPmioBase,
+ QNCGpeBase
+ );
+
+ if (!EFI_ERROR (Status)) {
+ (*RpEnableMask) |= LShiftU64(1, Index);
+ DEBUG ((EFI_D_INFO, " Root Port %x device found, enabled. RpEnableMask: 0x%x\n", Index + 1, *RpEnableMask));
+ }
+ }
+ }
+}
+
+/**
+ Do early init of pci express rootports on Soc.
+
+**/
+
+VOID
+EFIAPI
+PciExpressEarlyInit (
+ VOID
+ )
+{
+ //
+ // Setup Message Bus Idle Counter (SBIC) values.
+ //
+ QNCMmPci8(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_IOSFSBCTL) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_IOSFSBCTL, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK), V_PCIE_ROOT_PORT_SBIC_VALUE);
+ QNCMmPci8(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_IOSFSBCTL) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_IOSFSBCTL, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK), V_PCIE_ROOT_PORT_SBIC_VALUE);
+
+ //
+ // Program SVID/SID the same as VID/DID for Root ports.
+ //
+ QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, PCI_VENDOR_ID_OFFSET);
+ QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, PCI_VENDOR_ID_OFFSET);
+
+ //
+ // Set the IPF bit in MCR2
+ //
+ QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_MPC2) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_MPC2, B_QNC_PCIE_MPC2_IPF);
+ QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_MPC2) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_MPC2, B_QNC_PCIE_MPC2_IPF);
+
+ //
+ // Set up the Posted and Non Posted Request sizes for PCIe
+ //
+ QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_CCFG) = QNCMmPci32AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_CCFG, ~B_QNC_PCIE_CCFG_UPSD, (B_QNC_PCIE_CCFG_UNRS | B_QNC_PCIE_CCFG_UPRS));
+
+ return;
+}
+
+
+/**
+ Complete initialization all the pci express rootports on Soc.
+**/
+EFI_STATUS
+EFIAPI
+PciExpressInit (
+ )
+{
+ UINT64 PciExpressBar;
+ UINT32 QNCRootComplexBar;
+ UINT32 QNCGpioBase;
+ UINT32 QNCPmioBase;
+ UINT32 QNCGpeBase;
+ UINTN RpEnableMask;
+ PCIEXP_ROOT_PORT_CONFIGURATION *mRootPortConfig;
+ QNC_DEVICE_ENABLES mQNCDeviceEnables;
+
+ //
+ // Get BAR registers
+ //
+ QNCRootComplexBar = QNC_RCRB_BASE;
+ QNCGpioBase = LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
+ QNCPmioBase = LpcPciCfg32 (R_QNC_LPC_PM1BLK) & B_QNC_LPC_PM1BLK_MASK;
+ QNCGpeBase = LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & B_QNC_LPC_GPE0BLK_MASK;
+ RpEnableMask = 0; // assume all root ports are disabled
+
+ PciExpressBar = PcdGet64 (PcdPciExpressBaseAddress);
+
+ //
+ // Get platform information from PCD entries
+ //
+ mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);
+ mRootPortConfig = (PCIEXP_ROOT_PORT_CONFIGURATION*) PcdGetPtr (PcdPcieRootPortConfiguration);
+
+ DEBUG ((EFI_D_INFO, " mRootPortConfig: 0x%x, value1: 0x%x, value2: 0x%x, value3: 0x%x, value4: 0x%x\n",
+ mRootPortConfig, mRootPortConfig[0].Uint32, mRootPortConfig[1].Uint32,
+ mRootPortConfig[2].Uint32, mRootPortConfig[3].Uint32));
+
+ QNCDownStreamPortsInit (
+ mRootPortConfig,
+ &mQNCDeviceEnables,
+ PciExpressBar,
+ QNCRootComplexBar,
+ QNCPmioBase,
+ QNCGpeBase,
+ &RpEnableMask
+ );
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/BaseAccess.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/BaseAccess.c
new file mode 100644
index 0000000..f92d09d
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/BaseAccess.c
@@ -0,0 +1,52 @@
+/** @file
+ Base Lib function for QNC internal network access.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <Uefi.h>
+
+/**
+ Gets the base address of PCI Express for Quark North Cluster.
+
+ @return The base address of PCI Express for Quark North Cluster.
+
+**/
+UINTN
+EFIAPI
+QncGetPciExpressBaseAddress (
+ VOID
+ )
+{
+ return (UINTN) PcdGet64(PcdPciExpressBaseAddress);
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.c
new file mode 100755
index 0000000..54ef8a0
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.c
@@ -0,0 +1,341 @@
+/** @file
+ Common Lib function for QNC internal network access.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <Uefi.h>
+
+#include <IntelQNCRegs.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Pci22.h>
+
+UINT32
+EFIAPI
+QNCPortRead(
+ UINT8 Port,
+ UINT32 RegAddress
+ )
+{
+ McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_READ_DW (Port, RegAddress);
+ return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
+}
+
+VOID
+EFIAPI
+QNCPortWrite (
+ UINT8 Port,
+ UINT32 RegAddress,
+ UINT32 WriteValue
+ )
+{
+ McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
+ McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_WRITE_DW (Port, RegAddress);
+}
+
+UINT32
+EFIAPI
+QNCAltPortRead (
+ UINT8 Port,
+ UINT32 RegAddress
+ )
+{
+ McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_READ_DW (Port, RegAddress);
+ return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
+}
+
+VOID
+EFIAPI
+QNCAltPortWrite (
+ UINT8 Port,
+ UINT32 RegAddress,
+ UINT32 WriteValue
+ )
+{
+ McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
+ McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_WRITE_DW (Port, RegAddress);
+}
+
+UINT32
+EFIAPI
+QNCPortIORead(
+ UINT8 Port,
+ UINT32 RegAddress
+ )
+{
+ McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_READ_DW (Port, RegAddress);
+ return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
+}
+
+VOID
+EFIAPI
+QNCPortIOWrite (
+ UINT8 Port,
+ UINT32 RegAddress,
+ UINT32 WriteValue
+ )
+{
+ McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
+ McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
+ McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_WRITE_DW (Port, RegAddress);
+}
+
+EFI_STATUS
+EFIAPI
+QNCMmIoWrite (
+ UINT32 MmIoAddress,
+ QNC_MEM_IO_WIDTH Width,
+ UINT32 DataNumber,
+ VOID *pData
+ )
+/*++
+
+Routine Description:
+
+ This is for the special consideration for QNC MMIO write, as required by FWG, a reading must be performed after MMIO writing
+to ensure the expected write is processed and data is flushed into chipset
+
+Arguments:
+
+ Row -- row number to be cleared ( start from 1 )
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ Status = EFI_SUCCESS;
+
+ for (Index =0; Index < DataNumber; Index++) {
+ switch (Width) {
+ case QNCMmioWidthUint8:
+ QNCMmio8 (MmIoAddress, 0) = ((UINT8 *)pData)[Index];
+ if (QNCMmio8 (MmIoAddress, 0) != ((UINT8*)pData)[Index]) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ break;
+
+ case QNCMmioWidthUint16:
+ QNCMmio16 (MmIoAddress, 0) = ((UINT16 *)pData)[Index];
+ if (QNCMmio16 (MmIoAddress, 0) != ((UINT16 *)pData)[Index]) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ break;
+
+ case QNCMmioWidthUint32:
+ QNCMmio32 (MmIoAddress, 0) = ((UINT32 *)pData)[Index];
+ if (QNCMmio32 (MmIoAddress, 0) != ((UINT32 *)pData)[Index]) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ break;
+
+ case QNCMmioWidthUint64:
+ QNCMmio64 (MmIoAddress, 0) = ((UINT64 *)pData)[Index];
+ if (QNCMmio64 (MmIoAddress, 0) != ((UINT64 *)pData)[Index]) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return Status;
+}
+
+VOID
+EFIAPI
+QncHsmmcWrite (
+ UINT32 WriteValue
+ )
+{
+ UINT16 DeviceId;
+ UINT32 Data32;
+
+ //
+ // Check what Soc we are running on (read Host bridge DeviceId)
+ //
+ DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
+
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {
+ //
+ // Disable HSMMC configuration
+ //
+ Data32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
+ Data32 &= ~SMM_CTL_EN;
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, Data32);
+
+ //
+ // Validate HSMMC configuration is disabled
+ //
+ Data32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
+ ASSERT((Data32 & SMM_CTL_EN) == 0);
+
+ //
+ // Enable HSMMC configuration
+ //
+ WriteValue |= SMM_CTL_EN;
+ }
+
+ //
+ // Write the register value
+ //
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, WriteValue);
+
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {
+ //
+ // Validate HSMMC configuration is enabled
+ //
+ Data32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
+ ASSERT((Data32 & SMM_CTL_EN) != 0);
+ }
+}
+
+VOID
+EFIAPI
+QncImrWrite (
+ UINT32 ImrBaseOffset,
+ UINT32 ImrLow,
+ UINT32 ImrHigh,
+ UINT32 ImrReadMask,
+ UINT32 ImrWriteMask
+ )
+{
+ UINT16 DeviceId;
+ UINT32 Data32;
+
+ //
+ // Check what Soc we are running on (read Host bridge DeviceId)
+ //
+ DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
+
+ //
+ // Disable IMR protection
+ //
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {
+ //
+ // Disable IMR protection
+ //
+ Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
+ Data32 &= ~IMR_EN;
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, Data32);
+
+ //
+ // Validate IMR protection is disabled
+ //
+ Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
+ ASSERT((Data32 & IMR_EN) == 0);
+
+ //
+ // Update the IMR (IMRXL must be last as it may enable IMR violation checking)
+ //
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, ImrLow);
+
+ //
+ // Validate IMR protection is enabled/disabled
+ //
+ Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
+ ASSERT((Data32 & IMR_EN) == (ImrLow & IMR_EN));
+ } else {
+ //
+ // Disable IMR protection (allow all access)
+ //
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, (UINT32)IMRX_ALL_ACCESS);
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, (UINT32)IMRX_ALL_ACCESS);
+
+ //
+ // Update the IMR (IMRXRM/IMRXWM must be last as they restrict IMR access)
+ //
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, (ImrLow & ~IMR_EN));
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);
+ QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);
+ }
+}
+
+VOID
+EFIAPI
+QncIClkAndThenOr (
+ UINT32 RegAddress,
+ UINT32 AndValue,
+ UINT32 OrValue
+ )
+{
+ UINT32 RegValue;
+ //
+ // Whenever an iCLK SB register (Endpoint 32h) is being programmed the access
+ // should always consist of a READ from the address followed by 2 identical
+ // WRITEs to that address.
+ //
+ RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);
+ RegValue &= AndValue;
+ RegValue |= OrValue;
+ QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
+ QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
+}
+
+VOID
+EFIAPI
+QncIClkOr (
+ UINT32 RegAddress,
+ UINT32 OrValue
+ )
+{
+ UINT32 RegValue;
+ //
+ // Whenever an iCLK SB register (Endpoint 32h) is being programmed the access
+ // should always consist of a READ from the address followed by 2 identical
+ // WRITEs to that address.
+ //
+ RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);
+ RegValue |= OrValue;
+ QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
+ QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf
new file mode 100755
index 0000000..b0a360d
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf
@@ -0,0 +1,63 @@
+## @file
+# Base Intel QNC Library Instance
+#
+# Intel QNC internal network access Library Instance
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QNCAccessLib
+ FILE_GUID = CC13B9FB-DAF5-4b42-907F-122216787C05
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = QNCAccessLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ QNCAccessLib.c
+ BaseAccess.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ DebugLib
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[Pcd]
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeAccess.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeAccess.c
new file mode 100644
index 0000000..0ad8864
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeAccess.c
@@ -0,0 +1,166 @@
+/** @file
+ Runtime Lib function for QNC internal network access.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/QNCAccessLib.h>
+
+///
+/// Set Virtual Address Map Event
+///
+EFI_EVENT mDxeRuntimeQncAccessLibVirtualNotifyEvent = NULL;
+
+///
+/// Module global that contains the base physical address of the PCI Express MMIO range.
+///
+UINTN mDxeRuntimeQncAccessLibPciExpressBaseAddress = 0;
+
+/**
+ Convert the physical PCI Express MMIO address to a virtual address.
+
+ @param[in] Event The event that is being processed.
+ @param[in] Context The Event Context.
+**/
+VOID
+EFIAPI
+DxeRuntimeQncAccessLibVirtualNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Convert the physical PCI Express MMIO address to a virtual address.
+ //
+ Status = EfiConvertPointer (0, (VOID **) &mDxeRuntimeQncAccessLibPciExpressBaseAddress);
+
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ The constructor function to setup globals and goto virtual mode notify.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor completed successfully.
+ @retval Other value The constructor did not complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeRuntimeQncAccessLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Cache the physical address of the PCI Express MMIO range into a module global variable
+ //
+ mDxeRuntimeQncAccessLibPciExpressBaseAddress = (UINTN) PcdGet64(PcdPciExpressBaseAddress);
+
+ //
+ // Register SetVirtualAddressMap () notify function
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ DxeRuntimeQncAccessLibVirtualNotify,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mDxeRuntimeQncAccessLibVirtualNotifyEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ The destructor function frees any allocated buffers and closes the Set Virtual
+ Address Map event.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The destructor completed successfully.
+ @retval Other value The destructor did not complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeRuntimeQncAccessLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Close the Set Virtual Address Map event
+ //
+ Status = gBS->CloseEvent (mDxeRuntimeQncAccessLibVirtualNotifyEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Gets the base address of PCI Express for Quark North Cluster.
+
+ @return The base address of PCI Express for Quark North Cluster.
+
+**/
+UINTN
+EFIAPI
+QncGetPciExpressBaseAddress (
+ VOID
+ )
+{
+ //
+ // If system goes to virtual mode then virtual notify callback will update
+ // mDxeRuntimeQncAccessLibPciExpressBaseAddress with virtual address of
+ // PCIe memory base.
+ //
+ return mDxeRuntimeQncAccessLibPciExpressBaseAddress;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeQNCAccessLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeQNCAccessLib.inf
new file mode 100644
index 0000000..b8baebb
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeQNCAccessLib.inf
@@ -0,0 +1,69 @@
+## @file
+# DXE Runtime Intel QNC Library Instance
+#
+# Intel QNC internal network access Library Instance.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RuntimeQNCAccessLib
+ FILE_GUID = E6B51D93-E4C8-4425-9FA9-9DED814220F9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = QNCAccessLib|DXE_RUNTIME_DRIVER
+ CONSTRUCTOR = DxeRuntimeQncAccessLibConstructor
+ DESTRUCTOR = DxeRuntimeQncAccessLibDestructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ QNCAccessLib.c
+ RuntimeAccess.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiRuntimeLib
+
+[Guids]
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
new file mode 100755
index 0000000..7459df9
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
@@ -0,0 +1,235 @@
+/** @file
+ QNC Smm Library Services that implements both S/W SMI generation and detection.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include <Base.h>
+#include <IntelQNCRegs.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/QNCAccessLib.h>
+
+#define BOOT_SERVICE_SOFTWARE_SMI_DATA 0
+#define RUNTIME_SOFTWARE_SMI_DATA 1
+
+/**
+ Triggers a run time or boot time SMI.
+
+ This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.
+
+ @param Data The value to set the APMC status.
+
+**/
+VOID
+InternalTriggerSmi (
+ IN UINT8 Data
+ )
+{
+ UINT16 PM1BLK_Base;
+ UINT16 GPE0BLK_Base;
+ UINT32 NewValue;
+
+ //
+ // Get PM1BLK_Base & GPE0BLK_Base
+ //
+ PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);
+ GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);
+
+
+ //
+ // Enable APM SMI
+ //
+ IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), B_QNC_GPE0BLK_SMIE_APM);
+
+ //
+ // Enable SMI globally
+ //
+ NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ NewValue |= SMI_EN;
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
+
+ //
+ // Set APM_STS
+ //
+ IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);
+
+ //
+ // Generate the APM SMI
+ //
+ IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));
+
+ //
+ // Clear the APM SMI Status Bit
+ //
+ IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);
+
+ //
+ // Set the EOS Bit
+ //
+ IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
+}
+
+
+/**
+ Triggers an SMI at boot time.
+
+ This function triggers a software SMM interrupt at boot time.
+
+**/
+VOID
+EFIAPI
+TriggerBootServiceSoftwareSmi (
+ VOID
+ )
+{
+ InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA);
+}
+
+
+/**
+ Triggers an SMI at run time.
+
+ This function triggers a software SMM interrupt at run time.
+
+**/
+VOID
+EFIAPI
+TriggerRuntimeSoftwareSmi (
+ VOID
+ )
+{
+ InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA);
+}
+
+
+/**
+ Gets the software SMI data.
+
+ This function tests if a software SMM interrupt happens. If a software SMI happens,
+ it retrieves the SMM data and returns it as a non-negative value; otherwise a negative
+ value is returned.
+
+ @return Data The data retrieved from SMM data port in case of a software SMI;
+ otherwise a negative value.
+
+**/
+INTN
+InternalGetSwSmiData (
+ VOID
+ )
+{
+ UINT8 SmiStatus;
+ UINT8 Data;
+
+ SmiStatus = IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);
+ if (((SmiStatus & B_QNC_GPE0BLK_SMIS_APM) != 0) &&
+ (IoRead8 (PcdGet16 (PcdSmmActivationPort)) == PcdGet8 (PcdSmmActivationData))) {
+ Data = IoRead8 (PcdGet16 (PcdSmmDataPort));
+ return (INTN)(UINTN)Data;
+ }
+
+ return -1;
+}
+
+
+/**
+ Test if a boot time software SMI happened.
+
+ This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and
+ it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE.
+
+ @retval TRUE A software SMI triggered at boot time happened.
+ @retval FLASE No software SMI happened or the software SMI was triggered at run time.
+
+**/
+BOOLEAN
+EFIAPI
+IsBootServiceSoftwareSmi (
+ VOID
+ )
+{
+ return (BOOLEAN) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA);
+}
+
+
+/**
+ Test if a run time software SMI happened.
+
+ This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and
+ it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE.
+
+ @retval TRUE A software SMI triggered at run time happened.
+ @retval FLASE No software SMI happened or the software SMI was triggered at boot time.
+
+**/
+BOOLEAN
+EFIAPI
+IsRuntimeSoftwareSmi (
+ VOID
+ )
+{
+ return (BOOLEAN) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA);
+}
+
+
+
+/**
+
+ Clear APM SMI Status Bit; Set the EOS bit.
+
+**/
+VOID
+EFIAPI
+ClearSmi (
+ VOID
+ )
+{
+
+ UINT16 GPE0BLK_Base;
+
+ //
+ // Get GpeBase
+ //
+ GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);
+
+ //
+ // Clear the APM SMI Status Bit
+ //
+ IoOr16 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_APM);
+
+ //
+ // Set the EOS Bit
+ //
+ IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf
new file mode 100755
index 0000000..182e404
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf
@@ -0,0 +1,68 @@
+## @file
+# Component description file for Intel QNC SMM Library.
+#
+# QNC SMM Library that layers on top of the I/O Library to directly
+# access SMM power management registers.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QNCSmmLib
+ FILE_GUID = 8A9A62F5-758B-4965-A28B-0AAC292FBD89
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SmmLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ QNCSmmLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ IoLib
+ QNCAccessLib
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmDataPort
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationData
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServices.c b/QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServices.c
new file mode 100644
index 0000000..976cfee
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServices.c
@@ -0,0 +1,392 @@
+/** @file
+ Implmentation module for redirect PEI services.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiPei.h>
+
+#include <Guid/RedirectServicesHob.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/RedirectPeiServicesLib.h>
+
+//
+// Context structure for Redirect PEI services, must be allocated in memory
+// shared by all PEI executables.
+//
+typedef struct {
+ EFI_PEI_SERVICES OriginalPeiServices;
+ UINTN AllocCount;
+ UINTN NextAllocLoc;
+ VOID *PoolBuffer;
+ UINTN PoolBufferLength;
+} REDIRECT_CONTEXT;
+
+STATIC
+REDIRECT_CONTEXT *
+GetRedirectContext (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ return (REDIRECT_CONTEXT *) GetFirstGuidHob (&gRedirectServicesHobGuid);
+}
+
+STATIC
+REDIRECT_CONTEXT *
+CreateRedirectContext (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ REDIRECT_CONTEXT Context;
+ VOID *BuiltHob;
+
+ //
+ // Use HOB to allow context to be shared by all PEI executables.
+ //
+
+ ZeroMem (&Context, sizeof(Context));
+ BuiltHob = BuildGuidDataHob (
+ &gRedirectServicesHobGuid,
+ (VOID *) &Context,
+ sizeof(Context)
+ );
+ ASSERT (BuiltHob != NULL);
+
+ return GetRedirectContext (PeiServices);
+}
+
+STATIC
+CHAR16 *
+MemoryTypePrintString (
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ CHAR16 *Str;
+
+ if (MemoryType == EfiLoaderCode) {
+ Str = L"LoaderCode";
+ } else if (MemoryType == EfiLoaderData) {
+ Str = L"LoaderData";
+ } else if (MemoryType == EfiRuntimeServicesCode) {
+ Str = L"RuntimeServicesCode";
+ } else if (MemoryType == EfiRuntimeServicesData) {
+ Str = L"RuntimeServicesData";
+ } else if (MemoryType == EfiBootServicesCode) {
+ Str = L"BootServicesCode";
+ } else if (MemoryType == EfiBootServicesData) {
+ Str = L"BootServicesData";
+ } else if (MemoryType == EfiACPIReclaimMemory) {
+ Str = L"ACPIReclaimMemory";
+ } else if (MemoryType == EfiACPIMemoryNVS) {
+ Str = L"ACPIMemoryNVS";
+ } else {
+ Str = L"MemTypeUnknown";
+ }
+ return Str;
+}
+
+STATIC
+EFI_STATUS
+RedirectAllocCommon (
+ IN REDIRECT_CONTEXT *Context,
+ IN CONST UINTN Pages,
+ OUT UINTN *ThisAllocLocPtr
+ )
+{
+ UINTN MaxLimit;
+ UINTN ThisAllocLimit;
+ UINTN ThicAllocInc;
+
+ if (Context->PoolBufferLength == 0) {
+ return EFI_NOT_READY;
+ }
+
+ MaxLimit =
+ ((UINTN) Context->PoolBuffer) +
+ (Context->PoolBufferLength - 1);
+
+ ThicAllocInc = (Pages * EFI_PAGE_SIZE);
+ ThisAllocLimit = Context->NextAllocLoc + (ThicAllocInc - 1);
+ if (ThisAllocLimit <= MaxLimit) {
+ *ThisAllocLocPtr = Context->NextAllocLoc;
+ Context->NextAllocLoc += ThicAllocInc;
+ Context->AllocCount = Context->AllocCount + 1;
+ return EFI_SUCCESS;
+ }
+ return EFI_OUT_OF_RESOURCES;
+}
+
+/**
+ Allocates pages from redirected memory pool.
+
+ @param Type The type of allocation to perform (ignored,
+ left here for compatibility with core services)
+ @param MemoryType The type of memory to turn the allocated pages
+ into
+ @param NumberOfPages The number of pages to allocate
+ @param Memory A pointer to receive the base allocated memory
+ address
+
+ @return Status. On success, Memory is filled in with the base address allocated
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_READY Redirected memory pool not setup.
+ @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
+ @retval EFI_SUCCESS Pages successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+RedirectPeiAllocatePages (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT EFI_PHYSICAL_ADDRESS *Memory
+ )
+{
+ REDIRECT_CONTEXT *Context;
+ UINTN ThisAllocLoc;
+ EFI_STATUS Status;
+
+ if (Memory == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get PEI executable shared context structure.
+ //
+ Context = GetRedirectContext (GetPeiServicesTablePointer ());
+ ASSERT (Context != NULL);
+
+ //
+ // Allocate memory from redirected memory pool and return
+ // memory location to caller.
+ //
+ Status = RedirectAllocCommon (Context, Pages, &ThisAllocLoc);
+ if (!EFI_ERROR(Status)) {
+ *Memory = (EFI_PHYSICAL_ADDRESS) ThisAllocLoc;
+ }
+ return Status;
+}
+
+/**
+
+ Memory allocation service for memory from redirected memory pool.
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param Size Amount of memory required
+ @param Buffer Address of pointer to the buffer
+
+ @retval EFI_SUCCESS The allocation was successful
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to satisfy the requirement
+ to allocate the requested size.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_READY Redirected memory pool not setup.
+
+**/
+EFI_STATUS
+EFIAPI
+RedirectPeiAllocatePool (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+{
+ REDIRECT_CONTEXT *Context;
+ UINTN Pages;
+ UINTN ThisAllocLoc;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get PEI executable shared context structure.
+ //
+ Context = GetRedirectContext (GetPeiServicesTablePointer ());
+ ASSERT (Context != NULL);
+
+ //
+ // Always allocated memory in PAGE SIZE chunks.
+ //
+ Pages = Size / EFI_PAGE_SIZE;
+ if ((Size % EFI_PAGE_SIZE) != 0) {
+ Pages++;
+ }
+
+ //
+ // Allocate memory from redirected memory pool and return
+ // memory location to caller.
+ //
+ Status = RedirectAllocCommon (Context, Pages, &ThisAllocLoc);
+ if (!EFI_ERROR(Status)) {
+ *Buffer = (VOID *) ThisAllocLoc;
+ }
+ return Status;
+}
+
+/**
+
+ Init RedirectedPeiServices Lib.
+
+**/
+VOID
+EFIAPI
+RedirectServicesInit (
+ VOID
+ )
+{
+ CONST EFI_PEI_SERVICES **PeiServices;
+ REDIRECT_CONTEXT *Context;
+
+ PeiServices = GetPeiServicesTablePointer ();
+ Context = GetRedirectContext (PeiServices);
+ if (Context != NULL) {
+ DEBUG ((EFI_D_INFO, "RedirectServicesInit: already initialised\n"));
+ return;
+ }
+
+ //
+ // Create PEI executable shared Context struct.
+ //
+ Context = CreateRedirectContext (PeiServices);
+ ASSERT (Context != NULL);
+}
+
+/**
+
+ Set memory pool to be used for redirected PEI memory alloc. services.
+
+ @param PoolBuffer Address of memory pool.
+ @param PoolBufferLength Length of memory pool.
+
+**/
+VOID
+EFIAPI
+RedirectMemoryServicesSetPool (
+ IN VOID *PoolBuffer,
+ IN CONST UINTN PoolBufferLength
+ )
+{
+ REDIRECT_CONTEXT *Context;
+
+ //
+ // Get PEI executable shared context structure.
+ //
+ Context = GetRedirectContext (GetPeiServicesTablePointer ());
+ ASSERT (Context != NULL);
+
+ //
+ // Init memory alloc fields in context structure.
+ //
+ Context->PoolBuffer = PoolBuffer;
+ Context->PoolBufferLength = PoolBufferLength;
+ Context->AllocCount = 0;
+ Context->NextAllocLoc = (UINTN) Context->PoolBuffer;
+
+ DEBUG ((EFI_D_INFO, "RedirectMemoryServicesSetPool Base:Size 0x%08X:0x%08X\n",
+ (UINTN) Context->PoolBuffer,
+ (UINTN) Context->PoolBufferLength
+ ));
+}
+
+/**
+
+ Enable memory allocations from redirected memory pool.
+
+**/
+VOID
+EFIAPI
+RedirectMemoryServicesEnable (
+ VOID
+ )
+{
+ CONST EFI_PEI_SERVICES **PeiServices;
+ EFI_PEI_SERVICES **WorkPeiServices;
+ REDIRECT_CONTEXT *Context;
+
+ PeiServices = GetPeiServicesTablePointer ();
+ WorkPeiServices = (EFI_PEI_SERVICES **) PeiServices;
+
+ //
+ // Get PEI executable shared context structure.
+ //
+ Context = GetRedirectContext (PeiServices);
+ ASSERT (Context != NULL);
+
+ //
+ // Save address of current memory allocation services.
+ //
+ Context->OriginalPeiServices.AllocatePool = (*PeiServices)->AllocatePool;
+ Context->OriginalPeiServices.AllocatePages = (*PeiServices)->AllocatePages;
+
+ //
+ // Switch memory allocation services to use our routines.
+ //
+ (*WorkPeiServices)->AllocatePool = RedirectPeiAllocatePool;
+ (*WorkPeiServices)->AllocatePages = RedirectPeiAllocatePages;
+}
+
+/**
+
+ Disable memory allocations from redirected memory pool.
+
+**/
+VOID
+EFIAPI
+RedirectMemoryServicesDisable (
+ VOID
+ )
+{
+ CONST EFI_PEI_SERVICES **PeiServices;
+ EFI_PEI_SERVICES **WorkPeiServices;
+ REDIRECT_CONTEXT *Context;
+
+ PeiServices = GetPeiServicesTablePointer ();
+ WorkPeiServices = (EFI_PEI_SERVICES **) PeiServices;
+
+ //
+ // Get PEI executable shared context structure.
+ //
+ Context = GetRedirectContext (PeiServices);
+ ASSERT (Context != NULL);
+
+ //
+ // Restore address of original memory allocation services.
+ //
+ (*WorkPeiServices)->AllocatePool = Context->OriginalPeiServices.AllocatePool;
+ (*WorkPeiServices)->AllocatePages = Context->OriginalPeiServices.AllocatePages;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServicesLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServicesLib.inf
new file mode 100644
index 0000000..655b6cd
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/RedirectPeiServicesLib/RedirectPeiServicesLib.inf
@@ -0,0 +1,74 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Module Name:
+#
+# RedirectPeiServicesLib.inf
+#
+# Abstract:
+#
+# Library producing routines for redirect PEI services functionality.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RedirectPeiServicesLib
+ FILE_GUID = 6D9A8870-14DC-414d-AEE4-2042D9574FB5
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedirectPeiServicesLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ RedirectPeiServices.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ HobLib
+
+[Guids]
+ gRedirectServicesHobGuid
+
+[Ppis]
+
+[FeaturePcd]
+
+[FixedPcd]
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.c
new file mode 100755
index 0000000..7d89f6d
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.c
@@ -0,0 +1,340 @@
+/** @file
+ System reset Library Services. This library class provides a set of
+ methods to reset whole system with manipulate QNC.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Base.h>
+#include <IntelQNCBase.h>
+#include <QNCAccess.h>
+
+#include <Uefi/UefiBaseType.h>
+
+#include <Library/ResetSystemLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CpuLib.h>
+#include <Library/QNCAccessLib.h>
+
+//
+// Amount of time (seconds) before RTC alarm fires
+// This must be < BCD_BASE
+//
+#define PLATFORM_WAKE_SECONDS_BUFFER 0x06
+
+//
+// RTC 'seconds' above which we will not read to avoid potential rollover
+//
+#define PLATFORM_RTC_ROLLOVER_LIMIT 0x47
+
+//
+// BCD is base 10
+//
+#define BCD_BASE 0x0A
+
+#define PCAT_RTC_ADDRESS_REGISTER 0x70
+#define PCAT_RTC_DATA_REGISTER 0x71
+
+//
+// Dallas DS12C887 Real Time Clock
+//
+#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59
+#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59
+#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59
+#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59
+#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7
+#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31
+#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12
+#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99
+#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]
+#define RTC_ADDRESS_REGISTER_B 11 // R/W
+#define RTC_ADDRESS_REGISTER_C 12 // RO
+#define RTC_ADDRESS_REGISTER_D 13 // RO
+#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W
+
+/**
+ Wait for an RTC update to happen
+
+**/
+VOID
+EFIAPI
+WaitForRTCUpdate (
+VOID
+)
+{
+ UINT8 Data8;
+
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
+ Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ if ((Data8 & BIT7) == BIT7) {
+ while ((Data8 & BIT7) == BIT7) {
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
+ Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ }
+
+ } else {
+ while ((Data8 & BIT7) == 0) {
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
+ Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ }
+
+ while ((Data8 & BIT7) == BIT7) {
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
+ Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ }
+ }
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+VOID
+)
+{
+ //
+ // Reference to QuarkNcSocId BWG
+ // Setting bit 1 will generate a warm reset, driving only RSTRDY# low
+ //
+ IoWrite8 (RST_CNT, B_RST_CNT_COLD_RST);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+VOID
+)
+{
+ //
+ // Reference to QuarkNcSocId BWG
+ // Setting bit 1 will generate a warm reset, driving only RSTRDY# low
+ //
+ IoWrite8 (RST_CNT, B_RST_CNT_WARM_RST);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+VOID
+)
+{
+ //
+ // Reference to QuarkNcSocId BWG
+ // Disable RTC Alarm : (RTC Enable at PM1BLK + 02h[10]))
+ //
+ IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, 0);
+
+ //
+ // Firstly, GPE0_EN should be disabled to
+ // avoid any GPI waking up the system from S5
+ //
+ IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E, 0);
+
+ //
+ // Reference to QuarkNcSocId BWG
+ // Disable Resume Well GPIO : (GPIO bits in GPIOBASE + 34h[8:0])
+ //
+ IoWrite32 (PcdGet16 (PcdGbaIoBaseAddress) + R_QNC_GPIO_RGGPE_RESUME_WELL, 0);
+
+ //
+ // No power button status bit to clear for our platform, go to next step.
+ //
+
+ //
+ // Finally, transform system into S5 sleep state
+ //
+ IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, 0xffffc3ff, B_QNC_PM1BLK_PM1C_SLPEN | V_S5);
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule
+ update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+VOID
+)
+{
+ UINT8 Data8;
+ UINT16 Data16;
+ UINT32 Data32;
+ UINTN Eflags;
+ UINTN RegCr0;
+ EFI_TIME EfiTime;
+ UINT32 SmiEnSave;
+
+ Eflags = AsmReadEflags ();
+ if ( (Eflags & 0x200) ) {
+ DisableInterrupts ();
+ }
+
+ //
+ // Write all cache data to memory because processor will lost power
+ //
+ AsmWbinvd();
+ RegCr0 = AsmReadCr0();
+ AsmWriteCr0 (RegCr0 | 0x060000000);
+
+ SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));
+
+ //
+ // Pogram RTC alarm for immediate WAKE
+ //
+
+ //
+ // Disable SMI sources
+ //
+ IoWrite16 (PcdGet16 (PcdGpe0blkIoBaseAddress) + R_QNC_GPE0BLK_SMIE, 0);
+
+ //
+ // Disable RTC alarm interrupt
+ //
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);
+ Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 & ~BIT5));
+
+ //
+ // Clear RTC alarm if already set
+ //
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_C);
+ Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER); // Read clears alarm status
+
+ //
+ // Disable all WAKE events
+ //
+ IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, B_QNC_PM1BLK_PM1E_PWAKED);
+
+ //
+ // Clear all WAKE status bits
+ //
+ IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S, B_QNC_PM1BLK_PM1S_ALL);
+
+ //
+ // Avoid RTC rollover
+ //
+ do {
+ WaitForRTCUpdate();
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);
+ EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ } while (EfiTime.Second > PLATFORM_RTC_ROLLOVER_LIMIT);
+
+ //
+ // Read RTC time
+ //
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS);
+ EfiTime.Hour = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES);
+ EfiTime.Minute = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);
+ EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);
+
+ //
+ // Set RTC alarm
+ //
+
+ //
+ // Add PLATFORM_WAKE_SECONDS_BUFFER to current EfiTime.Second
+ // The maths is to allow for the fact we are adding to a BCD number and require the answer to be BCD (EfiTime.Second)
+ //
+ if ((BCD_BASE - (EfiTime.Second & 0x0F)) <= PLATFORM_WAKE_SECONDS_BUFFER) {
+ Data8 = (((EfiTime.Second & 0xF0) + 0x10) + (PLATFORM_WAKE_SECONDS_BUFFER - (BCD_BASE - (EfiTime.Second & 0x0F))));
+ } else {
+ Data8 = EfiTime.Second + PLATFORM_WAKE_SECONDS_BUFFER;
+ }
+
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS_ALARM);
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Hour);
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES_ALARM);
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Minute);
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS_ALARM);
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, Data8);
+
+ //
+ // Enable RTC alarm interrupt
+ //
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);
+ Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 | BIT5));
+
+ //
+ // Enable RTC alarm as WAKE event
+ //
+ Data16 = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);
+ IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, (Data16 | B_QNC_PM1BLK_PM1E_RTC));
+
+ //
+ // Enter S3
+ //
+ Data32 = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
+ Data32 = (UINT32) ((Data32 & 0xffffc3fe) | V_S3 | B_QNC_PM1BLK_PM1C_SCIEN);
+ IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);
+ Data32 = Data32 | B_QNC_PM1BLK_PM1C_SLPEN;
+ IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);
+
+ //
+ // Enable Interrupt if it's enabled before
+ //
+ if ( (Eflags & 0x200) ) {
+ EnableInterrupts ();
+ }
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf
new file mode 100755
index 0000000..ad5cd0e
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf
@@ -0,0 +1,70 @@
+## @file
+# Component description file for Intel QuarkNcSocId Reset System Library.
+#
+# Reset System Library implementation that bases on QNC.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ResetSystemLib
+ FILE_GUID = AD33A56E-3AAD-40ac-91B1-FA861E8D9D85
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ResetSystemLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ ResetSystemLib.c
+
+
+[Packages]
+ QuarkSocPkg/QuarkSocPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ IoLib
+ BaseLib
+ CpuLib
+ QNCAccessLib
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/CommonHeader.h b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/CommonHeader.h
new file mode 100644
index 0000000..d05b2c1
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/CommonHeader.h
@@ -0,0 +1,49 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+#include <Uefi.h>
+#include <Base.h>
+
+#include <Library/SmbusLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/QNCAccessLib.h>
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c
new file mode 100644
index 0000000..a2e014e
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c
@@ -0,0 +1,771 @@
+/** @file
+ Intel QNC SMBUS library implementation built upon I/O library.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+/**
+ Gets Io port base address of Smbus Host Controller.
+
+ This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress
+ to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base
+ address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always
+ read Pci configuration space to get that value in each Smbus bus transaction.
+
+ @return The Io port base address of Smbus host controller.
+
+**/
+UINTN
+InternalGetSmbusIoPortBaseAddress (
+ VOID
+ )
+{
+ UINTN IoPortBaseAddress;
+
+ if (FeaturePcdGet (PcdSmbaIoBaseAddressFixed)) {
+ IoPortBaseAddress = (UINTN) PcdGet16 (PcdSmbaIoBaseAddress);
+ } else {
+ IoPortBaseAddress = (UINTN) LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) & B_QNC_LPC_SMBUS_BASE_MASK;
+ }
+
+ //
+ // Make sure that the IO port base address has been properly set.
+ //
+ ASSERT (IoPortBaseAddress != 0);
+
+ return IoPortBaseAddress;
+}
+
+
+/**
+ Acquires the ownership of SMBUS.
+
+ This internal function reads the host state register.
+ If the SMBUS is not available, RETURN_TIMEOUT is returned;
+ Otherwise, it performs some basic initializations and returns
+ RETURN_SUCCESS.
+
+ @param IoPortBaseAddress The Io port base address of Smbus Host controller.
+
+ @retval RETURN_SUCCESS The SMBUS command was executed successfully.
+ @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command.
+
+**/
+RETURN_STATUS
+InternalSmBusAcquire (
+ UINTN IoPortBaseAddress
+ )
+{
+
+ //
+ // Clear host status register and exit.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL, 0);
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, 0);
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD1, 0);
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Starts the SMBUS transaction and waits until the end.
+
+ This internal function start the SMBUS transaction and waits until the transaction
+ of SMBUS is over by polling the INTR bit of Host status register.
+ If the SMBUS is not available, RETURN_TIMEOUT is returned;
+ Otherwise, it performs some basic initializations and returns
+ RETURN_SUCCESS.
+
+ @param IoPortBaseAddress The Io port base address of Smbus Host controller.
+ @param HostControl The Host control command to start SMBUS transaction.
+
+ @retval RETURN_SUCCESS The SMBUS command was executed successfully.
+ @retval RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect).
+ @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected
+ in the Host Status Register bit. Device errors are
+ a result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+
+**/
+RETURN_STATUS
+InternalSmBusStart (
+ IN UINTN IoPortBaseAddress,
+ IN UINT8 HostControl
+ )
+{
+ UINT8 HostStatus;
+
+ //
+ // Set Host Control Register (Initiate Operation, Interrupt disabled).
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL, HostControl + B_QNC_SMBUS_START);
+
+ do {
+ //
+ // Poll INTR bit of Host Status Register.
+ //
+ HostStatus = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS);
+ } while ((HostStatus & (B_QNC_SMBUS_BYTE_DONE_STS | B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR)) == 0);
+
+ if ((HostStatus & (B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR)) == 0) {
+ return RETURN_SUCCESS;
+ }
+ //
+ // Clear error bits of Host Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, (B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR));
+
+ return RETURN_DEVICE_ERROR;
+}
+
+/**
+ Executes an SMBUS quick, byte or word command.
+
+ This internal function executes an SMBUS quick, byte or word commond.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+
+ @param HostControl The value of Host Control Register to set.
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Value The byte/word write to the SMBUS.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The byte/word read from the SMBUS.
+
+**/
+UINT16
+InternalSmBusNonBlock (
+ IN UINT8 HostControl,
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status
+ )
+{
+ RETURN_STATUS ReturnStatus;
+ UINTN IoPortBaseAddress;
+
+ IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
+
+ //
+ // Try to acquire the ownership of QNC SMBUS.
+ //
+ ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+
+ //
+ // Set Host Commond Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
+ //
+ // Write value to Host Data 0 and Host Data 1 Registers.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, (UINT8) Value);
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD1, (UINT8) (Value >> 8));
+
+
+ //
+ // Set SMBUS slave address for the device to send/receive from.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_TSA, (UINT8) SmBusAddress);
+ //
+ // Start the SMBUS transaction and wait for the end.
+ //
+ ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
+ //
+ // Read value from Host Data 0 and Host Data 1 Registers.
+ //
+ Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD1) << 8);
+ Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD0));
+
+ //
+ // Clear Host Status Register and Auxiliary Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
+
+Done:
+ if (Status != NULL) {
+ *Status = ReturnStatus;
+ }
+
+ return Value;
+}
+
+/**
+ Executes an SMBUS quick read command.
+
+ Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If PEC is set in SmBusAddress, then ASSERT().
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+SmBusQuickRead (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_QUICK,
+ SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
+ 0,
+ Status
+ );
+
+}
+
+/**
+ Executes an SMBUS quick write command.
+
+ Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If PEC is set in SmBusAddress, then ASSERT().
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+SmBusQuickWrite (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_QUICK,
+ SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
+ 0,
+ Status
+ );
+
+}
+
+/**
+ Executes an SMBUS receive byte command.
+
+ Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ The byte received from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The byte received from the SMBUS.
+
+**/
+UINT8
+EFIAPI
+SmBusReceiveByte (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_BYTE,
+ SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
+ 0,
+ Status
+ );
+
+}
+
+/**
+ Executes an SMBUS send byte command.
+
+ Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress.
+ The byte specified by Value is sent.
+ Only the SMBUS slave address field of SmBusAddress is required. Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Value The 8-bit value to send.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The parameter of Value.
+
+**/
+UINT8
+EFIAPI
+SmBusSendByte (
+ IN UINTN SmBusAddress,
+ IN UINT8 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_BYTE,
+ SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
+ Value,
+ Status
+ );
+
+}
+
+/**
+ Executes an SMBUS read data byte command.
+
+ Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 8-bit value read from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The byte read from the SMBUS.
+
+**/
+UINT8
+EFIAPI
+SmBusReadDataByte (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_BYTE_DATA,
+ SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS write data byte command.
+
+ Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress.
+ The 8-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Value The 8-bit value to write.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The parameter of Value.
+
+**/
+UINT8
+EFIAPI
+SmBusWriteDataByte (
+ IN UINTN SmBusAddress,
+ IN UINT8 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_BYTE_DATA,
+ SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS read data word command.
+
+ Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 16-bit value read from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The byte read from the SMBUS.
+
+**/
+UINT16
+EFIAPI
+SmBusReadDataWord (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 2);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_WORD_DATA,
+ SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
+ 0,
+ Status
+ );
+
+}
+
+/**
+ Executes an SMBUS write data word command.
+
+ Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress.
+ The 16-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Value The 16-bit value to write.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The parameter of Value.
+
+**/
+UINT16
+EFIAPI
+SmBusWriteDataWord (
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 2);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_WORD_DATA,
+ SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS process call command.
+
+ Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress.
+ The 16-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 16-bit value returned by the process call command is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Value The 16-bit value to write.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The 16-bit value returned by the process call command.
+
+**/
+UINT16
+EFIAPI
+SmBusProcessCall (
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return InternalSmBusNonBlock (
+ V_QNC_SMBUS_HCTL_CMD_PROCESS_CALL,
+ SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
+ Value,
+ Status
+ );
+
+}
+
+/**
+ Executes an SMBUS block command.
+
+ Executes an SMBUS block read, block write and block write-block read command
+ on the SMBUS device specified by SmBusAddress.
+ Bytes are read from the SMBUS and stored in Buffer.
+ The number of bytes read is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+ SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
+
+ @param HostControl The value of Host Control Register to set.
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
+ @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The number of bytes read from the SMBUS.
+
+**/
+UINTN
+InternalSmBusBlock (
+ IN UINT8 HostControl,
+ IN UINTN SmBusAddress,
+ IN UINT8 *WriteBuffer,
+ OUT UINT8 *ReadBuffer,
+ OUT RETURN_STATUS *Status
+ )
+{
+ RETURN_STATUS ReturnStatus;
+ UINTN Index;
+ UINTN BytesCount;
+ UINTN IoPortBaseAddress;
+
+ IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
+
+ BytesCount = SMBUS_LIB_LENGTH (SmBusAddress);
+
+ //
+ // Try to acquire the ownership of ICH SMBUS.
+ //
+ ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+
+ //
+ // Set Host Command Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
+
+ //
+ // Clear byte pointer of 32-byte buffer.
+ //
+ IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL);
+
+ if (WriteBuffer != NULL) {
+ //
+ // Write the number of block to Host Block Data Byte Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, (UINT8) BytesCount);
+ //
+ // Write data block to Host Block Data Register.
+ //
+ for (Index = 0; Index < BytesCount; Index++) {
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HBD + (UINT8)Index, WriteBuffer[Index]);
+ }
+ }
+ //
+ // Set SMBUS slave address for the device to send/receive from.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_TSA, (UINT8) SmBusAddress);
+ //
+ // Start the SMBUS transaction and wait for the end.
+ //
+ ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+
+ if (ReadBuffer != NULL) {
+ //
+ // Read the number of block from host block data byte register.
+ //
+ BytesCount = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD0);
+ //
+ // Write data block from Host Block Data Register.
+ //
+ for (Index = 0; Index < BytesCount; Index++) {
+ ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HBD + (UINT8)Index);
+ }
+ }
+
+Done:
+ //
+ // Clear Host Status Register and Auxiliary Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
+
+ if (Status != NULL) {
+ *Status = ReturnStatus;
+ }
+
+ return BytesCount;
+}
+
+/**
+ Executes an SMBUS read block command.
+
+ Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Bytes are read from the SMBUS and stored in Buffer.
+ The number of bytes read is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+ SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If Buffer is NULL, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Buffer Pointer to the buffer to store the bytes read from the SMBUS.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The number of bytes read.
+
+**/
+UINTN
+EFIAPI
+SmBusReadBlock (
+ IN UINTN SmBusAddress,
+ OUT VOID *Buffer,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (Buffer != NULL);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return InternalSmBusBlock (
+ V_QNC_SMBUS_HCTL_CMD_BLOCK,
+ SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
+ NULL,
+ Buffer,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS write block command.
+
+ Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress.
+ The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
+ Bytes are written to the SMBUS from Buffer.
+ The number of bytes written is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is zero or greater than 32, then ASSERT().
+ If Buffer is NULL, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param Buffer Pointer to the buffer to store the bytes read from the SMBUS.
+ @param Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @return The number of bytes written.
+
+**/
+UINTN
+EFIAPI
+SmBusWriteBlock (
+ IN UINTN SmBusAddress,
+ OUT VOID *Buffer,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (Buffer != NULL);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ return InternalSmBusBlock (
+ V_QNC_SMBUS_HCTL_CMD_BLOCK,
+ SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
+ Buffer,
+ NULL,
+ Status
+ );
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf
new file mode 100644
index 0000000..fe0e3b5
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf
@@ -0,0 +1,74 @@
+## @file
+# Component description file for Intel QNC Smbus Library.
+#
+# SMBUS Library that layers on top of the I/O Library to directly
+# access a standard SMBUS host controller.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmbusLib
+ FILE_GUID = 6F2F36B3-936B-4eb2-83C7-2987B4F9D4EB
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SmbusLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ SmbusLib.c
+ CommonHeader.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+
+[LibraryClasses]
+ PcdLib
+ DebugLib
+ PciLib
+ IoLib
+
+
+[FeaturePcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddressFixed
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.c
new file mode 100755
index 0000000..5a8480a
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.c
@@ -0,0 +1,83 @@
+/**@file
+ Framework PEIM to initialize memory on a QuarkNcSocId Memory Controller.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ **/
+
+//
+// Include common header file for this module.
+//
+#include "MemoryInit.h"
+
+static PEI_CLT_MEMORY_INIT_PPI mPeiCltMemoryInitPpi =
+{ MrcStart };
+
+static EFI_PEI_PPI_DESCRIPTOR PpiListPeiCltMemoryInit =
+{
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gCltMemoryInitPpiGuid,
+ &mPeiCltMemoryInitPpi
+};
+
+void Mrc( MRCParams_t *MrcData);
+
+/**
+
+ Do memory initialization for QuarkNcSocId DDR3 SDRAM Controller
+
+ @param FfsHeader Not used.
+ @param PeiServices General purpose services available to every PEIM.
+
+ @return EFI_SUCCESS Memory initialization completed successfully.
+ All other error conditions encountered result in an ASSERT.
+
+ **/
+EFI_STATUS
+PeimMemoryInit(
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = (**PeiServices).InstallPpi(PeiServices, &PpiListPeiCltMemoryInit);
+
+ return Status;
+}
+
+VOID
+EFIAPI
+MrcStart(
+ IN OUT MRCParams_t *MrcData
+ )
+{
+
+ Mrc(MrcData);
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.h
new file mode 100755
index 0000000..20d4df6
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.h
@@ -0,0 +1,59 @@
+/**@file
+ Framework PEIM to initialize memory on an DDR2 SDRAM Memory Controller.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef _PEI_QNC_MEMORY_INIT_H_
+#define _PEI_QNC_MEMORY_INIT_H_
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+#include <IntelQNCPeim.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Ppi/CltMemoryInit.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+
+
+VOID
+EFIAPI
+MrcStart (
+ IN OUT MRCParams_t *MrcData
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
new file mode 100755
index 0000000..28583aa
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
@@ -0,0 +1,96 @@
+## @file
+# This is the Memory Initialization Driver for Quark
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MemoryInitPei
+ FILE_GUID = D2C69B26-82E1-4a1b-AD35-ED0261B9F347
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PeimMemoryInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[BuildOptions]
+ GCC:DEBUG_*_*_CC_FLAGS = -DGCC
+ GCC:RELEASE_*_*_CC_FLAGS = -DNDEBUG -DGCC
+ INTEL:RELEASE_*_*_CC_FLAGS = /D NDEBUG
+ MSFT:RELEASE_*_*_CC_FLAGS = /D NDEBUG
+
+[Sources]
+ memory_options.h
+ platform.c
+ lprint.c
+ meminit.h
+ meminit.c
+ meminit_utils.h
+ meminit_utils.c
+ gen5_iosf_sb_definitions.h
+ general_definitions.h
+ io.h
+ core_types.h
+ prememinit.h
+ prememinit.c
+ mrc.h
+ mrc.c
+ hte.c
+ hte.h
+ MemoryInit.h
+ MemoryInit.c
+
+[Packages]
+ QuarkSocPkg/QuarkSocPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ BaseMemoryLib
+
+[Ppis]
+ gCltMemoryInitPpiGuid # PPI ALWAYS_PRODUCED
+
+[Depex]
+ TRUE
+ \ No newline at end of file
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/core_types.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/core_types.h
new file mode 100755
index 0000000..5415a9c
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/core_types.h
@@ -0,0 +1,74 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Core_types.h
+
+ Abstract:
+
+ Core types used in Mrc.
+
+ --*/
+#ifndef __MRC_CORE_TYPES_H
+#define __MRC_CORE_TYPES_H
+
+typedef char char_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned char bool;
+typedef unsigned int size_t;
+
+#ifdef ASM_INC
+// Unfortunately h2inc has issue with long long
+typedef struct uint64_s
+{
+ uint32_t lo;
+ uint32_t hi;
+}uint64_t;
+#else
+typedef unsigned long long uint64_t;
+#endif
+
+#ifdef SIM
+// Native word length is 64bit in simulation environment
+typedef uint64_t uintn_t;
+#else
+// Quark is 32bit
+typedef uint32_t uintn_t;
+#endif
+
+#define PTR32(a) ((volatile uint32_t*)(uintn_t)(a))
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/gen5_iosf_sb_definitions.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/gen5_iosf_sb_definitions.h
new file mode 100755
index 0000000..3886953
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/gen5_iosf_sb_definitions.h
@@ -0,0 +1,762 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * MCU register definition
+ *
+ ************************************************************************/
+#ifndef __IOSF_DEFINITIONS_H
+#define __IOSF_DEFINITIONS_H
+
+// Define each of the IOSF-SB register offsets used by MRC.
+
+
+// MCU registers (DUNIT):
+// ====
+#define DRP 0x0000
+#define DTR0 0x0001
+#define DTR1 0x0002
+#define DTR2 0x0003
+#define DTR3 0x0004
+#define DTR4 0x0005
+#define DPMC0 0x0006
+#define DPMC1 0x0007
+#define DRFC 0x0008
+#define DSCH 0x0009
+#define DCAL 0x000A
+#define DRMC 0x000B
+#define PMSTS 0x000C
+#define DCO 0x000F
+#define DSTAT 0x0020
+#define DECCCTRL 0x0060
+#define DFUSESTAT 0x0070
+#define SCRMSEED 0x0080
+#define SCRMLO 0x0081
+#define SCRMHI 0x0082
+
+#define MCU_CH_OFFSET 0x0040
+#define MCU_RK_OFFSET 0x0020
+
+////
+//
+// BEGIN DUnit register definition
+//
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t rank0Enabled :1; /**< BIT [0] Rank 0 Enable */
+ uint32_t rank1Enabled :1; /**< BIT [1] Rank 1 Enable */
+ uint32_t reserved0 :2;
+ uint32_t dimm0DevWidth :2; /**< BIT [5:4] DIMM 0 Device Width (Rank0&1) */
+ uint32_t dimm0DevDensity :2; /**< BIT [7:6] DIMM 0 Device Density */
+ uint32_t reserved1 :1;
+ uint32_t dimm1DevWidth :2; /**< BIT [10:9] DIMM 1 Device Width (Rank2&3) */
+ uint32_t dimm1DevDensity :2; /**< BIT [12:11] DIMM 1 Device Density */
+ uint32_t split64 :1; /**< BIT [13] split 64B transactions */
+ uint32_t addressMap :2; /**< BIT [15:14] Address Map select */
+ uint32_t reserved3 :14;
+ uint32_t mode32 :1; /**< BIT [30] Select 32bit data interface*/
+ uint32_t reserved4 :1;
+ } field;
+} RegDRP; /**< DRAM Rank Population and Interface Register */
+#pragma pack()
+
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t dramFrequency :2; /**< DRAM Frequency (000=800,001=1033,010=1333) */
+ uint32_t reserved1 :2;
+ uint32_t tRP :4; /**< bit [7:4] Precharge to Activate Delay */
+ uint32_t tRCD :4; /**< bit [11:8] Activate to CAS Delay */
+ uint32_t tCL :3; /**< bit [14:12] CAS Latency */
+ uint32_t reserved4 :1;
+ uint32_t tXS :1; /**< SRX Delay */
+ uint32_t reserved5 :1;
+ uint32_t tXSDLL :1; /**< SRX To DLL Delay */
+ uint32_t reserved6 :1;
+ uint32_t tZQCS :1; /**< bit [20] ZQTS recovery Latncy */
+ uint32_t reserved7 :1;
+ uint32_t tZQCL :1; /**< bit [22] ZQCL recovery Latncy */
+ uint32_t reserved8 :1;
+ uint32_t pmeDelay :2; /**< bit [25:24] Power mode entry delay */
+ uint32_t reserved9 :2;
+ uint32_t CKEDLY :4; /**< bit [31:28] */
+ } field;
+} RegDTR0; /**< DRAM Timing Register 0 */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t tWCL :3; /**< bit [2:0] CAS Write Latency */
+ uint32_t reserved1 :1;
+ uint32_t tCMD :2; /**< bit [5:4] Command transport duration */
+ uint32_t reserved2 :2;
+ uint32_t tWTP :4; /**< Write to Precharge */
+ uint32_t tCCD :2; /**< CAS to CAS delay */
+ uint32_t reserved4 :2;
+ uint32_t tFAW :4; /**< Four bank Activation Window*/
+ uint32_t tRAS :4; /**< Row Activation Period: */
+ uint32_t tRRD :2; /**<Row activation to Row activation Delay */
+ uint32_t reserved5 :2;
+ uint32_t tRTP :3; /**<Read to Precharge Delay */
+ uint32_t reserved6 :1;
+ } field;
+} RegDTR1; /**< DRAM Timing Register 1 */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t tRRDR :3; /**< RD to RD from different ranks, same DIMM */
+ uint32_t reserved1 :5;
+ uint32_t tWWDR :3; /**< WR to WR from different ranks, same DIMM. */
+ uint32_t reserved3 :5;
+ uint32_t tRWDR :4; /**< bit [19:16] RD to WR from different ranks, same DIMM. */
+ uint32_t reserved5 :12;
+ } field;
+} RegDTR2; /**< DRAM Timing Register 2 */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t tWRDR :3; /**< WR to RD from different ranks, same DIMM. */
+ uint32_t reserved1 :1;
+ uint32_t tWRDD :3; /**< WR to RD from different DIMM. */
+ uint32_t reserved2 :1;
+ uint32_t tRWSR :4; /**< RD to WR Same Rank. */
+ uint32_t reserved3 :1;
+ uint32_t tWRSR :4; /**< WR to RD Same Rank. */
+ uint32_t reserved4 :5;
+ uint32_t tXP :2; /**< Time from CKE set on to any command. */
+ uint32_t PWD_DLY :4; /**< Extended Power-Down Delay. */
+ uint32_t EnDeRate :1;
+ uint32_t DeRateOvr :1;
+ uint32_t DeRateStat :1;
+ uint32_t reserved5 :1;
+ } field;
+} RegDTR3; /**< DRAM Timing Register 3 */
+#pragma pack()
+
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t WRODTSTRT :2; /**< WR command to ODT assert delay */
+ uint32_t reserved1 :2;
+ uint32_t WRODTSTOP :3; /**< Write command to ODT de-assert delay. */
+ uint32_t reserved2 :1;
+ uint32_t RDODTSTRT :3; /**< Read command to ODT assert delay */
+ uint32_t reserved3 :1;
+ uint32_t RDODTSTOP :3; /**< Read command to ODT de-assert delay */
+ uint32_t ODTDIS :1; /**< ODT disable */
+ uint32_t TRGSTRDIS :1; /**< Write target rank is not stretched */
+ uint32_t RDODTDIS :1; /**< Disable Read ODT */
+ uint32_t WRBODTDIS :1; /**< Disable Write ODT */
+ uint32_t reserved5 :13;
+ } field;
+} RegDTR4; /**< DRAM Timing Register 3 */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t SREntryDelay :8; /**< Self-Refresh Entry Delay: */
+ uint32_t powerModeOpCode :5; /**< SPID Power Mode Opcode */
+ uint32_t reserved1 :3;
+ uint32_t PCLSTO :3; /**< Page Close Timeout Period */
+ uint32_t reserved2 :1;
+ uint32_t PCLSWKOK :1; /**< Wake Allowed For Page Close Timeout */
+ uint32_t PREAPWDEN :1; /**< Send Precharge All to rank before entering Power-Down mode. */
+ uint32_t reserved3 :1;
+ uint32_t DYNSREN :1; /**< Dynamic Self-Refresh */
+ uint32_t CLKGTDIS :1; /**< Clock Gating Disabled*/
+ uint32_t DISPWRDN :1; /**< Disable Power Down*/
+ uint32_t reserved4 :2;
+ uint32_t REUTCLKGTDIS :1;
+ uint32_t ENPHYCLKGATE :1;
+ uint32_t reserved5 :2;
+ } field;
+} RegDPMC0; /**< DRAM Power Management Control Register 0 */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t REFWMLO :4; /**< Refresh Opportunistic Watermark */
+ uint32_t REFWMHI :4; /**< Refresh High Watermark*/
+ uint32_t REFWMPNC :4; /**< Refresh Panic Watermark */
+ uint32_t tREFI :3; /**< bit [14:12] Refresh Period */
+ uint32_t reserved1 :1;
+ uint32_t REFCNTMAX :2; /**< Refresh Max tREFI Interval */
+ uint32_t reserved2 :2;
+ uint32_t REFSKEWDIS :1; /**< tREFI counters */
+ uint32_t REFDBTCLR :1;
+ uint32_t reserved3 :2;
+ uint32_t CuRefRate :3;
+ uint32_t DisRefBW :1;
+ uint32_t reserved4 :4;
+ } field;
+} RegDRCF; /**< DRAM Refresh Control Register*/
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t reserved1 :8;
+ uint32_t ZQCINT :3; /**< ZQ Calibration Short Interval: */
+ uint32_t reserved2 :1;
+ uint32_t SRXZQCL :2; /** < ZQ Calibration Length */
+ uint32_t ZQCalType :1;
+ uint32_t ZQCalStart :1;
+ uint32_t TQPollStart :1;
+ uint32_t TQPollRS :2;
+ uint32_t reserved3 :5;
+ uint32_t MRRData :8; /**< bit[31:24] */
+ } field;
+} RegDCAL; /**< DRAM Calibration Control*/
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t OOOAGETRH :5; /**< Out-of-Order Aging Threshold */
+ uint32_t reserved1 :3;
+ uint32_t OOODIS :1; /**< Out-of-Order Disable */
+ uint32_t OOOST3DIS :1; /**< Out-of-Order Disabled when RequestBD_Status is 3. */
+ uint32_t reserved2 :2;
+ uint32_t NEWBYPDIS :1;
+ uint32_t reserved3 :3;
+ uint32_t IPREQMAX :3; /** < Max In-Progress Requests stored in MC */
+ uint32_t reserved4 :13;
+ } field;
+} RegDSCH; /**< DRAM Scheduler Control Register */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t DRPLOCK :1; /**< DRP lock bit */
+ uint32_t reserved1 :7;
+ uint32_t REUTLOCK :1; /**< REUT lock bit */
+ uint32_t reserved2 :19;
+ uint32_t PMICTL :1; /**< PRI Control Select: 0-memory_manager, 1-hte */
+ uint32_t PMIDIS :1; /**< PMIDIS Should be set is using IOSF-SB RW */
+ uint32_t DIOIC :1; /**< DDRIO initialization is complete */
+ uint32_t IC :1; /**< D-unit Initialization Complete */
+ } field;
+} RegDCO; /**< DRAM Controller Operation Register*/
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t SBEEN :1; /**< Enable Single Bit Error Detection and Correction */
+ uint32_t DBEEN :1; /**< Enable Double Bit Error Detection */
+ uint32_t CBOEN :3; /**< Enable ECC Check Bits Override */
+ uint32_t SYNSEL :2; /**< ECC Syndrome Bits Select for Observation */
+ uint32_t CLRSBECNT :1; /**< Clear ECC Single Bit Error Count */
+ uint32_t CBOV :8; /**< ECC Check Bits Override Value */
+ uint32_t reserved1 :1; /**< */
+ uint32_t ENCBGEN :1; /**< Enable Generation of ECC Check Bits */
+ uint32_t ENCBGESWIZ :1; /**< Enable Same Chip ECC Byte Lane Swizzle */
+
+ } field;
+} RegDECCCTRL; /**< DRAM ECC Control Register */
+#pragma pack()
+
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t FUS_DUN_ECC_DIS :1;
+ uint32_t FUS_DUN_MAX_SUPPORTED_MEMORY :3;
+ uint32_t FUS_DUN_MAX_DEVDEN :2;
+ uint32_t RESERVED1 :1;
+ uint32_t FUS_DUN_RANK2_DIS :1;
+ uint32_t FUS_DUN_OOO_DIS :1;
+ uint32_t FUS_DUN_MEMX8_DIS :1;
+ uint32_t FUS_DUN_MEMX16_DIS :1;
+ uint32_t RESERVED2 :1;
+ uint32_t FUS_DUN_1N_DIS :1;
+ uint32_t FUS_DUN_DQ_SCRAMBLER_DIS :1;
+ uint32_t RESERVED3 :1;
+ uint32_t FUS_DUN_32BIT_DRAM_IFC :1;
+ } field;
+} RegDFUSESTAT;
+#pragma pack()
+
+//
+// END DUnit register definition
+//
+////
+
+
+
+////
+//
+// DRAM Initialization Structures used in JEDEC Message Bus Commands
+//
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ unsigned command :3; /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110-ZQ,111-NOP */
+ unsigned bankAddress :3; /**< Bank Address (BA[2:0]) */
+ unsigned BL :2; /**< Burst Length, CDV:1*/
+ unsigned CL :1; /**< CL Reserved CDV:0 */
+ unsigned RBT :1; /**< Read Burst Type */
+ unsigned casLatency :3; /**< cas Latency */
+ unsigned TM :1; /**< Test mode */
+ unsigned dllReset :1; /**< DLL Reset */
+ unsigned writeRecovery :3; /**< Write Recovery for Auto Pre-Charge: 001=2,010=3,011=4,100=5,101=6 */
+ unsigned PPD :1; /**< DLL Control for Precharge Power-Down CDV:1 */
+ unsigned reserved1 :3;
+ unsigned rankSelect :4; /**< Rank Select */
+ unsigned reserved2 :6;
+ } field;
+} DramInitDDR3MRS0; /**< DDR3 Mode Register Set (MRS) Command */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ unsigned command :3; /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110-ZQ,111-NOP */
+ unsigned bankAddress :3; /**< Bank Address (BA[2:0]) */
+ unsigned dllEnabled :1; /**< CDV=0 */
+ unsigned DIC0 :1; /**< Output Driver Impedance Control */
+ unsigned rttNom0 :1; /**< RTT_nom[0] */
+ unsigned MRC_AL :2; /**< Additive Latency = 0 */
+ unsigned DIC1 :1; /**< Reserved */
+ unsigned rttNom1 :1; /**< RTT_nom[1] */
+ unsigned wlEnabled :1; /**< Write Leveling Enable */
+ unsigned reserved1 :1;
+ unsigned rttNom2 :1; /** < RTT_nom[2] */
+ unsigned reserved2 :1;
+ unsigned TDQS :1; /**< TDQS Enable */
+ unsigned Qoff :1; /**< Output Buffers Disabled */
+ unsigned reserved3 :3;
+ unsigned rankSelect :4; /**< Rank Select */
+ unsigned reserved4 :6;
+ } field;
+} DramInitDDR3EMR1; /**< DDR3 Extended Mode Register 1 Set (EMRS1) Command */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t command :3; /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110-ZQ,111-NOP */
+ uint32_t bankAddress :3; /**< Bank Address (BA[2:0]) */
+ uint32_t PASR :3; /**< Partial Array Self-Refresh */
+ uint32_t CWL :3; /**< CAS Write Latency */
+ uint32_t ASR :1; /**< Auto Self-Refresh */
+ uint32_t SRT :1; /**< SR Temperature Range = 0*/
+ uint32_t reserved1 :1;
+ uint32_t rtt_WR :2; /**< Rtt_WR */
+ uint32_t reserved2 :5;
+ uint32_t rankSelect :4; /**< Rank Select */
+ uint32_t reserved3 :6;
+ } field;
+} DramInitDDR3EMR2; /**< DDR3 Extended Mode Register 2 Set (EMRS2) Command */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t command :3; /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110-ZQ,111-NOP */
+ uint32_t bankAddress :3; /**< Bank Address (BA[2:0]) */
+ uint32_t MPR_Location :2; /**< MPR Location */
+ uint32_t MPR :1; /**< MPR: Multi Purpose Register */
+ uint32_t reserved1 :13;
+ uint32_t rankSelect :4; /**< Rank Select */
+ uint32_t reserved2 :6;
+ } field;
+} DramInitDDR3EMR3; /**< DDR3 Extended Mode Register 2 Set (EMRS2) Command */
+#pragma pack()
+
+#pragma pack(1)
+typedef union {
+ uint32_t raw;
+ struct {
+ uint32_t command :3; /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110 – ZQ Calibration,111-NOP */
+ uint32_t bankAddress :3; /**< Bank Address (BA[2:0]) */
+ uint32_t multAddress :16; /**< Multiplexed Address (MA[14:0]) */
+ uint32_t rankSelect :2; /**< Rank Select */
+ uint32_t reserved3 :8;
+ } field;
+} DramInitMisc; /**< Miscellaneous DDRx Initialization Command */
+#pragma pack()
+
+//
+// Construct DRAM init command using DramInitXxxx pattern
+//
+#define DCMD_MRS1(rnk,dat) (0 | ((rnk)<<22) | (1<<3) | ((dat)<<6))
+#define DCMD_REF(rnk) (1 | ((rnk)<<22))
+#define DCMD_PRE(rnk) (2 | ((rnk)<<22))
+#define DCMD_PREA(rnk) (2 | ((rnk)<<22) | (BIT10<<6))
+#define DCMD_ACT(rnk,row) (3 | ((rnk)<<22) | ((row)<<6))
+#define DCMD_WR(rnk,col) (4 | ((rnk)<<22) | ((col)<<6))
+#define DCMD_RD(rnk,col) (5 | ((rnk)<<22) | ((col)<<6))
+#define DCMD_ZQCS(rnk) (6 | ((rnk)<<22))
+#define DCMD_ZQCL(rnk) (6 | ((rnk)<<22) | (BIT10<<6))
+#define DCMD_NOP(rnk) (7 | ((rnk)<<22))
+
+
+
+
+#define DDR3_EMRS1_DIC_40 (0)
+#define DDR3_EMRS1_DIC_34 (1)
+
+#define DDR3_EMRS2_RTTWR_60 (BIT9)
+#define DDR3_EMRS2_RTTWR_120 (BIT10)
+
+#define DDR3_EMRS1_RTTNOM_0 (0)
+#define DDR3_EMRS1_RTTNOM_60 (BIT2)
+#define DDR3_EMRS1_RTTNOM_120 (BIT6)
+#define DDR3_EMRS1_RTTNOM_40 (BIT6|BIT2)
+#define DDR3_EMRS1_RTTNOM_20 (BIT9)
+#define DDR3_EMRS1_RTTNOM_30 (BIT9|BIT2)
+
+
+//
+// END DRAM Init...
+//
+////
+
+
+// HOST_BRIDGE registers:
+#define HMBOUND 0x0020 //ok
+
+// MEMORY_MANAGER registers:
+#define BCTRL 0x0004
+#define BWFLUSH 0x0008
+#define BDEBUG1 0x00C4
+
+////
+//
+// BEGIN DDRIO registers
+//
+
+// DDR IOs & COMPs:
+#define DDRIODQ_BL_OFFSET 0x0800
+#define DDRIODQ_CH_OFFSET ((NUM_BYTE_LANES/2) * DDRIODQ_BL_OFFSET)
+#define DDRIOCCC_CH_OFFSET 0x0800
+#define DDRCOMP_CH_OFFSET 0x0100
+
+// CH0-BL01-DQ
+#define DQOBSCKEBBCTL 0x0000
+#define DQDLLTXCTL 0x0004
+#define DQDLLRXCTL 0x0008
+#define DQMDLLCTL 0x000C
+#define B0RXIOBUFCTL 0x0010
+#define B0VREFCTL 0x0014
+#define B0RXOFFSET1 0x0018
+#define B0RXOFFSET0 0x001C
+#define B1RXIOBUFCTL 0x0020
+#define B1VREFCTL 0x0024
+#define B1RXOFFSET1 0x0028
+#define B1RXOFFSET0 0x002C
+#define DQDFTCTL 0x0030
+#define DQTRAINSTS 0x0034
+#define B1DLLPICODER0 0x0038
+#define B0DLLPICODER0 0x003C
+#define B1DLLPICODER1 0x0040
+#define B0DLLPICODER1 0x0044
+#define B1DLLPICODER2 0x0048
+#define B0DLLPICODER2 0x004C
+#define B1DLLPICODER3 0x0050
+#define B0DLLPICODER3 0x0054
+#define B1RXDQSPICODE 0x0058
+#define B0RXDQSPICODE 0x005C
+#define B1RXDQPICODER32 0x0060
+#define B1RXDQPICODER10 0x0064
+#define B0RXDQPICODER32 0x0068
+#define B0RXDQPICODER10 0x006C
+#define B01PTRCTL0 0x0070
+#define B01PTRCTL1 0x0074
+#define B01DBCTL0 0x0078
+#define B01DBCTL1 0x007C
+#define B0LATCTL0 0x0080
+#define B1LATCTL0 0x0084
+#define B01LATCTL1 0x0088
+#define B0ONDURCTL 0x008C
+#define B1ONDURCTL 0x0090
+#define B0OVRCTL 0x0094
+#define B1OVRCTL 0x0098
+#define DQCTL 0x009C
+#define B0RK2RKCHGPTRCTRL 0x00A0
+#define B1RK2RKCHGPTRCTRL 0x00A4
+#define DQRK2RKCTL 0x00A8
+#define DQRK2RKPTRCTL 0x00AC
+#define B0RK2RKLAT 0x00B0
+#define B1RK2RKLAT 0x00B4
+#define DQCLKALIGNREG0 0x00B8
+#define DQCLKALIGNREG1 0x00BC
+#define DQCLKALIGNREG2 0x00C0
+#define DQCLKALIGNSTS0 0x00C4
+#define DQCLKALIGNSTS1 0x00C8
+#define DQCLKGATE 0x00CC
+#define B0COMPSLV1 0x00D0
+#define B1COMPSLV1 0x00D4
+#define B0COMPSLV2 0x00D8
+#define B1COMPSLV2 0x00DC
+#define B0COMPSLV3 0x00E0
+#define B1COMPSLV3 0x00E4
+#define DQVISALANECR0TOP 0x00E8
+#define DQVISALANECR1TOP 0x00EC
+#define DQVISACONTROLCRTOP 0x00F0
+#define DQVISALANECR0BL 0x00F4
+#define DQVISALANECR1BL 0x00F8
+#define DQVISACONTROLCRBL 0x00FC
+#define DQTIMINGCTRL 0x010C
+// CH0-ECC
+#define ECCDLLTXCTL 0x2004
+#define ECCDLLRXCTL 0x2008
+#define ECCMDLLCTL 0x200C
+#define ECCB1DLLPICODER0 0x2038
+#define ECCB1DLLPICODER1 0x2040
+#define ECCB1DLLPICODER2 0x2048
+#define ECCB1DLLPICODER3 0x2050
+#define ECCB01DBCTL0 0x2078
+#define ECCB01DBCTL1 0x207C
+#define ECCCLKALIGNREG0 0x20B8
+#define ECCCLKALIGNREG1 0x20BC
+#define ECCCLKALIGNREG2 0x20C0
+// CH0-CMD
+#define CMDOBSCKEBBCTL 0x4800
+#define CMDDLLTXCTL 0x4808
+#define CMDDLLRXCTL 0x480C
+#define CMDMDLLCTL 0x4810
+#define CMDRCOMPODT 0x4814
+#define CMDDLLPICODER0 0x4820
+#define CMDDLLPICODER1 0x4824
+#define CMDCFGREG0 0x4840
+#define CMDPTRREG 0x4844
+#define CMDCLKALIGNREG0 0x4850
+#define CMDCLKALIGNREG1 0x4854
+#define CMDCLKALIGNREG2 0x4858
+#define CMDPMCONFIG0 0x485C
+#define CMDPMDLYREG0 0x4860
+#define CMDPMDLYREG1 0x4864
+#define CMDPMDLYREG2 0x4868
+#define CMDPMDLYREG3 0x486C
+#define CMDPMDLYREG4 0x4870
+#define CMDCLKALIGNSTS0 0x4874
+#define CMDCLKALIGNSTS1 0x4878
+#define CMDPMSTS0 0x487C
+#define CMDPMSTS1 0x4880
+#define CMDCOMPSLV 0x4884
+#define CMDBONUS0 0x488C
+#define CMDBONUS1 0x4890
+#define CMDVISALANECR0 0x4894
+#define CMDVISALANECR1 0x4898
+#define CMDVISACONTROLCR 0x489C
+#define CMDCLKGATE 0x48A0
+#define CMDTIMINGCTRL 0x48A4
+// CH0-CLK-CTL
+#define CCOBSCKEBBCTL 0x5800
+#define CCRCOMPIO 0x5804
+#define CCDLLTXCTL 0x5808
+#define CCDLLRXCTL 0x580C
+#define CCMDLLCTL 0x5810
+#define CCRCOMPODT 0x5814
+#define CCDLLPICODER0 0x5820
+#define CCDLLPICODER1 0x5824
+#define CCDDR3RESETCTL 0x5830
+#define CCCFGREG0 0x5838
+#define CCCFGREG1 0x5840
+#define CCPTRREG 0x5844
+#define CCCLKALIGNREG0 0x5850
+#define CCCLKALIGNREG1 0x5854
+#define CCCLKALIGNREG2 0x5858
+#define CCPMCONFIG0 0x585C
+#define CCPMDLYREG0 0x5860
+#define CCPMDLYREG1 0x5864
+#define CCPMDLYREG2 0x5868
+#define CCPMDLYREG3 0x586C
+#define CCPMDLYREG4 0x5870
+#define CCCLKALIGNSTS0 0x5874
+#define CCCLKALIGNSTS1 0x5878
+#define CCPMSTS0 0x587C
+#define CCPMSTS1 0x5880
+#define CCCOMPSLV1 0x5884
+#define CCCOMPSLV2 0x5888
+#define CCCOMPSLV3 0x588C
+#define CCBONUS0 0x5894
+#define CCBONUS1 0x5898
+#define CCVISALANECR0 0x589C
+#define CCVISALANECR1 0x58A0
+#define CCVISACONTROLCR 0x58A4
+#define CCCLKGATE 0x58A8
+#define CCTIMINGCTL 0x58AC
+// COMP
+#define CMPCTRL 0x6800
+#define SOFTRSTCNTL 0x6804
+#define MSCNTR 0x6808
+#define NMSCNTRL 0x680C
+#define LATCH1CTL 0x6814
+#define COMPVISALANECR0 0x681C
+#define COMPVISALANECR1 0x6820
+#define COMPVISACONTROLCR 0x6824
+#define COMPBONUS0 0x6830
+#define TCOCNTCTRL 0x683C
+#define DQANAODTPUCTL 0x6840
+#define DQANAODTPDCTL 0x6844
+#define DQANADRVPUCTL 0x6848
+#define DQANADRVPDCTL 0x684C
+#define DQANADLYPUCTL 0x6850
+#define DQANADLYPDCTL 0x6854
+#define DQANATCOPUCTL 0x6858
+#define DQANATCOPDCTL 0x685C
+#define CMDANADRVPUCTL 0x6868
+#define CMDANADRVPDCTL 0x686C
+#define CMDANADLYPUCTL 0x6870
+#define CMDANADLYPDCTL 0x6874
+#define CLKANAODTPUCTL 0x6880
+#define CLKANAODTPDCTL 0x6884
+#define CLKANADRVPUCTL 0x6888
+#define CLKANADRVPDCTL 0x688C
+#define CLKANADLYPUCTL 0x6890
+#define CLKANADLYPDCTL 0x6894
+#define CLKANATCOPUCTL 0x6898
+#define CLKANATCOPDCTL 0x689C
+#define DQSANAODTPUCTL 0x68A0
+#define DQSANAODTPDCTL 0x68A4
+#define DQSANADRVPUCTL 0x68A8
+#define DQSANADRVPDCTL 0x68AC
+#define DQSANADLYPUCTL 0x68B0
+#define DQSANADLYPDCTL 0x68B4
+#define DQSANATCOPUCTL 0x68B8
+#define DQSANATCOPDCTL 0x68BC
+#define CTLANADRVPUCTL 0x68C8
+#define CTLANADRVPDCTL 0x68CC
+#define CTLANADLYPUCTL 0x68D0
+#define CTLANADLYPDCTL 0x68D4
+#define CHNLBUFSTATIC 0x68F0
+#define COMPOBSCNTRL 0x68F4
+#define COMPBUFFDBG0 0x68F8
+#define COMPBUFFDBG1 0x68FC
+#define CFGMISCCH0 0x6900
+#define COMPEN0CH0 0x6904
+#define COMPEN1CH0 0x6908
+#define COMPEN2CH0 0x690C
+#define STATLEGEN0CH0 0x6910
+#define STATLEGEN1CH0 0x6914
+#define DQVREFCH0 0x6918
+#define CMDVREFCH0 0x691C
+#define CLKVREFCH0 0x6920
+#define DQSVREFCH0 0x6924
+#define CTLVREFCH0 0x6928
+#define TCOVREFCH0 0x692C
+#define DLYSELCH0 0x6930
+#define TCODRAMBUFODTCH0 0x6934
+#define CCBUFODTCH0 0x6938
+#define RXOFFSETCH0 0x693C
+#define DQODTPUCTLCH0 0x6940
+#define DQODTPDCTLCH0 0x6944
+#define DQDRVPUCTLCH0 0x6948
+#define DQDRVPDCTLCH0 0x694C
+#define DQDLYPUCTLCH0 0x6950
+#define DQDLYPDCTLCH0 0x6954
+#define DQTCOPUCTLCH0 0x6958
+#define DQTCOPDCTLCH0 0x695C
+#define CMDDRVPUCTLCH0 0x6968
+#define CMDDRVPDCTLCH0 0x696C
+#define CMDDLYPUCTLCH0 0x6970
+#define CMDDLYPDCTLCH0 0x6974
+#define CLKODTPUCTLCH0 0x6980
+#define CLKODTPDCTLCH0 0x6984
+#define CLKDRVPUCTLCH0 0x6988
+#define CLKDRVPDCTLCH0 0x698C
+#define CLKDLYPUCTLCH0 0x6990
+#define CLKDLYPDCTLCH0 0x6994
+#define CLKTCOPUCTLCH0 0x6998
+#define CLKTCOPDCTLCH0 0x699C
+#define DQSODTPUCTLCH0 0x69A0
+#define DQSODTPDCTLCH0 0x69A4
+#define DQSDRVPUCTLCH0 0x69A8
+#define DQSDRVPDCTLCH0 0x69AC
+#define DQSDLYPUCTLCH0 0x69B0
+#define DQSDLYPDCTLCH0 0x69B4
+#define DQSTCOPUCTLCH0 0x69B8
+#define DQSTCOPDCTLCH0 0x69BC
+#define CTLDRVPUCTLCH0 0x69C8
+#define CTLDRVPDCTLCH0 0x69CC
+#define CTLDLYPUCTLCH0 0x69D0
+#define CTLDLYPDCTLCH0 0x69D4
+#define FNLUPDTCTLCH0 0x69F0
+// PLL
+#define MPLLCTRL0 0x7800
+#define MPLLCTRL1 0x7808
+#define MPLLCSR0 0x7810
+#define MPLLCSR1 0x7814
+#define MPLLCSR2 0x7820
+#define MPLLDFT 0x7828
+#define MPLLMON0CTL 0x7830
+#define MPLLMON1CTL 0x7838
+#define MPLLMON2CTL 0x783C
+#define SFRTRIM 0x7850
+#define MPLLDFTOUT0 0x7858
+#define MPLLDFTOUT1 0x785C
+#define MASTERRSTN 0x7880
+#define PLLLOCKDEL 0x7884
+#define SFRDEL 0x7888
+#define CRUVISALANECR0 0x78F0
+#define CRUVISALANECR1 0x78F4
+#define CRUVISACONTROLCR 0x78F8
+#define IOSFVISALANECR0 0x78FC
+#define IOSFVISALANECR1 0x7900
+#define IOSFVISACONTROLCR 0x7904
+
+//
+// END DDRIO registers
+//
+////
+
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/general_definitions.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/general_definitions.h
new file mode 100755
index 0000000..5ff2987
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/general_definitions.h
@@ -0,0 +1,108 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************/
+#ifndef __GENERAL_DEFINITIONS_H
+#define __GENERAL_DEFINITIONS_H
+
+#undef BIT0
+#undef BIT1
+#undef BIT2
+#undef BIT3
+#undef BIT4
+#undef BIT5
+#undef BIT6
+#undef BIT7
+#undef BIT8
+#undef BIT9
+#undef BIT10
+#undef BIT11
+#undef BIT12
+#undef BIT13
+#undef BIT14
+#undef BIT15
+#undef BIT16
+#undef BIT17
+#undef BIT18
+#undef BIT19
+#undef BIT20
+#undef BIT21
+#undef BIT22
+#undef BIT23
+#undef BIT24
+#undef BIT25
+#undef BIT26
+#undef BIT27
+#undef BIT28
+#undef BIT29
+#undef BIT30
+#undef BIT31
+
+
+
+// defines
+#define BIT0 0x00000001U
+#define BIT1 0x00000002U
+#define BIT2 0x00000004U
+#define BIT3 0x00000008U
+#define BIT4 0x00000010U
+#define BIT5 0x00000020U
+#define BIT6 0x00000040U
+#define BIT7 0x00000080U
+#define BIT8 0x00000100U
+#define BIT9 0x00000200U
+#define BIT10 0x00000400U
+#define BIT11 0x00000800U
+#define BIT12 0x00001000U
+#define BIT13 0x00002000U
+#define BIT14 0x00004000U
+#define BIT15 0x00008000U
+#define BIT16 0x00010000U
+#define BIT17 0x00020000U
+#define BIT18 0x00040000U
+#define BIT19 0x00080000U
+#define BIT20 0x00100000U
+#define BIT21 0x00200000U
+#define BIT22 0x00400000U
+#define BIT23 0x00800000U
+#define BIT24 0x01000000U
+#define BIT25 0x02000000U
+#define BIT26 0x04000000U
+#define BIT27 0x08000000U
+#define BIT28 0x10000000U
+#define BIT29 0x20000000U
+#define BIT30 0x40000000U
+#define BIT31 0x80000000U
+
+
+#define true 0x01
+#define false 0x00
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c
new file mode 100755
index 0000000..847ac90
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c
@@ -0,0 +1,560 @@
+/**@file
+ HTE handling routines for MRC use.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "mrc.h"
+#include "memory_options.h"
+#include "io.h"
+
+#include "hte.h"
+
+
+#ifdef SIM
+VOID delay_n(UINT32 nanoseconds);
+#define MySimStall(a) delay_n(a/1000)
+#endif
+
+STATIC VOID EnableAllHteErrors(
+ UINT8 Mask)
+/*++
+
+ Routine Description:
+
+ This function enables to HTE to detect all possible errors for
+ the given training parameters (per-bit or full byte lane).
+
+ Returns:
+
+ None
+
+ --*/
+{
+ isbW32m(HTE, 0x000200A2, 0xFFFFFFFF);
+ isbW32m(HTE, 0x000200A3, 0x000000FF);
+ isbW32m(HTE, 0x000200A4, 0x00000000);
+}
+
+STATIC UINT32 CheckHteErrors(
+ VOID)
+/*++
+
+ Routine Description:
+
+ This function goes and reads the HTE register in order to find any error
+
+ Returns:
+
+ The errors detected in the HTE status register
+
+ --*/
+{
+ return isbR32m(HTE, 0x000200A7);
+}
+
+STATIC VOID WaitForHteComplete(
+ VOID)
+/*++
+
+ Routine Description:
+
+ This function waits until HTE finishes
+
+ Returns:
+
+ None
+
+ --*/
+{
+ UINT32 Tmp;
+
+ ENTERFN();
+
+ //
+ // Is the test done?
+ //
+ do
+ {
+#ifdef SIM
+ MySimStall (35000); // 35 ns delay
+#endif
+ } while (0 != (isbR32m(HTE, 0x00020012) & BIT30));
+
+ Tmp = isbR32m(HTE, 0x00020011);
+ Tmp = Tmp | BIT9;
+ Tmp = Tmp & ~(BIT13 | BIT12);
+ isbW32m(HTE, 0x00020011, Tmp);
+
+ LEAVEFN();
+}
+
+STATIC VOID ClearHteErrorRegisters(
+ VOID)
+/*++
+
+ Routine Description:
+
+ Clears registers related with errors in the HTE.
+
+ Returns:
+
+ None
+
+ --*/
+{
+ UINT32 Tmp;
+
+ //
+ // Clear all HTE errors and enable error checking
+ // for burst and chunk.
+ //
+ Tmp = isbR32m(HTE, 0x000200A1);
+ Tmp |= BIT8;
+ isbW32m(HTE, 0x000200A1, Tmp);
+}
+
+UINT32 HteMemInit(
+ MRC_PARAMS *CurrentMrcData,
+ UINT8 MemInitFlag,
+ UINT8 HaltHteEngineOnError)
+
+/*++
+
+ Routine Description:
+
+ Uses HW HTE engine to initialize or test all memory attached to a given DUNIT.
+ If MemInitFlag is 1, this routine writes 0s to all memory locations to initialize
+ ECC.
+ If MemInitFlag is 0, this routine will send an 5AA55AA5 pattern to all memory
+ locations on the RankMask and then read it back. Then it sends an A55AA55A
+ pattern to all memory locations on the RankMask and reads it back.
+
+ Arguments:
+
+ CurrentMrcData: Host struture for all MRC global data.
+ MemInitFlag: 0 for memtest, 1 for meminit.
+ HaltHteEngineOnError: Halt the HTE engine on first error observed, or keep
+ running to see how many errors are found.
+
+ Returns:
+ Errors register showing HTE failures.
+ Also prints out which rank failed the HTE test if failure occurs.
+ For rank detection to work, the address map must be left in its default
+ state. If MRC changes the address map, this function must be modified
+ to change it back to default at the beginning, then restore it at the end.
+
+ --*/
+{
+ UINT32 Offset;
+ UINT8 TestNum;
+ UINT8 i;
+
+ //
+ // Clear out the error registers at the start of each memory
+ // init or memory test run.
+ //
+ ClearHteErrorRegisters();
+
+ isbW32m(HTE, 0x00020062, 0x00000015);
+
+ for (Offset = 0x80; Offset <= 0x8F; Offset++)
+ {
+ isbW32m(HTE, Offset, ((Offset & 1) ? 0xA55A : 0x5AA5));
+ }
+
+ isbW32m(HTE, 0x00020021, 0x00000000);
+#ifdef QUICKSIM
+ // Just do 4 cache lines for simulation memtest to save time.
+ isbW32m(HTE, 0x00020022, 4-1);
+#else
+ isbW32m(HTE, 0x00020022, (CurrentMrcData->mem_size >> 6) - 1);
+#endif
+
+ isbW32m(HTE, 0x00020063, 0xAAAAAAAA);
+ isbW32m(HTE, 0x00020064, 0xCCCCCCCC);
+ isbW32m(HTE, 0x00020065, 0xF0F0F0F0);
+ isbW32m(HTE, 0x00020066, 0x03000000);
+
+ switch (MemInitFlag)
+ {
+ case MrcMemInit:
+ TestNum = 1; // Only 1 write pass through memory is needed to initialize ECC.
+ break;
+ case MrcMemTest:
+ TestNum = 4; // Write/read then write/read with inverted pattern.
+ break;
+ default:
+ DPF(D_INFO, "Unknown parameter for MemInitFlag: %d\n", MemInitFlag);
+ return 0xFFFFFFFF;
+ break;
+ }
+
+ DPF(D_INFO, "HteMemInit");
+ for (i = 0; i < TestNum; i++)
+ {
+ DPF(D_INFO, ".");
+
+ if (i == 0)
+ {
+ isbW32m(HTE, 0x00020061, 0x00000000);
+ isbW32m(HTE, 0x00020020, 0x00110010);
+ }
+ else if (i == 1)
+ {
+ isbW32m(HTE, 0x00020061, 0x00000000);
+ isbW32m(HTE, 0x00020020, 0x00010010);
+ }
+ else if (i == 2)
+ {
+ isbW32m(HTE, 0x00020061, 0x00010100);
+ isbW32m(HTE, 0x00020020, 0x00110010);
+ }
+ else
+ {
+ isbW32m(HTE, 0x00020061, 0x00010100);
+ isbW32m(HTE, 0x00020020, 0x00010010);
+ }
+
+ isbW32m(HTE, 0x00020011, 0x00111000);
+ isbW32m(HTE, 0x00020011, 0x00111100);
+
+ WaitForHteComplete();
+
+ //
+ // If this is a READ pass, check for errors at the end.
+ //
+ if ((i % 2) == 1)
+ {
+ //
+ // Return immediately if error.
+ //
+ if (CheckHteErrors())
+ {
+ break;
+ }
+ }
+ }
+
+ DPF(D_INFO, "done\n", i);
+ return CheckHteErrors();
+}
+
+STATIC UINT16 BasicDataCompareHte(
+ MRC_PARAMS *CurrentMrcData,
+ UINT32 Address,
+ UINT8 FirstRun,
+ UINT8 Mode)
+/*++
+
+ Routine Description:
+
+ Execute basic single cache line memory write/read/verify test using simple constant
+ pattern (different for READ_RAIN and WRITE_TRAIN modes.
+ See BasicWriteReadHTE which is external visible wrapper.
+
+ Arguments:
+
+ CurrentMrcData: Host struture for all MRC global data.
+ Address: memory adress being tested (must hit specific channel/rank)
+ FirstRun: If set then hte registers are configured, otherwise
+ it is assumed configuration is done and just re-run the test.
+ Mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
+
+ Returns:
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)
+
+ --*/
+{
+ UINT32 Pattern;
+ UINT32 Offset;
+
+ if (FirstRun)
+ {
+ isbW32m(HTE, 0x00020020, 0x01B10021);
+ isbW32m(HTE, 0x00020021, 0x06000000);
+ isbW32m(HTE, 0x00020022, Address >> 6);
+ isbW32m(HTE, 0x00020062, 0x00800015);
+ isbW32m(HTE, 0x00020063, 0xAAAAAAAA);
+ isbW32m(HTE, 0x00020064, 0xCCCCCCCC);
+ isbW32m(HTE, 0x00020065, 0xF0F0F0F0);
+ isbW32m(HTE, 0x00020061, 0x00030008);
+
+ if (Mode == WRITE_TRAIN)
+ {
+ Pattern = 0xC33C0000;
+ }
+ else // READ_TRAIN
+ {
+ Pattern = 0xAA5555AA;
+ }
+
+ for (Offset = 0x80; Offset <= 0x8F; Offset++)
+ {
+ isbW32m(HTE, Offset, Pattern);
+ }
+ }
+
+ isbW32m(HTE, 0x000200A1, 0xFFFF1000);
+
+ isbW32m(HTE, 0x00020011, 0x00011000);
+ isbW32m(HTE, 0x00020011, 0x00011100);
+
+ WaitForHteComplete();
+
+ //
+ // Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for any bytelane errors.
+ //
+ return ((CheckHteErrors() >> 8) & 0xFF);
+}
+
+STATIC UINT16 ReadWriteDataCompareHte(
+ MRC_PARAMS *CurrentMrcData,
+ UINT32 Address,
+ UINT8 LoopCount,
+ UINT32 LfsrSeedVictim,
+ UINT32 LfsrSeedAggressor,
+ UINT8 VictimBit,
+ UINT8 FirstRun)
+/*++
+
+ Routine Description:
+
+ Examines single cache line memory with write/read/verify test using
+ multiple data patterns (victim-aggressor algorithm).
+ See WriteStressBitLanesHTE which is external visible wrapper.
+
+ Arguments:
+
+ CurrentMrcData: host struture for all MRC global data.
+ Address: memory adress being tested (must hit specific channel/rank)
+ LoopCount: number of test iterations
+ LfsrSeedXxx: victim aggressor data pattern seed
+ VictimBit: should be 0 as auto rotate feature is in use.
+ FirstRun: If set then hte registers are configured, otherwise
+ it is assumed configuration is done and just re-run the test.
+
+ Returns:
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)
+
+ --*/
+{
+ UINT32 Offset;
+ UINT32 Tmp;
+
+ if (FirstRun)
+ {
+ isbW32m(HTE, 0x00020020, 0x00910024);
+ isbW32m(HTE, 0x00020023, 0x00810024);
+ isbW32m(HTE, 0x00020021, 0x06070000);
+ isbW32m(HTE, 0x00020024, 0x06070000);
+ isbW32m(HTE, 0x00020022, Address >> 6);
+ isbW32m(HTE, 0x00020025, Address >> 6);
+ isbW32m(HTE, 0x00020062, 0x0000002A);
+ isbW32m(HTE, 0x00020063, LfsrSeedVictim);
+ isbW32m(HTE, 0x00020064, LfsrSeedAggressor);
+ isbW32m(HTE, 0x00020065, LfsrSeedVictim);
+
+ //
+ // Write the pattern buffers to select the victim bit. Start with bit0.
+ //
+ for (Offset = 0x80; Offset <= 0x8F; Offset++)
+ {
+ if ((Offset % 8) == VictimBit)
+ {
+ isbW32m(HTE, Offset, 0x55555555);
+ }
+ else
+ {
+ isbW32m(HTE, Offset, 0xCCCCCCCC);
+ }
+ }
+
+ isbW32m(HTE, 0x00020061, 0x00000000);
+ isbW32m(HTE, 0x00020066, 0x03440000);
+ isbW32m(HTE, 0x000200A1, 0xFFFF1000);
+ }
+
+ Tmp = 0x10001000 | (LoopCount << 16);
+ isbW32m(HTE, 0x00020011, Tmp);
+ isbW32m(HTE, 0x00020011, Tmp | BIT8);
+
+ WaitForHteComplete();
+
+ return (CheckHteErrors() >> 8) & 0xFF;
+}
+
+UINT16 BasicWriteReadHTE(
+ MRC_PARAMS *CurrentMrcData,
+ UINT32 Address,
+ UINT8 FirstRun,
+ UINT8 Mode)
+/*++
+
+ Routine Description:
+
+ Execute basic single cache line memory write/read/verify test using simple constant
+ pattern (different for READ_RAIN and WRITE_TRAIN modes.
+
+ Arguments:
+
+ CurrentMrcData: Host struture for all MRC global data.
+ Address: memory adress being tested (must hit specific channel/rank)
+ FirstRun: If set then hte registers are configured, otherwise
+ it is assumed configuration is done and just re-run the test.
+ Mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
+
+ Returns:
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)
+
+ --*/
+{
+ UINT16 ByteLaneErrors;
+
+ ENTERFN();
+
+ //
+ // Enable all error reporting in preparation for HTE test.
+ //
+ EnableAllHteErrors(0xFF);
+ ClearHteErrorRegisters();
+
+ ByteLaneErrors = BasicDataCompareHte(CurrentMrcData, Address, FirstRun,
+ Mode);
+
+ LEAVEFN();
+ return ByteLaneErrors;
+}
+
+UINT16 WriteStressBitLanesHTE(
+ MRC_PARAMS *CurrentMrcData,
+ UINT32 Address,
+ UINT8 FirstRun)
+/*++
+
+ Routine Description:
+
+ Examines single cache line memory with write/read/verify test using
+ multiple data patterns (victim-aggressor algorithm).
+
+ Arguments:
+
+ CurrentMrcData: host struture for all MRC global data.
+ Address: memory adress being tested (must hit specific channel/rank)
+ FirstRun: If set then hte registers are configured, otherwise
+ it is assumed configuration is done and just re-run the test.
+
+ Returns:
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)
+
+ --*/
+{
+ UINT16 ByteLaneErrors;
+ UINT8 VictimBit = 0;
+
+ ENTERFN();
+
+ //
+ // Enable all error reporting in preparation for HTE test.
+ //
+ EnableAllHteErrors(0xFF);
+ ClearHteErrorRegisters();
+
+ //
+ // Loop through each bit in the bytelane. Each pass creates a victim bit
+ // while keeping all other bits the same - as aggressors.
+ // AVN HTE adds an auto-rotate feature which allows us to program the entire victim/aggressor
+ // sequence in 1 step. The victim bit rotates on each pass so no need to have software implement
+ // a victim bit loop like on VLV.
+ //
+ ByteLaneErrors = ReadWriteDataCompareHte(CurrentMrcData, Address,
+ HTE_LOOP_CNT, HTE_LFSR_VICTIM_SEED, HTE_LFSR_AGRESSOR_SEED, VictimBit,
+ FirstRun);
+
+ LEAVEFN();
+ return ByteLaneErrors;
+}
+
+VOID HteMemOp(
+ UINT32 Address,
+ UINT8 FirstRun,
+ UINT8 IsWrite)
+/*++
+
+ Routine Description:
+
+ Execute basic single cache line memory write or read.
+ This is just for receive enable / fine write levelling purpose.
+
+ Arguments:
+
+ CurrentMrcData: Host structure for all MRC global data.
+ Address: memory address used (must hit specific channel/rank)
+ FirstRun: If set then hte registers are configured, otherwise
+ it is assumed configuration is done and just re-run the test.
+ IsWrite: When non-zero memory write operation executed, otherwise read
+
+ Returns:
+ None
+
+ --*/
+{
+ UINT32 Offset;
+ UINT32 Tmp;
+
+ EnableAllHteErrors(0xFF);
+ ClearHteErrorRegisters();
+
+ if (FirstRun)
+ {
+ Tmp = IsWrite ? 0x01110021 : 0x01010021;
+ isbW32m(HTE, 0x00020020, Tmp);
+
+ isbW32m(HTE, 0x00020021, 0x06000000);
+ isbW32m(HTE, 0x00020022, Address >> 6);
+ isbW32m(HTE, 0x00020062, 0x00800015);
+ isbW32m(HTE, 0x00020063, 0xAAAAAAAA);
+ isbW32m(HTE, 0x00020064, 0xCCCCCCCC);
+ isbW32m(HTE, 0x00020065, 0xF0F0F0F0);
+ isbW32m(HTE, 0x00020061, 0x00030008);
+
+ for (Offset = 0x80; Offset <= 0x8F; Offset++)
+ {
+ isbW32m(HTE, Offset, 0xC33C0000);
+ }
+ }
+
+ isbW32m(HTE, 0x000200A1, 0xFFFF1000);
+ isbW32m(HTE, 0x00020011, 0x00011000);
+ isbW32m(HTE, 0x00020011, 0x00011100);
+
+ WaitForHteComplete();
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.h
new file mode 100755
index 0000000..bb8a5c8
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.h
@@ -0,0 +1,97 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Hte.h
+
+ Abstract:
+
+ HTE handling routines for MRC use.
+
+ --*/
+#ifndef __HTE_H
+#define __HTE_H
+
+#define STATIC static
+#define VOID void
+
+#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L)
+typedef uint32_t UINT32;
+typedef uint16_t UINT16;
+typedef uint8_t UINT8;
+#endif
+
+typedef enum
+{
+ MrcNoHaltSystemOnError,
+ MrcHaltSystemOnError,
+ MrcHaltHteEngineOnError,
+ MrcNoHaltHteEngineOnError
+} HALT_TYPE;
+
+typedef enum
+{
+ MrcMemInit, MrcMemTest
+} MEM_INIT_OR_TEST;
+
+#define READ_TRAIN 1
+#define WRITE_TRAIN 2
+
+#define HTE_MEMTEST_NUM 2
+#define HTE_LOOP_CNT 5 // EXP_LOOP_CNT field of HTE_CMD_CTL. This CANNOT be less than 4
+#define HTE_LFSR_VICTIM_SEED 0xF294BA21 // Random seed for victim.
+#define HTE_LFSR_AGRESSOR_SEED 0xEBA7492D // Random seed for aggressor.
+UINT32
+HteMemInit(
+ MRC_PARAMS *CurrentMrcData,
+ UINT8 MemInitFlag,
+ UINT8 HaltHteEngineOnError);
+
+UINT16
+BasicWriteReadHTE(
+ MRC_PARAMS *CurrentMrcData,
+ UINT32 Address,
+ UINT8 FirstRun,
+ UINT8 Mode);
+
+UINT16
+WriteStressBitLanesHTE(
+ MRC_PARAMS *CurrentMrcData,
+ UINT32 Address,
+ UINT8 FirstRun);
+
+VOID
+HteMemOp(
+ UINT32 Address,
+ UINT8 FirstRun,
+ UINT8 IsWrite);
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/io.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/io.h
new file mode 100755
index 0000000..febab4e
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/io.h
@@ -0,0 +1,163 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Io.h
+
+ Abstract:
+
+ Declaration of IO handling routines.
+
+ --*/
+#ifndef __IO_H
+#define __IO_H
+
+#include "core_types.h"
+
+#include "general_definitions.h"
+#include "gen5_iosf_sb_definitions.h"
+
+// Instruction not present on Quark
+#define SFENCE()
+
+#define DEAD_LOOP() for(;;);
+
+////
+// Define each of the IOSF_SB ports used by MRC
+//
+
+//
+// Has to be 0 because of emulation static data
+// initialisation:
+// Space_t EmuSpace[ SPACE_COUNT] = {0};
+//
+#define FREE 0x000
+
+// Pseudo side-band ports for access abstraction
+// See Wr32/Rd32 functions
+#define MEM 0x101
+#define MMIO 0x102
+#define DCMD 0x0A0
+
+// Real side-band ports
+// See Wr32/Rd32 functions
+#define MCU 0x001
+#define HOST_BRIDGE 0x003
+#define MEMORY_MANAGER 0x005
+#define HTE 0x011
+#define DDRPHY 0x012
+#define FUSE 0x033
+
+// End of IOSF_SB ports
+////
+
+// Pciexbar address
+#define EC_BASE 0xE0000000
+
+#define PCIADDR(bus,dev,fn,reg) ( \
+ (EC_BASE) + \
+ ((bus) << 20) + \
+ ((dev) << 15) + \
+ ((fn) << 12) + \
+ (reg))
+
+// Various offsets used in the building sideband commands.
+#define SB_OPCODE_OFFSET 24
+#define SB_PORT_OFFSET 16
+#define SB_REG_OFFEST 8
+
+// Sideband opcodes
+#define SB_REG_READ_OPCODE 0x10
+#define SB_REG_WRITE_OPCODE 0x11
+
+#define SB_FUSE_REG_READ_OPCODE 0x06
+#define SB_FUSE_REG_WRITE_OPCODE 0x07
+
+#define SB_DDRIO_REG_READ_OPCODE 0x06
+#define SB_DDRIO_REG_WRITE_OPCODE 0x07
+
+#define SB_DRAM_CMND_OPCODE 0x68
+#define SB_WAKE_CMND_OPCODE 0xCA
+#define SB_SUSPEND_CMND_OPCODE 0xCC
+
+// Register addresses for sideband command and data.
+#define SB_PACKET_REG 0x00D0
+#define SB_DATA_REG 0x00D4
+#define SB_HADR_REG 0x00D8
+
+// We always flag all 4 bytes in the register reads/writes as required.
+#define SB_ALL_BYTES_ENABLED 0xF0
+
+#define SB_COMMAND(Opcode, Port, Reg) \
+ ((Opcode << SB_OPCODE_OFFSET) | \
+ (Port << SB_PORT_OFFSET) | \
+ (Reg << SB_REG_OFFEST) | \
+ SB_ALL_BYTES_ENABLED)
+
+// iosf
+#define isbM32m WrMask32
+#define isbW32m Wr32
+#define isbR32m Rd32
+
+// pci
+
+void pciwrite32(
+ uint32_t bus,
+ uint32_t dev,
+ uint32_t fn,
+ uint32_t reg,
+ uint32_t data);
+
+uint32_t pciread32(
+ uint32_t bus,
+ uint32_t dev,
+ uint32_t fn,
+ uint32_t reg);
+
+// general
+
+uint32_t Rd32(
+ uint32_t unit,
+ uint32_t addr);
+
+void Wr32(
+ uint32_t unit,
+ uint32_t addr,
+ uint32_t data);
+
+void WrMask32(
+ uint32_t unit,
+ uint32_t addr,
+ uint32_t data,
+ uint32_t mask);
+
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/lprint.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/lprint.c
new file mode 100755
index 0000000..d48caba
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/lprint.c
@@ -0,0 +1,411 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Lprint.c
+
+ Abstract:
+
+ Serial conole output and string formating.
+
+ --*/
+#include "memory_options.h"
+#include "general_definitions.h"
+
+// Resource programmed to PCI bridge, 1MB bound alignment is needed.
+// The default value is overwritten by MRC parameter, assuming code
+// relocated to eSRAM.
+uint32_t UartMmioBase = 0;
+
+// Serial port registers based on SerialPortLib.c
+#define R_UART_BAUD_THR 0
+#define R_UART_LSR 20
+
+#define B_UART_LSR_RXRDY BIT0
+#define B_UART_LSR_TXRDY BIT5
+#define B_UART_LSR_TEMT BIT6
+
+// Print mask see DPF and D_Xxxx
+#define DPF_MASK DpfPrintMask
+
+// Select class of messages enabled for printing
+uint32_t DpfPrintMask =
+ D_ERROR |
+ D_INFO |
+ // D_REGRD |
+ // D_REGWR |
+ // D_FCALL |
+ // D_TRN |
+ 0;
+
+#ifdef NDEBUG
+// Don't generate debug code
+void dpf( uint32_t mask, char_t* bla, ...)
+{
+ return;
+}
+
+uint8_t mgetc(void)
+{
+ return 0;
+}
+
+uint8_t mgetch(void)
+{
+ return 0;
+}
+
+#else
+
+#ifdef SIM
+// Use Vpi console in simulation environment
+#include <vpi_user.h>
+
+void dpf( uint32_t mask, char_t* bla, ...)
+{
+ va_list va;
+
+ if( 0 == (mask & DPF_MASK)) return;
+
+ va_start( va, bla);
+ vpi_vprintf( bla, va);
+ va_end(va);
+}
+
+#else
+
+#ifdef EMU
+// Use standard console in windows environment
+#include <stdio.h>
+#endif
+
+// Read character from serial port
+uint8_t mgetc(void)
+{
+#ifdef EMU
+
+ // Emulation in Windows environment uses console
+ getchar();
+
+#else
+ uint8_t c;
+
+ while ((*(volatile uint8_t*) (UartMmioBase + R_UART_LSR) & B_UART_LSR_RXRDY) == 0);
+ c = *(volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR);
+
+ return c;
+#endif
+}
+
+
+uint8_t mgetch(void)
+{
+#ifdef EMU
+ return 0;
+#else
+ uint8_t c = 0;
+
+ if((*(volatile uint8_t*) (UartMmioBase + R_UART_LSR) & B_UART_LSR_RXRDY) != 0)
+ {
+ c = *(volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR);
+ }
+
+ return c;
+#endif
+}
+
+// Print single character
+static void printc(
+ uint8_t c)
+{
+#ifdef EMU
+
+ // Emulation in Windows environment uses console output
+ putchar(c);
+
+#else
+
+ //
+ // Use MMIO access to serial port on PCI
+ // while( 0 == (0x20 & inp(0x3f8 + 5)));
+ // outp(0x3f8 + 0, c);
+ //
+ while (0
+ == (B_UART_LSR_TEMT & *((volatile uint8_t*) (UartMmioBase + R_UART_LSR))))
+ ;
+ *((volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR)) = c;
+#endif
+}
+
+// Print 0 terminated string on serial console
+static void printstr(
+ char_t *str)
+{
+ while (*str)
+ {
+ printc(*str++);
+ }
+}
+// Print 64bit number as hex string on serial console
+// the width parameters allows skipping leading zeros
+static void printhexx(
+ uint64_t val,
+ uint32_t width)
+{
+ uint32_t i;
+ uint8_t c;
+ uint8_t empty = 1;
+
+ // 64bit number has 16 characters in hex representation
+ for (i = 16; i > 0; i--)
+ {
+ c = (uint8_t) ((val >> 60) & 0x0F);
+ if (c > 9)
+ c += 'A' - 10;
+ else
+ c += '0';
+
+ val = val << 4;
+
+ if (c != '0')
+ {
+ // end of leading zeros
+ empty = 0;
+ }
+
+ // don't print leading zero
+ if (!empty || i <= width)
+ {
+ printc(c);
+ }
+ }
+}
+// Print 32bit number as hex string on serial console
+// the width parameters allows skipping leading zeros
+static void printhex(
+ uint32_t val,
+ uint32_t width)
+{
+ uint32_t i;
+ uint8_t c;
+ uint8_t empty = 1;
+
+ // 32bit number has 8 characters in hex representation
+ for (i = 8; i > 0; i--)
+ {
+ c = (uint8_t) ((val >> 28) & 0x0F);
+ if (c > 9)
+ c += 'A' - 10;
+ else
+ c += '0';
+
+ val = val << 4;
+
+ if (c != '0')
+ {
+ // end of leading zeros
+ empty = 0;
+ }
+
+ // don't print leading zero
+ if (!empty || i <= width)
+ {
+ printc(c);
+ }
+ }
+}
+// Print 32bit number as decimal string on serial console
+// the width parameters allows skipping leading zeros
+static void printdec(
+ uint32_t val,
+ uint32_t width)
+{
+ uint32_t i;
+ uint8_t c = 0;
+ uint8_t empty = 1;
+
+ // Ten digits is enough for 32bit number in decimal
+ uint8_t buf[10];
+
+ for (i = 0; i < sizeof(buf); i++)
+ {
+ c = (uint8_t) (val % 10);
+ buf[i] = c + '0';
+ val = val / 10;
+ }
+
+ while (i > 0)
+ {
+ c = buf[--i];
+
+ if (c != '0')
+ {
+ // end of leading zeros
+ empty = 0;
+ }
+
+ // don't print leading zero
+ if (!empty || i < width)
+ {
+ printc(c);
+ }
+ }
+}
+
+// Consume numeric substring leading the given string
+// Return pointer to the first non-numeric character
+// Buffer reference by width is updated with number
+// converted from the numeric substring.
+static char_t *getwidth(
+ char_t *bla,
+ uint32_t *width)
+{
+ uint32_t val = 0;
+
+ while (*bla >= '0' && *bla <= '9')
+ {
+ val = val * 10 + *bla - '0';
+ bla += 1;
+ }
+
+ if (val > 0)
+ {
+ *width = val;
+ }
+ return bla;
+}
+
+// Consume print format designator from the head of given string
+// Return pointer to first character after format designator
+// input fmt
+// ----- ---
+// s -> s
+// d -> d
+// X -> X
+// llX -> L
+static char_t *getformat(
+ char_t *bla,
+ uint8_t *fmt)
+{
+ if (bla[0] == 's')
+ {
+ bla += 1;
+ *fmt = 's';
+ }
+ else if (bla[0] == 'd')
+ {
+ bla += 1;
+ *fmt = 'd';
+ }
+ else if (bla[0] == 'X' || bla[0] == 'x')
+ {
+ bla += 1;
+ *fmt = 'X';
+ }
+ else if (bla[0] == 'l' && bla[1] == 'l' && bla[2] == 'X')
+ {
+ bla += 3;
+ *fmt = 'L';
+ }
+
+ return bla;
+}
+
+// Simplified implementation of standard printf function
+// The output is directed to serial console. Only selected
+// class of messages is printed (mask has to match DpfPrintMask)
+// Supported print formats: %[n]s,%[n]d,%[n]X,,%[n]llX
+// The width is ignored for %s format.
+void dpf(
+ uint32_t mask,
+ char_t* bla,
+ ...)
+{
+ uint32_t* arg = (uint32_t*) (&bla + 1);
+
+ // Check UART MMIO base configured
+ if (0 == UartMmioBase)
+ return;
+
+ // Check event not masked
+ if (0 == (mask & DPF_MASK))
+ return;
+
+ for (;;)
+ {
+ uint8_t x = *bla++;
+ if (x == 0)
+ break;
+
+ if (x == '\n')
+ {
+ printc('\r');
+ printc('\n');
+ }
+ else if (x == '%')
+ {
+ uint8_t fmt = 0;
+ uint32_t width = 1;
+
+ bla = getwidth(bla, &width);
+ bla = getformat(bla, &fmt);
+
+ // Print value
+ if (fmt == 'd')
+ {
+ printdec(*arg, width);
+ arg += 1;
+ }
+ else if (fmt == 'X')
+ {
+ printhex(*arg, width);
+ arg += 1;
+ }
+ else if (fmt == 'L')
+ {
+ printhexx(*(uint64_t*) arg, width);
+ arg += 2;
+ }
+ else if (fmt == 's')
+ {
+ printstr(*(char**) arg);
+ arg += 1;
+ }
+ }
+ else
+ {
+ printc(x);
+ }
+ }
+}
+
+#endif //SIM
+#endif //NDEBUG
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.c
new file mode 100755
index 0000000..d16614e
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.c
@@ -0,0 +1,2663 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file contains all of the Cat Mountain Memory Reference Code (MRC).
+ *
+ * These functions are generic and should work for any Cat Mountain config.
+ *
+ * MRC requires two data structures to be passed in which are initialised by "PreMemInit()".
+ *
+ * The basic flow is as follows:
+ * 01) Check for supported DDR speed configuration
+ * 02) Set up MEMORY_MANAGER buffer as pass-through (POR)
+ * 03) Set Channel Interleaving Mode and Channel Stride to the most aggressive setting possible
+ * 04) Set up the MCU logic
+ * 05) Set up the DDR_PHY logic
+ * 06) Initialise the DRAMs (JEDEC)
+ * 07) Perform the Receive Enable Calibration algorithm
+ * 08) Perform the Write Leveling algorithm
+ * 09) Perform the Read Training algorithm (includes internal Vref)
+ * 10) Perform the Write Training algorithm
+ * 11) Set Channel Interleaving Mode and Channel Stride to the desired settings
+ *
+ * Dunit configuration based on Valleyview MRC.
+ *
+ ***************************************************************************/
+
+#include "mrc.h"
+#include "memory_options.h"
+
+#include "meminit.h"
+#include "meminit_utils.h"
+#include "hte.h"
+#include "io.h"
+
+// Override ODT to off state if requested
+#define DRMC_DEFAULT (mrc_params->rd_odt_value==0?BIT12:0)
+
+
+// tRFC values (in picoseconds) per density
+const uint32_t tRFC[5] =
+{
+ 90000, // 512Mb
+ 110000, // 1Gb
+ 160000, // 2Gb
+ 300000, // 4Gb
+ 350000, // 8Gb
+ };
+
+// tCK clock period in picoseconds per speed index 800, 1066, 1333
+const uint32_t tCK[3] =
+{
+ 2500,
+ 1875,
+ 1500
+};
+
+#ifdef SIM
+// Select static timings specific to simulation environment
+#define PLATFORM_ID 0
+#else
+// Select static timings specific to ClantonPeek platform
+#define PLATFORM_ID 1
+#endif
+
+
+// Global variables
+const uint16_t ddr_wclk[] =
+ {193, 158};
+
+const uint16_t ddr_wctl[] =
+ { 1, 217};
+
+const uint16_t ddr_wcmd[] =
+ { 1, 220};
+
+
+#ifdef BACKUP_RCVN
+const uint16_t ddr_rcvn[] =
+ {129, 498};
+#endif // BACKUP_RCVN
+
+#ifdef BACKUP_WDQS
+const uint16_t ddr_wdqs[] =
+ { 65, 289};
+#endif // BACKUP_WDQS
+
+#ifdef BACKUP_RDQS
+const uint8_t ddr_rdqs[] =
+ { 32, 24};
+#endif // BACKUP_RDQS
+
+#ifdef BACKUP_WDQ
+const uint16_t ddr_wdq[] =
+ { 32, 257};
+#endif // BACKUP_WDQ
+
+
+
+// Select MEMORY_MANAGER as the source for PRI interface
+static void select_memory_manager(
+ MRCParams_t *mrc_params)
+{
+ RegDCO Dco;
+
+ ENTERFN();
+
+ Dco.raw = isbR32m(MCU, DCO);
+ Dco.field.PMICTL = 0; //0 - PRI owned by MEMORY_MANAGER
+ isbW32m(MCU, DCO, Dco.raw);
+
+ LEAVEFN();
+}
+
+// Select HTE as the source for PRI interface
+void select_hte(
+ MRCParams_t *mrc_params)
+{
+ RegDCO Dco;
+
+ ENTERFN();
+
+ Dco.raw = isbR32m(MCU, DCO);
+ Dco.field.PMICTL = 1; //1 - PRI owned by HTE
+ isbW32m(MCU, DCO, Dco.raw);
+
+ LEAVEFN();
+}
+
+// Send DRAM command, data should be formated
+// using DCMD_Xxxx macro or emrsXCommand structure.
+static void dram_init_command(
+ uint32_t data)
+{
+ Wr32(DCMD, 0, data);
+}
+
+// Send DRAM wake command using special MCU side-band WAKE opcode
+static void dram_wake_command(
+ void)
+{
+ ENTERFN();
+
+ Wr32(MMIO, PCIADDR(0,0,0,SB_PACKET_REG),
+ (uint32_t) SB_COMMAND(SB_WAKE_CMND_OPCODE, MCU, 0));
+
+ LEAVEFN();
+}
+
+// Stop self refresh driven by MCU
+static void clear_self_refresh(
+ MRCParams_t *mrc_params)
+{
+ ENTERFN();
+
+ // clear the PMSTS Channel Self Refresh bits
+ isbM32m(MCU, PMSTS, BIT0, BIT0);
+
+ LEAVEFN();
+}
+
+// Configure MCU before jedec init sequence
+static void prog_decode_before_jedec(
+ MRCParams_t *mrc_params)
+{
+ RegDRP Drp;
+ RegDRCF Drfc;
+ RegDCAL Dcal;
+ RegDSCH Dsch;
+ RegDPMC0 Dpmc0;
+
+ ENTERFN();
+
+ // Disable power saving features
+ Dpmc0.raw = isbR32m(MCU, DPMC0);
+ Dpmc0.field.CLKGTDIS = 1;
+ Dpmc0.field.DISPWRDN = 1;
+ Dpmc0.field.DYNSREN = 0;
+ Dpmc0.field.PCLSTO = 0;
+ isbW32m(MCU, DPMC0, Dpmc0.raw);
+
+ // Disable out of order transactions
+ Dsch.raw = isbR32m(MCU, DSCH);
+ Dsch.field.OOODIS = 1;
+ Dsch.field.NEWBYPDIS = 1;
+ isbW32m(MCU, DSCH, Dsch.raw);
+
+ // Disable issuing the REF command
+ Drfc.raw = isbR32m(MCU, DRFC);
+ Drfc.field.tREFI = 0;
+ isbW32m(MCU, DRFC, Drfc.raw);
+
+ // Disable ZQ calibration short
+ Dcal.raw = isbR32m(MCU, DCAL);
+ Dcal.field.ZQCINT = 0;
+ Dcal.field.SRXZQCL = 0;
+ isbW32m(MCU, DCAL, Dcal.raw);
+
+ // Training performed in address mode 0, rank population has limited impact, however
+ // simulator complains if enabled non-existing rank.
+ Drp.raw = 0;
+ if (mrc_params->rank_enables & 1)
+ Drp.field.rank0Enabled = 1;
+ if (mrc_params->rank_enables & 2)
+ Drp.field.rank1Enabled = 1;
+ isbW32m(MCU, DRP, Drp.raw);
+
+ LEAVEFN();
+}
+
+// After Cold Reset, BIOS should set COLDWAKE bit to 1 before
+// sending the WAKE message to the Dunit.
+// For Standby Exit, or any other mode in which the DRAM is in
+// SR, this bit must be set to 0.
+static void perform_ddr_reset(
+ MRCParams_t *mrc_params)
+{
+ ENTERFN();
+
+ // Set COLDWAKE bit before sending the WAKE message
+ isbM32m(MCU, DRMC, BIT16, BIT16);
+
+ // Send wake command to DUNIT (MUST be done before JEDEC)
+ dram_wake_command();
+
+ // Set default value
+ isbW32m(MCU, DRMC, DRMC_DEFAULT);
+
+ LEAVEFN();
+}
+
+// Dunit Initialisation Complete.
+// Indicates that initialisation of the Dunit has completed.
+// Memory accesses are permitted and maintenance operation
+// begins. Until this bit is set to a 1, the memory controller will
+// not accept DRAM requests from the MEMORY_MANAGER or HTE.
+static void set_ddr_init_complete(
+ MRCParams_t *mrc_params)
+{
+ RegDCO Dco;
+
+ ENTERFN();
+
+ Dco.raw = isbR32m(MCU, DCO);
+ Dco.field.PMICTL = 0; //0 - PRI owned by MEMORY_MANAGER
+ Dco.field.IC = 1; //1 - initialisation complete
+ isbW32m(MCU, DCO, Dco.raw);
+
+ LEAVEFN();
+}
+
+static void prog_page_ctrl(
+ MRCParams_t *mrc_params)
+{
+ RegDPMC0 Dpmc0;
+
+ ENTERFN();
+
+ Dpmc0.raw = isbR32m(MCU, DPMC0);
+
+ Dpmc0.field.PCLSTO = 0x4;
+ Dpmc0.field.PREAPWDEN = 1;
+
+ isbW32m(MCU, DPMC0, Dpmc0.raw);
+}
+
+// Configure MCU Power Management Control Register
+// and Scheduler Control Register.
+static void prog_ddr_control(
+ MRCParams_t *mrc_params)
+{
+ RegDSCH Dsch;
+ RegDPMC0 Dpmc0;
+
+ ENTERFN();
+
+ Dpmc0.raw = isbR32m(MCU, DPMC0);
+ Dsch.raw = isbR32m(MCU, DSCH);
+
+ Dpmc0.field.DISPWRDN = mrc_params->power_down_disable;
+ Dpmc0.field.CLKGTDIS = 0;
+ Dpmc0.field.PCLSTO = 4;
+ Dpmc0.field.PREAPWDEN = 1;
+
+ Dsch.field.OOODIS = 0;
+ Dsch.field.OOOST3DIS = 0;
+ Dsch.field.NEWBYPDIS = 0;
+
+ isbW32m(MCU, DSCH, Dsch.raw);
+ isbW32m(MCU, DPMC0, Dpmc0.raw);
+
+ // CMDTRIST = 2h - CMD/ADDR are tristated when no valid command
+ isbM32m(MCU, DPMC1, 2 << 4, BIT5|BIT4);
+
+ LEAVEFN();
+}
+
+// After training complete configure MCU Rank Population Register
+// specifying: ranks enabled, device width, density, address mode.
+static void prog_dra_drb(
+ MRCParams_t *mrc_params)
+{
+ RegDRP Drp;
+ RegDCO Dco;
+
+ ENTERFN();
+
+ Dco.raw = isbR32m(MCU, DCO);
+ Dco.field.IC = 0;
+ isbW32m(MCU, DCO, Dco.raw);
+
+ Drp.raw = 0;
+ if (mrc_params->rank_enables & 1)
+ Drp.field.rank0Enabled = 1;
+ if (mrc_params->rank_enables & 2)
+ Drp.field.rank1Enabled = 1;
+ if (mrc_params->dram_width == x16)
+ {
+ Drp.field.dimm0DevWidth = 1;
+ Drp.field.dimm1DevWidth = 1;
+ }
+ // Density encoding in DRAMParams_t 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
+ // has to be mapped RANKDENSx encoding (0=1Gb)
+ Drp.field.dimm0DevDensity = mrc_params->params.DENSITY - 1;
+ Drp.field.dimm1DevDensity = mrc_params->params.DENSITY - 1;
+
+ // Address mode can be overwritten if ECC enabled
+ Drp.field.addressMap = mrc_params->address_mode;
+
+ isbW32m(MCU, DRP, Drp.raw);
+
+ Dco.field.PMICTL = 0; //0 - PRI owned by MEMORY_MANAGER
+ Dco.field.IC = 1; //1 - initialisation complete
+ isbW32m(MCU, DCO, Dco.raw);
+
+ LEAVEFN();
+}
+
+// Configure refresh rate and short ZQ calibration interval.
+// Activate dynamic self refresh.
+static void change_refresh_period(
+ MRCParams_t *mrc_params)
+{
+ RegDRCF Drfc;
+ RegDCAL Dcal;
+ RegDPMC0 Dpmc0;
+
+ ENTERFN();
+
+ Drfc.raw = isbR32m(MCU, DRFC);
+ Drfc.field.tREFI = mrc_params->refresh_rate;
+ Drfc.field.REFDBTCLR = 1;
+ isbW32m(MCU, DRFC, Drfc.raw);
+
+ Dcal.raw = isbR32m(MCU, DCAL);
+ Dcal.field.ZQCINT = 3; // 63ms
+ isbW32m(MCU, DCAL, Dcal.raw);
+
+ Dpmc0.raw = isbR32m(MCU, DPMC0);
+ Dpmc0.field.ENPHYCLKGATE = 1;
+ Dpmc0.field.DYNSREN = 1;
+ isbW32m(MCU, DPMC0, Dpmc0.raw);
+
+ LEAVEFN();
+}
+
+// Send DRAM wake command
+static void perform_wake(
+ MRCParams_t *mrc_params)
+{
+ ENTERFN();
+
+ dram_wake_command();
+
+ LEAVEFN();
+}
+
+// prog_ddr_timing_control (aka mcu_init):
+// POST_CODE[major] == 0x02
+//
+// It will initialise timing registers in the MCU (DTR0..DTR4).
+static void prog_ddr_timing_control(
+ MRCParams_t *mrc_params)
+{
+ uint8_t TCL, WL;
+ uint8_t TRP, TRCD, TRAS, TRFC, TWR, TWTR, TRRD, TRTP, TFAW;
+ uint32_t TCK;
+
+ RegDTR0 Dtr0;
+ RegDTR1 Dtr1;
+ RegDTR2 Dtr2;
+ RegDTR3 Dtr3;
+ RegDTR4 Dtr4;
+
+ ENTERFN();
+
+ // mcu_init starts
+ post_code(0x02, 0x00);
+
+ Dtr0.raw = isbR32m(MCU, DTR0);
+ Dtr1.raw = isbR32m(MCU, DTR1);
+ Dtr2.raw = isbR32m(MCU, DTR2);
+ Dtr3.raw = isbR32m(MCU, DTR3);
+ Dtr4.raw = isbR32m(MCU, DTR4);
+
+ TCK = tCK[mrc_params->ddr_speed]; // Clock in picoseconds
+ TCL = mrc_params->params.tCL; // CAS latency in clocks
+ TRP = TCL; // Per CAT MRC
+ TRCD = TCL; // Per CAT MRC
+ TRAS = MCEIL(mrc_params->params.tRAS, TCK);
+ TRFC = MCEIL(tRFC[mrc_params->params.DENSITY], TCK);
+ TWR = MCEIL(15000, TCK); // Per JEDEC: tWR=15000ps DDR2/3 from 800-1600
+
+ TWTR = MCEIL(mrc_params->params.tWTR, TCK);
+ TRRD = MCEIL(mrc_params->params.tRRD, TCK);
+ TRTP = 4; // Valid for 800 and 1066, use 5 for 1333
+ TFAW = MCEIL(mrc_params->params.tFAW, TCK);
+
+ WL = 5 + mrc_params->ddr_speed;
+
+ Dtr0.field.dramFrequency = mrc_params->ddr_speed;
+
+ Dtr0.field.tCL = TCL - 5; //Convert from TCL (DRAM clocks) to VLV indx
+ Dtr0.field.tRP = TRP - 5; //5 bit DRAM Clock
+ Dtr0.field.tRCD = TRCD - 5; //5 bit DRAM Clock
+
+ Dtr1.field.tWCL = WL - 3; //Convert from WL (DRAM clocks) to VLV indx
+ Dtr1.field.tWTP = WL + 4 + TWR - 14; //Change to tWTP
+ Dtr1.field.tRTP = MMAX(TRTP, 4) - 3; //4 bit DRAM Clock
+ Dtr1.field.tRRD = TRRD - 4; //4 bit DRAM Clock
+ Dtr1.field.tCMD = 1; //2N
+ Dtr1.field.tRAS = TRAS - 14; //6 bit DRAM Clock
+
+ Dtr1.field.tFAW = ((TFAW + 1) >> 1) - 5; //4 bit DRAM Clock
+ Dtr1.field.tCCD = 0; //Set 4 Clock CAS to CAS delay (multi-burst)
+ Dtr2.field.tRRDR = 1;
+ Dtr2.field.tWWDR = 2;
+ Dtr2.field.tRWDR = 2;
+ Dtr3.field.tWRDR = 2;
+ Dtr3.field.tWRDD = 2;
+
+ if (mrc_params->ddr_speed == DDRFREQ_800)
+ {
+ // Extended RW delay (+1)
+ Dtr3.field.tRWSR = TCL - 5 + 1;
+ }
+ else if(mrc_params->ddr_speed == DDRFREQ_1066)
+ {
+ // Extended RW delay (+1)
+ Dtr3.field.tRWSR = TCL - 5 + 1;
+ }
+
+ Dtr3.field.tWRSR = 4 + WL + TWTR - 11;
+
+ if (mrc_params->ddr_speed == DDRFREQ_800)
+ {
+ Dtr3.field.tXP = MMAX(0, 1 - Dtr1.field.tCMD);
+ }
+ else
+ {
+ Dtr3.field.tXP = MMAX(0, 2 - Dtr1.field.tCMD);
+ }
+
+ Dtr4.field.WRODTSTRT = Dtr1.field.tCMD;
+ Dtr4.field.WRODTSTOP = Dtr1.field.tCMD;
+ Dtr4.field.RDODTSTRT = Dtr1.field.tCMD + Dtr0.field.tCL - Dtr1.field.tWCL + 2; //Convert from WL (DRAM clocks) to VLV indx
+ Dtr4.field.RDODTSTOP = Dtr1.field.tCMD + Dtr0.field.tCL - Dtr1.field.tWCL + 2;
+ Dtr4.field.TRGSTRDIS = 0;
+ Dtr4.field.ODTDIS = 0;
+
+ isbW32m(MCU, DTR0, Dtr0.raw);
+ isbW32m(MCU, DTR1, Dtr1.raw);
+ isbW32m(MCU, DTR2, Dtr2.raw);
+ isbW32m(MCU, DTR3, Dtr3.raw);
+ isbW32m(MCU, DTR4, Dtr4.raw);
+
+ LEAVEFN();
+}
+
+// ddrphy_init:
+// POST_CODE[major] == 0x03
+//
+// This function performs some initialisation on the DDRIO unit.
+// This function is dependent on BOARD_ID, DDR_SPEED, and CHANNEL_ENABLES.
+static void ddrphy_init(MRCParams_t *mrc_params)
+{
+ uint32_t tempD; // temporary DWORD
+ uint8_t channel_i; // channel counter
+ uint8_t rank_i; // rank counter
+ uint8_t bl_grp_i; // byte lane group counter (2 BLs per module)
+
+ uint8_t bl_divisor = /*(mrc_params->channel_width==x16)?2:*/1; // byte lane divisor
+ uint8_t speed = mrc_params->ddr_speed & (BIT1|BIT0); // For DDR3 --> 0 == 800, 1 == 1066, 2 == 1333
+ uint8_t tCAS;
+ uint8_t tCWL;
+
+ ENTERFN();
+
+ tCAS = mrc_params->params.tCL;
+ tCWL = 5 + mrc_params->ddr_speed;
+
+ // ddrphy_init starts
+ post_code(0x03, 0x00);
+
+ // HSD#231531
+ // Make sure IOBUFACT is deasserted before initialising the DDR PHY.
+ // HSD#234845
+ // Make sure WRPTRENABLE is deasserted before initialising the DDR PHY.
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {
+ if (mrc_params->channel_enables & (1<<channel_i)) {
+ // Deassert DDRPHY Initialisation Complete
+ isbM32m(DDRPHY, (CMDPMCONFIG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ~BIT20, BIT20); // SPID_INIT_COMPLETE=0
+ // Deassert IOBUFACT
+ isbM32m(DDRPHY, (CMDCFGREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ~BIT2, BIT2); // IOBUFACTRST_N=0
+ // Disable WRPTR
+ isbM32m(DDRPHY, (CMDPTRREG + (channel_i * DDRIOCCC_CH_OFFSET)), ~BIT0, BIT0); // WRPTRENABLE=0
+ } // if channel enabled
+ } // channel_i loop
+
+ // Put PHY in reset
+ isbM32m(DDRPHY, MASTERRSTN, 0, BIT0); // PHYRSTN=0
+
+ // Initialise DQ01,DQ23,CMD,CLK-CTL,COMP modules
+ // STEP0:
+ post_code(0x03, 0x10);
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {
+ if (mrc_params->channel_enables & (1<<channel_i)) {
+
+ // DQ01-DQ23
+ for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {
+ isbM32m(DDRPHY, (DQOBSCKEBBCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((bl_grp_i) ? (0x00) : (BIT22)), (BIT22)); // Analog MUX select - IO2xCLKSEL
+
+ // ODT Strength
+ switch (mrc_params->rd_odt_value) {
+ case 1: tempD = 0x3; break; // 60 ohm
+ case 2: tempD = 0x3; break; // 120 ohm
+ case 3: tempD = 0x3; break; // 180 ohm
+ default: tempD = 0x3; break; // 120 ohm
+ }
+ isbM32m(DDRPHY, (B0RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (tempD<<5), (BIT6|BIT5)); // ODT strength
+ isbM32m(DDRPHY, (B1RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (tempD<<5), (BIT6|BIT5)); // ODT strength
+ // Dynamic ODT/DIFFAMP
+ tempD = (((tCAS)<<24)|((tCAS)<<16)|((tCAS)<<8)|((tCAS)<<0));
+ switch (speed) {
+ case 0: tempD -= 0x01010101; break; // 800
+ case 1: tempD -= 0x02020202; break; // 1066
+ case 2: tempD -= 0x03030303; break; // 1333
+ case 3: tempD -= 0x04040404; break; // 1600
+ }
+ isbM32m(DDRPHY, (B01LATCTL1 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // Launch Time: ODT, DIFFAMP, ODT, DIFFAMP
+ switch (speed) {
+ // HSD#234715
+ case 0: tempD = ((0x06<<16)|(0x07<<8)); break; // 800
+ case 1: tempD = ((0x07<<16)|(0x08<<8)); break; // 1066
+ case 2: tempD = ((0x09<<16)|(0x0A<<8)); break; // 1333
+ case 3: tempD = ((0x0A<<16)|(0x0B<<8)); break; // 1600
+ }
+ isbM32m(DDRPHY, (B0ONDURCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT13|BIT12|BIT11|BIT10|BIT9|BIT8))); // On Duration: ODT, DIFFAMP
+ isbM32m(DDRPHY, (B1ONDURCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT13|BIT12|BIT11|BIT10|BIT9|BIT8))); // On Duration: ODT, DIFFAMP
+
+ switch (mrc_params->rd_odt_value) {
+ case 0: tempD = ((0x3F<<16)|(0x3f<<10)); break; // override DIFFAMP=on, ODT=off
+ default: tempD = ((0x3F<<16)|(0x2A<<10)); break; // override DIFFAMP=on, ODT=on
+ }
+ isbM32m(DDRPHY, (B0OVRCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10))); // Override: DIFFAMP, ODT
+ isbM32m(DDRPHY, (B1OVRCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10))); // Override: DIFFAMP, ODT
+
+ // DLL Setup
+ // 1xCLK Domain Timings: tEDP,RCVEN,WDQS (PO)
+ isbM32m(DDRPHY, (B0LATCTL0 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (((tCAS+7)<<16)|((tCAS-4)<<8)|((tCWL-2)<<0)), ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // 1xCLK: tEDP, RCVEN, WDQS
+ isbM32m(DDRPHY, (B1LATCTL0 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (((tCAS+7)<<16)|((tCAS-4)<<8)|((tCWL-2)<<0)), ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // 1xCLK: tEDP, RCVEN, WDQS
+
+ // RCVEN Bypass (PO)
+ isbM32m(DDRPHY, (B0RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((0x0<<7)|(0x0<<0)), (BIT7|BIT0)); // AFE Bypass, RCVEN DIFFAMP
+ isbM32m(DDRPHY, (B1RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((0x0<<7)|(0x0<<0)), (BIT7|BIT0)); // AFE Bypass, RCVEN DIFFAMP
+ // TX
+ isbM32m(DDRPHY, (DQCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT16), (BIT16)); // 0 means driving DQ during DQS-preamble
+ isbM32m(DDRPHY, (B01PTRCTL1 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT8), (BIT8)); // WR_LVL mode disable
+ // RX (PO)
+ isbM32m(DDRPHY, (B0VREFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((0x03<<2)|(0x0<<1)|(0x0<<0)), ((BIT7|BIT6|BIT5|BIT4|BIT3|BIT2)|BIT1|BIT0)); // Internal Vref Code, Enable#, Ext_or_Int (1=Ext)
+ isbM32m(DDRPHY, (B1VREFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((0x03<<2)|(0x0<<1)|(0x0<<0)), ((BIT7|BIT6|BIT5|BIT4|BIT3|BIT2)|BIT1|BIT0)); // Internal Vref Code, Enable#, Ext_or_Int (1=Ext)
+ isbM32m(DDRPHY, (B0RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (0), (BIT4)); // Per-Bit De-Skew Enable
+ isbM32m(DDRPHY, (B1RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (0), (BIT4)); // Per-Bit De-Skew Enable
+ }
+ // CLKEBB
+ isbM32m(DDRPHY, (CMDOBSCKEBBCTL + (channel_i * DDRIOCCC_CH_OFFSET)), 0, (BIT23));
+
+ // Enable tristate control of cmd/address bus
+ isbM32m(DDRPHY, (CMDCFGREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), 0, (BIT1|BIT0));
+
+ // ODT RCOMP
+ isbM32m(DDRPHY, (CMDRCOMPODT + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x03<<5)|(0x03<<0)), ((BIT9|BIT8|BIT7|BIT6|BIT5)|(BIT4|BIT3|BIT2|BIT1|BIT0)));
+
+ // CMDPM* registers must be programmed in this order...
+ isbM32m(DDRPHY, (CMDPMDLYREG4 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFFFFU<<16)|(0xFFFF<<0)), ((BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8|BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // Turn On Delays: SFR (regulator), MPLL
+ isbM32m(DDRPHY, (CMDPMDLYREG3 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFU<<28)|(0xFFF<<16)|(0xF<<12)|(0x616<<0)), ((BIT31|BIT30|BIT29|BIT28)|(BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8|BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // Delays: ASSERT_IOBUFACT_to_ALLON0_for_PM_MSG_3, VREG (MDLL) Turn On, ALLON0_to_DEASSERT_IOBUFACT_for_PM_MSG_gt0, MDLL Turn On
+ isbM32m(DDRPHY, (CMDPMDLYREG2 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFFU<<24)|(0xFF<<16)|(0xFF<<8)|(0xFF<<0)), ((BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // MPLL Divider Reset Delays
+ isbM32m(DDRPHY, (CMDPMDLYREG1 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFFU<<24)|(0xFF<<16)|(0xFF<<8)|(0xFF<<0)), ((BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // Turn Off Delays: VREG, Staggered MDLL, MDLL, PI
+ isbM32m(DDRPHY, (CMDPMDLYREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFFU<<24)|(0xFF<<16)|(0xFF<<8)|(0xFF<<0)), ((BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // Turn On Delays: MPLL, Staggered MDLL, PI, IOBUFACT
+ isbM32m(DDRPHY, (CMDPMCONFIG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x6<<8)|BIT6|(0x4<<0)), (BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|(BIT11|BIT10|BIT9|BIT8)|BIT6|(BIT3|BIT2|BIT1|BIT0))); // Allow PUnit signals
+ isbM32m(DDRPHY, (CMDMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x3<<4)|(0x7<<0)), ((BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // DLL_VREG Bias Trim, VREF Tuning for DLL_VREG
+ // CLK-CTL
+ isbM32m(DDRPHY, (CCOBSCKEBBCTL + (channel_i * DDRIOCCC_CH_OFFSET)), 0, (BIT24)); // CLKEBB
+ isbM32m(DDRPHY, (CCCFGREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x0<<16)|(0x0<<12)|(0x0<<8)|(0xF<<4)|BIT0), ((BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|BIT0)); // Buffer Enable: CS,CKE,ODT,CLK
+ isbM32m(DDRPHY, (CCRCOMPODT + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x03<<8)|(0x03<<0)), ((BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // ODT RCOMP
+ isbM32m(DDRPHY, (CCMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x3<<4)|(0x7<<0)), ((BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // DLL_VREG Bias Trim, VREF Tuning for DLL_VREG
+
+ // COMP (RON channel specific)
+ // - DQ/DQS/DM RON: 32 Ohm
+ // - CTRL/CMD RON: 27 Ohm
+ // - CLK RON: 26 Ohm
+ isbM32m(DDRPHY, (DQVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x08<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP Vref PU/PD
+ isbM32m(DDRPHY, (CMDVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x0C<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP Vref PU/PD
+ isbM32m(DDRPHY, (CLKVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x0F<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP Vref PU/PD
+ isbM32m(DDRPHY, (DQSVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x08<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP Vref PU/PD
+ isbM32m(DDRPHY, (CTLVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x0C<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP Vref PU/PD
+
+ // DQS Swapped Input Enable
+ isbM32m(DDRPHY, (COMPEN1CH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT19|BIT17), ((BIT31|BIT30)|BIT19|BIT17|(BIT15|BIT14)));
+
+ // ODT VREF = 1.5 x 274/360+274 = 0.65V (code of ~50)
+ isbM32m(DDRPHY, (DQVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x32<<8)|(0x03<<0)), ((BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // ODT Vref PU/PD
+ isbM32m(DDRPHY, (DQSVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x32<<8)|(0x03<<0)), ((BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // ODT Vref PU/PD
+ isbM32m(DDRPHY, (CLKVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x0E<<8)|(0x05<<0)), ((BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // ODT Vref PU/PD
+
+ // Slew rate settings are frequency specific, numbers below are for 800Mhz (speed == 0)
+ // - DQ/DQS/DM/CLK SR: 4V/ns,
+ // - CTRL/CMD SR: 1.5V/ns
+ tempD = (0x0E<<16)|(0x0E<<12)|(0x08<<8)|(0x0B<<4)|(0x0B<<0);
+ isbM32m(DDRPHY, (DLYSELCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (tempD), ((BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // DCOMP Delay Select: CTL,CMD,CLK,DQS,DQ
+ isbM32m(DDRPHY, (TCOVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x05<<16)|(0x05<<8)|(0x05<<0)), ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // TCO Vref CLK,DQS,DQ
+ isbM32m(DDRPHY, (CCBUFODTCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x03<<8)|(0x03<<0)), ((BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // ODTCOMP CMD/CTL PU/PD
+ isbM32m(DDRPHY, (COMPEN0CH0 + (channel_i * DDRCOMP_CH_OFFSET)), (0), ((BIT31|BIT30)|BIT8)); // COMP
+
+ #ifdef BACKUP_COMPS
+ // DQ COMP Overrides
+ isbM32m(DDRPHY, (DQDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU
+ isbM32m(DDRPHY, (DQDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD
+ isbM32m(DDRPHY, (DQDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x10<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU
+ isbM32m(DDRPHY, (DQDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x10<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD
+ isbM32m(DDRPHY, (DQODTPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PU
+ isbM32m(DDRPHY, (DQODTPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PD
+ isbM32m(DDRPHY, (DQTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PU
+ isbM32m(DDRPHY, (DQTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PD
+ // DQS COMP Overrides
+ isbM32m(DDRPHY, (DQSDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU
+ isbM32m(DDRPHY, (DQSDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD
+ isbM32m(DDRPHY, (DQSDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x10<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU
+ isbM32m(DDRPHY, (DQSDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x10<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD
+ isbM32m(DDRPHY, (DQSODTPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PU
+ isbM32m(DDRPHY, (DQSODTPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PD
+ isbM32m(DDRPHY, (DQSTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PU
+ isbM32m(DDRPHY, (DQSTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PD
+ // CLK COMP Overrides
+ isbM32m(DDRPHY, (CLKDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0C<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU
+ isbM32m(DDRPHY, (CLKDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0C<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD
+ isbM32m(DDRPHY, (CLKDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x07<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU
+ isbM32m(DDRPHY, (CLKDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x07<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD
+ isbM32m(DDRPHY, (CLKODTPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PU
+ isbM32m(DDRPHY, (CLKODTPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PD
+ isbM32m(DDRPHY, (CLKTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PU
+ isbM32m(DDRPHY, (CLKTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PD
+ // CMD COMP Overrides
+ isbM32m(DDRPHY, (CMDDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0D<<16)), (BIT31|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU
+ isbM32m(DDRPHY, (CMDDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0D<<16)), (BIT31|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD
+ isbM32m(DDRPHY, (CMDDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU
+ isbM32m(DDRPHY, (CMDDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD
+ // CTL COMP Overrides
+ isbM32m(DDRPHY, (CTLDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0D<<16)), (BIT31|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU
+ isbM32m(DDRPHY, (CTLDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0D<<16)), (BIT31|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD
+ isbM32m(DDRPHY, (CTLDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU
+ isbM32m(DDRPHY, (CTLDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD
+ #else
+ // DQ TCOCOMP Overrides
+ isbM32m(DDRPHY, (DQTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PU
+ isbM32m(DDRPHY, (DQTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PD
+ // DQS TCOCOMP Overrides
+ isbM32m(DDRPHY, (DQSTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PU
+ isbM32m(DDRPHY, (DQSTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PD
+ // CLK TCOCOMP Overrides
+ isbM32m(DDRPHY, (CLKTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PU
+ isbM32m(DDRPHY, (CLKTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PD
+ #endif // BACKUP_COMPS
+ // program STATIC delays
+ #ifdef BACKUP_WCMD
+ set_wcmd(channel_i, ddr_wcmd[PLATFORM_ID]);
+ #else
+ set_wcmd(channel_i, ddr_wclk[PLATFORM_ID] + HALF_CLK);
+ #endif // BACKUP_WCMD
+ for (rank_i=0; rank_i<NUM_RANKS; rank_i++) {
+ if (mrc_params->rank_enables & (1<<rank_i)) {
+ set_wclk(channel_i, rank_i, ddr_wclk[PLATFORM_ID]);
+ #ifdef BACKUP_WCTL
+ set_wctl(channel_i, rank_i, ddr_wctl[PLATFORM_ID]);
+ #else
+ set_wctl(channel_i, rank_i, ddr_wclk[PLATFORM_ID] + HALF_CLK);
+ #endif // BACKUP_WCTL
+ }
+ }
+ }
+ }
+ // COMP (non channel specific)
+ //isbM32m(DDRPHY, (), (), ());
+ isbM32m(DDRPHY, (DQANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (DQANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (CMDANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (CMDANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (CLKANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (CLKANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (DQSANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (DQSANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (CTLANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (CTLANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (DQANAODTPUCTL), (BIT30), (BIT30)); // ODT: Dither PU Enable
+ isbM32m(DDRPHY, (DQANAODTPDCTL), (BIT30), (BIT30)); // ODT: Dither PD Enable
+ isbM32m(DDRPHY, (CLKANAODTPUCTL), (BIT30), (BIT30)); // ODT: Dither PU Enable
+ isbM32m(DDRPHY, (CLKANAODTPDCTL), (BIT30), (BIT30)); // ODT: Dither PD Enable
+ isbM32m(DDRPHY, (DQSANAODTPUCTL), (BIT30), (BIT30)); // ODT: Dither PU Enable
+ isbM32m(DDRPHY, (DQSANAODTPDCTL), (BIT30), (BIT30)); // ODT: Dither PD Enable
+ isbM32m(DDRPHY, (DQANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (DQANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (CMDANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (CMDANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (CLKANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (CLKANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (DQSANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (DQSANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (CTLANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable
+ isbM32m(DDRPHY, (CTLANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable
+ isbM32m(DDRPHY, (DQANATCOPUCTL), (BIT30), (BIT30)); // TCO: Dither PU Enable
+ isbM32m(DDRPHY, (DQANATCOPDCTL), (BIT30), (BIT30)); // TCO: Dither PD Enable
+ isbM32m(DDRPHY, (CLKANATCOPUCTL), (BIT30), (BIT30)); // TCO: Dither PU Enable
+ isbM32m(DDRPHY, (CLKANATCOPDCTL), (BIT30), (BIT30)); // TCO: Dither PD Enable
+ isbM32m(DDRPHY, (DQSANATCOPUCTL), (BIT30), (BIT30)); // TCO: Dither PU Enable
+ isbM32m(DDRPHY, (DQSANATCOPDCTL), (BIT30), (BIT30)); // TCO: Dither PD Enable
+ isbM32m(DDRPHY, (TCOCNTCTRL), (0x1<<0), (BIT1|BIT0)); // TCOCOMP: Pulse Count
+ isbM32m(DDRPHY, (CHNLBUFSTATIC), ((0x03<<24)|(0x03<<16)), ((BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODT: CMD/CTL PD/PU
+ isbM32m(DDRPHY, (MSCNTR), (0x64<<0), (BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0)); // Set 1us counter
+ isbM32m(DDRPHY, (LATCH1CTL), (0x1<<28), (BIT30|BIT29|BIT28)); // ???
+
+ // Release PHY from reset
+ isbM32m(DDRPHY, MASTERRSTN, BIT0, BIT0); // PHYRSTN=1
+
+ // STEP1:
+ post_code(0x03, 0x11);
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {
+ if (mrc_params->channel_enables & (1<<channel_i)) {
+ // DQ01-DQ23
+ for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {
+ isbM32m(DDRPHY, (DQMDLLCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT13), (BIT13)); // Enable VREG
+ delay_n(3);
+ }
+ // ECC
+ isbM32m(DDRPHY, (ECCMDLLCTL), (BIT13), (BIT13)); // Enable VREG
+ delay_n(3);
+ // CMD
+ isbM32m(DDRPHY, (CMDMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), (BIT13), (BIT13)); // Enable VREG
+ delay_n(3);
+ // CLK-CTL
+ isbM32m(DDRPHY, (CCMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), (BIT13), (BIT13)); // Enable VREG
+ delay_n(3);
+ }
+ }
+
+ // STEP2:
+ post_code(0x03, 0x12);
+ delay_n(200);
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {
+ if (mrc_params->channel_enables & (1<<channel_i)) {
+ // DQ01-DQ23
+ for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {
+ isbM32m(DDRPHY, (DQMDLLCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT17), (BIT17)); // Enable MCDLL
+ delay_n(50);
+ }
+ // ECC
+ isbM32m(DDRPHY, (ECCMDLLCTL), (BIT17), (BIT17)); // Enable MCDLL
+ delay_n(50);
+ // CMD
+ isbM32m(DDRPHY, (CMDMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), (BIT18), (BIT18)); // Enable MCDLL
+ delay_n(50);
+ // CLK-CTL
+ isbM32m(DDRPHY, (CCMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), (BIT18), (BIT18)); // Enable MCDLL
+ delay_n(50);
+ }
+ }
+
+ // STEP3:
+ post_code(0x03, 0x13);
+ delay_n(100);
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {
+ if (mrc_params->channel_enables & (1<<channel_i)) {
+ // DQ01-DQ23
+ for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {
+#ifdef FORCE_16BIT_DDRIO
+ tempD = ((bl_grp_i) && (mrc_params->channel_width == x16)) ? ((0x1<<12)|(0x1<<8)|(0xF<<4)|(0xF<<0)) : ((0xF<<12)|(0xF<<8)|(0xF<<4)|(0xF<<0));
+#else
+ tempD = ((0xF<<12)|(0xF<<8)|(0xF<<4)|(0xF<<0));
+#endif
+ isbM32m(DDRPHY, (DQDLLTXCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (tempD), ((BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // Enable TXDLL
+ delay_n(3);
+ isbM32m(DDRPHY, (DQDLLRXCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT3|BIT2|BIT1|BIT0), (BIT3|BIT2|BIT1|BIT0)); // Enable RXDLL
+ delay_n(3);
+ isbM32m(DDRPHY, (B0OVRCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT3|BIT2|BIT1|BIT0), (BIT3|BIT2|BIT1|BIT0)); // Enable RXDLL Overrides BL0
+ }
+
+ // ECC
+ tempD = ((0xF<<12)|(0xF<<8)|(0xF<<4)|(0xF<<0));
+ isbM32m(DDRPHY, (ECCDLLTXCTL), (tempD), ((BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // Enable TXDLL
+ delay_n(3);
+
+ // CMD (PO)
+ isbM32m(DDRPHY, (CMDDLLTXCTL + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xF<<12)|(0xF<<8)|(0xF<<4)|(0xF<<0)), ((BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // Enable TXDLL
+ delay_n(3);
+ }
+ }
+
+
+ // STEP4:
+ post_code(0x03, 0x14);
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {
+ if (mrc_params->channel_enables & (1<<channel_i)) {
+ // Host To Memory Clock Alignment (HMC) for 800/1066
+ for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {
+ isbM32m(DDRPHY, (DQCLKALIGNREG2 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((bl_grp_i)?(0x3):(0x1)), (BIT3|BIT2|BIT1|BIT0)); // CLK_ALIGN_MOD_ID
+ }
+ isbM32m(DDRPHY, (ECCCLKALIGNREG2 + (channel_i * DDRIODQ_CH_OFFSET)), 0x2, (BIT3|BIT2|BIT1|BIT0)); // CLK_ALIGN_MOD_ID
+ isbM32m(DDRPHY, (CMDCLKALIGNREG2 + (channel_i * DDRIODQ_CH_OFFSET)), 0x0, (BIT3|BIT2|BIT1|BIT0)); // CLK_ALIGN_MOD_ID
+ isbM32m(DDRPHY, (CCCLKALIGNREG2 + (channel_i * DDRIODQ_CH_OFFSET)), 0x2, (BIT3|BIT2|BIT1|BIT0)); // CLK_ALIGN_MOD_ID
+ isbM32m(DDRPHY, (CMDCLKALIGNREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), (0x2<<4), (BIT5|BIT4)); // CLK_ALIGN_MODE
+ isbM32m(DDRPHY, (CMDCLKALIGNREG1 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x18<<16)|(0x10<<8)|(0x8<<2)|(0x1<<0)), ((BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4|BIT3|BIT2)|(BIT1|BIT0))); // NUM_SAMPLES, MAX_SAMPLES, MACRO_PI_STEP, MICRO_PI_STEP
+ isbM32m(DDRPHY, (CMDCLKALIGNREG2 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x10<<16)|(0x4<<8)|(0x2<<4)), ((BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4))); // ???, TOTAL_NUM_MODULES, FIRST_U_PARTITION
+ #ifdef HMC_TEST
+ isbM32m(DDRPHY, (CMDCLKALIGNREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), BIT24, BIT24); // START_CLK_ALIGN=1
+ while (isbR32m(DDRPHY, (CMDCLKALIGNREG0 + (channel_i * DDRIOCCC_CH_OFFSET))) & BIT24); // wait for START_CLK_ALIGN=0
+ #endif // HMC_TEST
+
+ // Set RD/WR Pointer Seperation & COUNTEN & FIFOPTREN
+ isbM32m(DDRPHY, (CMDPTRREG + (channel_i * DDRIOCCC_CH_OFFSET)), BIT0, BIT0); // WRPTRENABLE=1
+
+
+#ifdef SIM
+ // comp is not working on simulator
+#else
+ // COMP initial
+ isbM32m(DDRPHY, (COMPEN0CH0 + (channel_i * DDRCOMP_CH_OFFSET)), BIT5, BIT5); // enable bypass for CLK buffer (PO)
+ isbM32m(DDRPHY, (CMPCTRL), (BIT0), (BIT0)); // Initial COMP Enable
+ while (isbR32m(DDRPHY, (CMPCTRL)) & BIT0); // wait for Initial COMP Enable = 0
+ isbM32m(DDRPHY, (COMPEN0CH0 + (channel_i * DDRCOMP_CH_OFFSET)), ~BIT5, BIT5); // disable bypass for CLK buffer (PO)
+#endif
+
+ // IOBUFACT
+ // STEP4a
+ isbM32m(DDRPHY, (CMDCFGREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), BIT2, BIT2); // IOBUFACTRST_N=1
+
+ // DDRPHY initialisation complete
+ isbM32m(DDRPHY, (CMDPMCONFIG0 + (channel_i * DDRIOCCC_CH_OFFSET)), BIT20, BIT20); // SPID_INIT_COMPLETE=1
+ }
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// jedec_init (aka PerformJedecInit):
+// This function performs JEDEC initialisation on all enabled channels.
+static void jedec_init(
+ MRCParams_t *mrc_params,
+ uint32_t silent)
+{
+ uint8_t TWR, WL, Rank;
+ uint32_t TCK;
+
+ RegDTR0 DTR0reg;
+
+ DramInitDDR3MRS0 mrs0Command;
+ DramInitDDR3EMR1 emrs1Command;
+ DramInitDDR3EMR2 emrs2Command;
+ DramInitDDR3EMR3 emrs3Command;
+
+ ENTERFN();
+
+ // jedec_init starts
+ if (!silent)
+ {
+ post_code(0x04, 0x00);
+ }
+
+ // Assert RESET# for 200us
+ isbM32m(DDRPHY, CCDDR3RESETCTL, BIT1, (BIT8|BIT1)); // DDR3_RESET_SET=0, DDR3_RESET_RESET=1
+#ifdef QUICKSIM
+ // Don't waste time during simulation
+ delay_u(2);
+#else
+ delay_u(200);
+#endif
+ isbM32m(DDRPHY, CCDDR3RESETCTL, BIT8, (BIT8|BIT1)); // DDR3_RESET_SET=1, DDR3_RESET_RESET=0
+
+ DTR0reg.raw = isbR32m(MCU, DTR0);
+
+ // Set CKEVAL for populated ranks
+ // then send NOP to each rank (#4550197)
+ {
+ uint32_t DRPbuffer;
+ uint32_t DRMCbuffer;
+
+ DRPbuffer = isbR32m(MCU, DRP);
+ DRPbuffer &= 0x3;
+ DRMCbuffer = isbR32m(MCU, DRMC);
+ DRMCbuffer &= 0xFFFFFFFC;
+ DRMCbuffer |= (BIT4 | DRPbuffer);
+
+ isbW32m(MCU, DRMC, DRMCbuffer);
+
+ for (Rank = 0; Rank < NUM_RANKS; Rank++)
+ {
+ // Skip to next populated rank
+ if ((mrc_params->rank_enables & (1 << Rank)) == 0)
+ {
+ continue;
+ }
+
+ dram_init_command(DCMD_NOP(Rank));
+ }
+
+ isbW32m(MCU, DRMC, DRMC_DEFAULT);
+ }
+
+ // setup for emrs 2
+ // BIT[15:11] --> Always "0"
+ // BIT[10:09] --> Rtt_WR: want "Dynamic ODT Off" (0)
+ // BIT[08] --> Always "0"
+ // BIT[07] --> SRT: use sr_temp_range
+ // BIT[06] --> ASR: want "Manual SR Reference" (0)
+ // BIT[05:03] --> CWL: use oem_tCWL
+ // BIT[02:00] --> PASR: want "Full Array" (0)
+ emrs2Command.raw = 0;
+ emrs2Command.field.bankAddress = 2;
+
+ WL = 5 + mrc_params->ddr_speed;
+ emrs2Command.field.CWL = WL - 5;
+ emrs2Command.field.SRT = mrc_params->sr_temp_range;
+
+ // setup for emrs 3
+ // BIT[15:03] --> Always "0"
+ // BIT[02] --> MPR: want "Normal Operation" (0)
+ // BIT[01:00] --> MPR_Loc: want "Predefined Pattern" (0)
+ emrs3Command.raw = 0;
+ emrs3Command.field.bankAddress = 3;
+
+ // setup for emrs 1
+ // BIT[15:13] --> Always "0"
+ // BIT[12:12] --> Qoff: want "Output Buffer Enabled" (0)
+ // BIT[11:11] --> TDQS: want "Disabled" (0)
+ // BIT[10:10] --> Always "0"
+ // BIT[09,06,02] --> Rtt_nom: use rtt_nom_value
+ // BIT[08] --> Always "0"
+ // BIT[07] --> WR_LVL: want "Disabled" (0)
+ // BIT[05,01] --> DIC: use ron_value
+ // BIT[04:03] --> AL: additive latency want "0" (0)
+ // BIT[00] --> DLL: want "Enable" (0)
+ //
+ // (BIT5|BIT1) set Ron value
+ // 00 --> RZQ/6 (40ohm)
+ // 01 --> RZQ/7 (34ohm)
+ // 1* --> RESERVED
+ //
+ // (BIT9|BIT6|BIT2) set Rtt_nom value
+ // 000 --> Disabled
+ // 001 --> RZQ/4 ( 60ohm)
+ // 010 --> RZQ/2 (120ohm)
+ // 011 --> RZQ/6 ( 40ohm)
+ // 1** --> RESERVED
+ emrs1Command.raw = 0;
+ emrs1Command.field.bankAddress = 1;
+ emrs1Command.field.dllEnabled = 0; // 0 = Enable , 1 = Disable
+
+ if (mrc_params->ron_value == 0)
+ {
+ emrs1Command.field.DIC0 = DDR3_EMRS1_DIC_34;
+ }
+ else
+ {
+ emrs1Command.field.DIC0 = DDR3_EMRS1_DIC_40;
+ }
+
+
+ if (mrc_params->rtt_nom_value == 0)
+ {
+ emrs1Command.raw |= (DDR3_EMRS1_RTTNOM_40 << 6);
+ }
+ else if (mrc_params->rtt_nom_value == 1)
+ {
+ emrs1Command.raw |= (DDR3_EMRS1_RTTNOM_60 << 6);
+ }
+ else if (mrc_params->rtt_nom_value == 2)
+ {
+ emrs1Command.raw |= (DDR3_EMRS1_RTTNOM_120 << 6);
+ }
+
+ // save MRS1 value (excluding control fields)
+ mrc_params->mrs1 = emrs1Command.raw >> 6;
+
+ // setup for mrs 0
+ // BIT[15:13] --> Always "0"
+ // BIT[12] --> PPD: for Quark (1)
+ // BIT[11:09] --> WR: use oem_tWR
+ // BIT[08] --> DLL: want "Reset" (1, self clearing)
+ // BIT[07] --> MODE: want "Normal" (0)
+ // BIT[06:04,02] --> CL: use oem_tCAS
+ // BIT[03] --> RD_BURST_TYPE: want "Interleave" (1)
+ // BIT[01:00] --> BL: want "8 Fixed" (0)
+ // WR:
+ // 0 --> 16
+ // 1 --> 5
+ // 2 --> 6
+ // 3 --> 7
+ // 4 --> 8
+ // 5 --> 10
+ // 6 --> 12
+ // 7 --> 14
+ // CL:
+ // BIT[02:02] "0" if oem_tCAS <= 11 (1866?)
+ // BIT[06:04] use oem_tCAS-4
+ mrs0Command.raw = 0;
+ mrs0Command.field.bankAddress = 0;
+ mrs0Command.field.dllReset = 1;
+ mrs0Command.field.BL = 0;
+ mrs0Command.field.PPD = 1;
+ mrs0Command.field.casLatency = DTR0reg.field.tCL + 1;
+
+ TCK = tCK[mrc_params->ddr_speed];
+ TWR = MCEIL(15000, TCK); // Per JEDEC: tWR=15000ps DDR2/3 from 800-1600
+ mrs0Command.field.writeRecovery = TWR - 4;
+
+ for (Rank = 0; Rank < NUM_RANKS; Rank++)
+ {
+ // Skip to next populated rank
+ if ((mrc_params->rank_enables & (1 << Rank)) == 0)
+ {
+ continue;
+ }
+
+ emrs2Command.field.rankSelect = Rank;
+ dram_init_command(emrs2Command.raw);
+
+ emrs3Command.field.rankSelect = Rank;
+ dram_init_command(emrs3Command.raw);
+
+ emrs1Command.field.rankSelect = Rank;
+ dram_init_command(emrs1Command.raw);
+
+ mrs0Command.field.rankSelect = Rank;
+ dram_init_command(mrs0Command.raw);
+
+ dram_init_command(DCMD_ZQCL(Rank));
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// rcvn_cal:
+// POST_CODE[major] == 0x05
+//
+// This function will perform our RCVEN Calibration Algorithm.
+// We will only use the 2xCLK domain timings to perform RCVEN Calibration.
+// All byte lanes will be calibrated "simultaneously" per channel per rank.
+static void rcvn_cal(
+ MRCParams_t *mrc_params)
+{
+ uint8_t channel_i; // channel counter
+ uint8_t rank_i; // rank counter
+ uint8_t bl_i; // byte lane counter
+ uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor
+
+#ifdef R2R_SHARING
+ uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES]; // used to find placement for rank2rank sharing configs
+#ifndef BACKUP_RCVN
+ uint32_t num_ranks_enabled = 0; // used to find placement for rank2rank sharing configs
+#endif // BACKUP_RCVN
+#endif // R2R_SHARING
+
+#ifdef BACKUP_RCVN
+#else
+ uint32_t tempD; // temporary DWORD
+ uint32_t delay[NUM_BYTE_LANES]; // absolute PI value to be programmed on the byte lane
+ RegDTR1 dtr1;
+ RegDTR1 dtr1save;
+#endif // BACKUP_RCVN
+ ENTERFN();
+
+ // rcvn_cal starts
+ post_code(0x05, 0x00);
+
+#ifndef BACKUP_RCVN
+ // need separate burst to sample DQS preamble
+ dtr1.raw = dtr1save.raw = isbR32m(MCU, DTR1);
+ dtr1.field.tCCD = 1;
+ isbW32m(MCU, DTR1, dtr1.raw);
+#endif
+
+#ifdef R2R_SHARING
+ // need to set "final_delay[][]" elements to "0"
+ memset((void *) (final_delay), 0x00, (size_t) sizeof(final_delay));
+#endif // R2R_SHARING
+
+ // loop through each enabled channel
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ // perform RCVEN Calibration on a per rank basis
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+ // POST_CODE here indicates the current channel and rank being calibrated
+ post_code(0x05, (0x10 + ((channel_i << 4) | rank_i)));
+
+#ifdef BACKUP_RCVN
+ // set hard-coded timing values
+ for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)
+ {
+ set_rcvn(channel_i, rank_i, bl_i, ddr_rcvn[PLATFORM_ID]);
+ }
+#else
+ // enable FIFORST
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i += 2)
+ {
+ isbM32m(DDRPHY, (B01PTRCTL1 + ((bl_i >> 1) * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), 0,
+ BIT8); // 0 is enabled
+ } // bl_i loop
+ // initialise the starting delay to 128 PI (tCAS +1 CLK)
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+#ifdef SIM
+ // Original value was late at the end of DQS sequence
+ delay[bl_i] = 3 * FULL_CLK;
+#else
+ delay[bl_i] = (4 + 1) * FULL_CLK; // 1x CLK domain timing is tCAS-4
+#endif
+
+ set_rcvn(channel_i, rank_i, bl_i, delay[bl_i]);
+ } // bl_i loop
+
+ // now find the rising edge
+ find_rising_edge(mrc_params, delay, channel_i, rank_i, true);
+ // Now increase delay by 32 PI (1/4 CLK) to place in center of high pulse.
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ delay[bl_i] += QRTR_CLK;
+ set_rcvn(channel_i, rank_i, bl_i, delay[bl_i]);
+ } // bl_i loop
+ // Now decrement delay by 128 PI (1 CLK) until we sample a "0"
+ do
+ {
+
+ tempD = sample_dqs(mrc_params, channel_i, rank_i, true);
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ if (tempD & (1 << bl_i))
+ {
+ if (delay[bl_i] >= FULL_CLK)
+ {
+ delay[bl_i] -= FULL_CLK;
+ set_rcvn(channel_i, rank_i, bl_i, delay[bl_i]);
+ }
+ else
+ {
+ // not enough delay
+ training_message(channel_i, rank_i, bl_i);
+ post_code(0xEE, 0x50);
+ }
+ }
+ } // bl_i loop
+ } while (tempD & 0xFF);
+
+#ifdef R2R_SHARING
+ // increment "num_ranks_enabled"
+ num_ranks_enabled++;
+ // Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble.
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ delay[bl_i] += QRTR_CLK;
+ // add "delay[]" values to "final_delay[][]" for rolling average
+ final_delay[channel_i][bl_i] += delay[bl_i];
+ // set timing based on rolling average values
+ set_rcvn(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled));
+ } // bl_i loop
+#else
+ // Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble.
+ for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)
+ {
+ delay[bl_i] += QRTR_CLK;
+ set_rcvn(channel_i, rank_i, bl_i, delay[bl_i]);
+ } // bl_i loop
+
+#endif // R2R_SHARING
+
+ // disable FIFORST
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i += 2)
+ {
+ isbM32m(DDRPHY, (B01PTRCTL1 + ((bl_i >> 1) * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), BIT8,
+ BIT8); // 1 is disabled
+ } // bl_i loop
+
+#endif // BACKUP_RCVN
+
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+
+#ifndef BACKUP_RCVN
+ // restore original
+ isbW32m(MCU, DTR1, dtr1save.raw);
+#endif
+
+#ifdef MRC_SV
+ if (mrc_params->tune_rcvn)
+ {
+ uint32_t rcven, val;
+ uint32_t rdcmd2rcven;
+
+ /*
+ Formulas for RDCMD2DATAVALID & DIFFAMP dynamic timings
+
+ 1. Set after RCVEN training
+
+ //Tune RDCMD2DATAVALID
+
+ x80/x84[21:16]
+ MAX OF 2 RANKS : round up (rdcmd2rcven (rcven 1x) + 2x x 2 + PI/128) + 5
+
+ //rdcmd2rcven x80/84[12:8]
+ //rcven 2x x70[23:20] & [11:8]
+
+ //Tune DIFFAMP Timings
+
+ //diffampen launch x88[20:16] & [4:0] -- B01LATCTL1
+ MIN OF 2 RANKS : round down (rcven 1x + 2x x 2 + PI/128) - 1
+
+ //diffampen length x8C/x90 [13:8] -- B0ONDURCTL B1ONDURCTL
+ MAX OF 2 RANKS : roundup (rcven 1x + 2x x 2 + PI/128) + 5
+
+
+ 2. need to do a fiforst after settings these values
+ */
+
+ DPF(D_INFO, "BEFORE\n");
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B0LATCTL0));
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B01LATCTL1));
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B0ONDURCTL));
+
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B1LATCTL0));
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B1ONDURCTL));
+
+ rcven = get_rcvn(0, 0, 0) / 128;
+ rdcmd2rcven = (isbR32m(DDRPHY, B0LATCTL0) >> 8) & 0x1F;
+ val = rdcmd2rcven + rcven + 6;
+ isbM32m(DDRPHY, B0LATCTL0, val << 16, (BIT21|BIT20|BIT19|BIT18|BIT17|BIT16));
+
+ val = rdcmd2rcven + rcven - 1;
+ isbM32m(DDRPHY, B01LATCTL1, val << 0, (BIT4|BIT3|BIT2|BIT1|BIT0));
+
+ val = rdcmd2rcven + rcven + 5;
+ isbM32m(DDRPHY, B0ONDURCTL, val << 8, (BIT13|BIT12|BIT11|BIT10|BIT9|BIT8));
+
+ rcven = get_rcvn(0, 0, 1) / 128;
+ rdcmd2rcven = (isbR32m(DDRPHY, B1LATCTL0) >> 8) & 0x1F;
+ val = rdcmd2rcven + rcven + 6;
+ isbM32m(DDRPHY, B1LATCTL0, val << 16, (BIT21|BIT20|BIT19|BIT18|BIT17|BIT16));
+
+ val = rdcmd2rcven + rcven - 1;
+ isbM32m(DDRPHY, B01LATCTL1, val << 16, (BIT20|BIT19|BIT18|BIT17|BIT16));
+
+ val = rdcmd2rcven + rcven + 5;
+ isbM32m(DDRPHY, B1ONDURCTL, val << 8, (BIT13|BIT12|BIT11|BIT10|BIT9|BIT8));
+
+ DPF(D_INFO, "AFTER\n");
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B0LATCTL0));
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B01LATCTL1));
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B0ONDURCTL));
+
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B1LATCTL0));
+ DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B1ONDURCTL));
+
+ DPF(D_INFO, "\nPress a key\n");
+ mgetc();
+
+ // fifo reset
+ isbM32m(DDRPHY, B01PTRCTL1, 0, BIT8); // 0 is enabled
+ delay_n(3);
+ isbM32m(DDRPHY, B01PTRCTL1, BIT8, BIT8); // 1 is disabled
+ }
+#endif
+
+ LEAVEFN();
+ return;
+}
+
+// Check memory executing write/read/verify of many data patterns
+// at the specified address. Bits in the result indicate failure
+// on specific byte lane.
+static uint32_t check_bls_ex(
+ MRCParams_t *mrc_params,
+ uint32_t address)
+{
+ uint32_t result;
+ uint8_t first_run = 0;
+
+ if (mrc_params->hte_setup)
+ {
+ mrc_params->hte_setup = 0;
+
+ first_run = 1;
+ select_hte(mrc_params);
+ }
+
+ result = WriteStressBitLanesHTE(mrc_params, address, first_run);
+
+ DPF(D_TRN, "check_bls_ex result is %x\n", result);
+ return result;
+}
+
+// Check memory executing simple write/read/verify at
+// the specified address. Bits in the result indicate failure
+// on specific byte lane.
+static uint32_t check_rw_coarse(
+ MRCParams_t *mrc_params,
+ uint32_t address)
+{
+ uint32_t result = 0;
+ uint8_t first_run = 0;
+
+ if (mrc_params->hte_setup)
+ {
+ mrc_params->hte_setup = 0;
+
+ first_run = 1;
+ select_hte(mrc_params);
+ }
+
+ result = BasicWriteReadHTE(mrc_params, address, first_run, WRITE_TRAIN);
+
+ DPF(D_TRN, "check_rw_coarse result is %x\n", result);
+ return result;
+}
+
+// wr_level:
+// POST_CODE[major] == 0x06
+//
+// This function will perform the Write Levelling algorithm (align WCLK and WDQS).
+// This algorithm will act on each rank in each channel separately.
+static void wr_level(
+ MRCParams_t *mrc_params)
+{
+ uint8_t channel_i; // channel counter
+ uint8_t rank_i; // rank counter
+ uint8_t bl_i; // byte lane counter
+ uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor
+
+#ifdef R2R_SHARING
+ uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES]; // used to find placement for rank2rank sharing configs
+#ifndef BACKUP_WDQS
+ uint32_t num_ranks_enabled = 0; // used to find placement for rank2rank sharing configs
+#endif // BACKUP_WDQS
+#endif // R2R_SHARING
+
+#ifdef BACKUP_WDQS
+#else
+ bool all_edges_found; // determines stop condition for CRS_WR_LVL
+ uint32_t delay[NUM_BYTE_LANES]; // absolute PI value to be programmed on the byte lane
+ // static makes it so the data is loaded in the heap once by shadow(), where
+ // non-static copies the data onto the stack every time this function is called.
+
+ uint32_t address; // address to be checked during COARSE_WR_LVL
+ RegDTR4 dtr4;
+ RegDTR4 dtr4save;
+#endif // BACKUP_WDQS
+
+ ENTERFN();
+
+ // wr_level starts
+ post_code(0x06, 0x00);
+
+#ifdef R2R_SHARING
+ // need to set "final_delay[][]" elements to "0"
+ memset((void *) (final_delay), 0x00, (size_t) sizeof(final_delay));
+#endif // R2R_SHARING
+ // loop through each enabled channel
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ // perform WRITE LEVELING algorithm on a per rank basis
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+ // POST_CODE here indicates the current rank and channel being calibrated
+ post_code(0x06, (0x10 + ((channel_i << 4) | rank_i)));
+
+#ifdef BACKUP_WDQS
+ for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)
+ {
+ set_wdqs(channel_i, rank_i, bl_i, ddr_wdqs[PLATFORM_ID]);
+ set_wdq(channel_i, rank_i, bl_i, (ddr_wdqs[PLATFORM_ID] - QRTR_CLK));
+ }
+#else
+
+ { // Begin product specific code
+
+ // perform a single PRECHARGE_ALL command to make DRAM state machine go to IDLE state
+ dram_init_command(DCMD_PREA(rank_i));
+
+ // enable Write Levelling Mode (EMRS1 w/ Write Levelling Mode Enable)
+ dram_init_command(DCMD_MRS1(rank_i,0x0082));
+
+ // set ODT DRAM Full Time Termination disable in MCU
+ dtr4.raw = dtr4save.raw = isbR32m(MCU, DTR4);
+ dtr4.field.ODTDIS = 1;
+ isbW32m(MCU, DTR4, dtr4.raw);
+
+ for (bl_i = 0; bl_i < ((NUM_BYTE_LANES / bl_divisor) / 2); bl_i++)
+ {
+ isbM32m(DDRPHY, DQCTL + (DDRIODQ_BL_OFFSET * bl_i) + (DDRIODQ_CH_OFFSET * channel_i),
+ (BIT28 | (0x1 << 8) | (0x1 << 6) | (0x1 << 4) | (0x1 << 2)),
+ (BIT28 | (BIT9|BIT8) | (BIT7|BIT6) | (BIT5|BIT4) | (BIT3|BIT2))); // Enable Sandy Bridge Mode (WDQ Tri-State) & Ensure 5 WDQS pulses during Write Leveling
+ }
+
+ isbM32m(DDRPHY, CCDDR3RESETCTL + (DDRIOCCC_CH_OFFSET * channel_i), (BIT16), (BIT16)); // Write Leveling Mode enabled in IO
+ } // End product specific code
+ // Initialise the starting delay to WCLK
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ { // Begin product specific code
+ // CLK0 --> RK0
+ // CLK1 --> RK1
+ delay[bl_i] = get_wclk(channel_i, rank_i);
+ } // End product specific code
+ set_wdqs(channel_i, rank_i, bl_i, delay[bl_i]);
+ } // bl_i loop
+ // now find the rising edge
+ find_rising_edge(mrc_params, delay, channel_i, rank_i, false);
+ { // Begin product specific code
+ // disable Write Levelling Mode
+ isbM32m(DDRPHY, CCDDR3RESETCTL + (DDRIOCCC_CH_OFFSET * channel_i), (0), (BIT16)); // Write Leveling Mode disabled in IO
+
+ for (bl_i = 0; bl_i < ((NUM_BYTE_LANES / bl_divisor) / 2); bl_i++)
+ {
+ isbM32m(DDRPHY, DQCTL + (DDRIODQ_BL_OFFSET * bl_i) + (DDRIODQ_CH_OFFSET * channel_i),
+ ((0x1 << 8) | (0x1 << 6) | (0x1 << 4) | (0x1 << 2)),
+ (BIT28 | (BIT9|BIT8) | (BIT7|BIT6) | (BIT5|BIT4) | (BIT3|BIT2))); // Disable Sandy Bridge Mode & Ensure 4 WDQS pulses during normal operation
+ } // bl_i loop
+
+ // restore original DTR4
+ isbW32m(MCU, DTR4, dtr4save.raw);
+
+ // restore original value (Write Levelling Mode Disable)
+ dram_init_command(DCMD_MRS1(rank_i, mrc_params->mrs1));
+
+ // perform a single PRECHARGE_ALL command to make DRAM state machine go to IDLE state
+ dram_init_command(DCMD_PREA(rank_i));
+ } // End product specific code
+
+ post_code(0x06, (0x30 + ((channel_i << 4) | rank_i)));
+
+ // COARSE WRITE LEVEL:
+ // check that we're on the correct clock edge
+
+ // hte reconfiguration request
+ mrc_params->hte_setup = 1;
+
+ // start CRS_WR_LVL with WDQS = WDQS + 128 PI
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ delay[bl_i] = get_wdqs(channel_i, rank_i, bl_i) + FULL_CLK;
+ set_wdqs(channel_i, rank_i, bl_i, delay[bl_i]);
+ // program WDQ timings based on WDQS (WDQ = WDQS - 32 PI)
+ set_wdq(channel_i, rank_i, bl_i, (delay[bl_i] - QRTR_CLK));
+ } // bl_i loop
+
+ // get an address in the targeted channel/rank
+ address = get_addr(mrc_params, channel_i, rank_i);
+ do
+ {
+ uint32_t coarse_result = 0x00;
+ uint32_t coarse_result_mask = byte_lane_mask(mrc_params);
+ all_edges_found = true; // assume pass
+
+#ifdef SIM
+ // need restore memory to idle state as write can be in bad sync
+ dram_init_command (DCMD_PREA(rank_i));
+#endif
+
+ mrc_params->hte_setup = 1;
+ coarse_result = check_rw_coarse(mrc_params, address);
+
+ // check for failures and margin the byte lane back 128 PI (1 CLK)
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ if (coarse_result & (coarse_result_mask << bl_i))
+ {
+ all_edges_found = false;
+ delay[bl_i] -= FULL_CLK;
+ set_wdqs(channel_i, rank_i, bl_i, delay[bl_i]);
+ // program WDQ timings based on WDQS (WDQ = WDQS - 32 PI)
+ set_wdq(channel_i, rank_i, bl_i, (delay[bl_i] - QRTR_CLK));
+ }
+ } // bl_i loop
+
+ } while (!all_edges_found);
+
+#ifdef R2R_SHARING
+ // increment "num_ranks_enabled"
+ num_ranks_enabled++;
+ // accumulate "final_delay[][]" values from "delay[]" values for rolling average
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ final_delay[channel_i][bl_i] += delay[bl_i];
+ set_wdqs(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled));
+ // program WDQ timings based on WDQS (WDQ = WDQS - 32 PI)
+ set_wdq(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled) - QRTR_CLK);
+ } // bl_i loop
+#endif // R2R_SHARING
+#endif // BACKUP_WDQS
+
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+
+ LEAVEFN();
+ return;
+}
+
+// rd_train:
+// POST_CODE[major] == 0x07
+//
+// This function will perform the READ TRAINING Algorithm on all channels/ranks/byte_lanes simultaneously to minimize execution time.
+// The idea here is to train the VREF and RDQS (and eventually RDQ) values to achieve maximum READ margins.
+// The algorithm will first determine the X coordinate (RDQS setting).
+// This is done by collapsing the VREF eye until we find a minimum required RDQS eye for VREF_MIN and VREF_MAX.
+// Then we take the averages of the RDQS eye at VREF_MIN and VREF_MAX, then average those; this will be the final X coordinate.
+// The algorithm will then determine the Y coordinate (VREF setting).
+// This is done by collapsing the RDQS eye until we find a minimum required VREF eye for RDQS_MIN and RDQS_MAX.
+// Then we take the averages of the VREF eye at RDQS_MIN and RDQS_MAX, then average those; this will be the final Y coordinate.
+// NOTE: this algorithm assumes the eye curves have a one-to-one relationship, meaning for each X the curve has only one Y and vice-a-versa.
+static void rd_train(
+ MRCParams_t *mrc_params)
+{
+
+#define MIN_RDQS_EYE 10 // in PI Codes
+#define MIN_VREF_EYE 10 // in VREF Codes
+#define RDQS_STEP 1 // how many RDQS codes to jump while margining
+#define VREF_STEP 1 // how many VREF codes to jump while margining
+#define VREF_MIN (0x00) // offset into "vref_codes[]" for minimum allowed VREF setting
+#define VREF_MAX (0x3F) // offset into "vref_codes[]" for maximum allowed VREF setting
+#define RDQS_MIN (0x00) // minimum RDQS delay value
+#define RDQS_MAX (0x3F) // maximum RDQS delay value
+#define B 0 // BOTTOM VREF
+#define T 1 // TOP VREF
+#define L 0 // LEFT RDQS
+#define R 1 // RIGHT RDQS
+
+ uint8_t channel_i; // channel counter
+ uint8_t rank_i; // rank counter
+ uint8_t bl_i; // byte lane counter
+ uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor
+#ifdef BACKUP_RDQS
+#else
+ uint8_t side_x; // tracks LEFT/RIGHT approach vectors
+ uint8_t side_y; // tracks BOTTOM/TOP approach vectors
+ uint8_t x_coordinate[2/*side_x*/][2/*side_y*/][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES]; // X coordinate data (passing RDQS values) for approach vectors
+ uint8_t y_coordinate[2/*side_x*/][2/*side_y*/][NUM_CHANNELS][NUM_BYTE_LANES]; // Y coordinate data (passing VREF values) for approach vectors
+ uint8_t x_center[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES]; // centered X (RDQS)
+ uint8_t y_center[NUM_CHANNELS][NUM_BYTE_LANES]; // centered Y (VREF)
+ uint32_t address; // target address for "check_bls_ex()"
+ uint32_t result; // result of "check_bls_ex()"
+ uint32_t bl_mask; // byte lane mask for "result" checking
+#ifdef R2R_SHARING
+ uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES]; // used to find placement for rank2rank sharing configs
+ uint32_t num_ranks_enabled = 0; // used to find placement for rank2rank sharing configs
+#endif // R2R_SHARING
+#endif // BACKUP_RDQS
+ // rd_train starts
+ post_code(0x07, 0x00);
+
+ ENTERFN();
+
+#ifdef BACKUP_RDQS
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1<<channel_i))
+ {
+ for (rank_i=0; rank_i<NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1<<rank_i))
+ {
+ for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)
+ {
+ set_rdqs(channel_i, rank_i, bl_i, ddr_rdqs[PLATFORM_ID]);
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+#else
+ // initialise x/y_coordinate arrays
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ // x_coordinate:
+ x_coordinate[L][B][channel_i][rank_i][bl_i] = RDQS_MIN;
+ x_coordinate[R][B][channel_i][rank_i][bl_i] = RDQS_MAX;
+ x_coordinate[L][T][channel_i][rank_i][bl_i] = RDQS_MIN;
+ x_coordinate[R][T][channel_i][rank_i][bl_i] = RDQS_MAX;
+ // y_coordinate:
+ y_coordinate[L][B][channel_i][bl_i] = VREF_MIN;
+ y_coordinate[R][B][channel_i][bl_i] = VREF_MIN;
+ y_coordinate[L][T][channel_i][bl_i] = VREF_MAX;
+ y_coordinate[R][T][channel_i][bl_i] = VREF_MAX;
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+
+ // initialise other variables
+ bl_mask = byte_lane_mask(mrc_params);
+ address = get_addr(mrc_params, 0, 0);
+
+#ifdef R2R_SHARING
+ // need to set "final_delay[][]" elements to "0"
+ memset((void *) (final_delay), 0x00, (size_t) sizeof(final_delay));
+#endif // R2R_SHARING
+
+ // look for passing coordinates
+ for (side_y = B; side_y <= T; side_y++)
+ {
+ for (side_x = L; side_x <= R; side_x++)
+ {
+
+ post_code(0x07, (0x10 + (side_y * 2) + (side_x)));
+
+ // find passing values
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (0x1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+
+ if (mrc_params->rank_enables & (0x1 << rank_i))
+ {
+ // set x/y_coordinate search starting settings
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ set_rdqs(channel_i, rank_i, bl_i, x_coordinate[side_x][side_y][channel_i][rank_i][bl_i]);
+ set_vref(channel_i, bl_i, y_coordinate[side_x][side_y][channel_i][bl_i]);
+ } // bl_i loop
+ // get an address in the target channel/rank
+ address = get_addr(mrc_params, channel_i, rank_i);
+
+ // request HTE reconfiguration
+ mrc_params->hte_setup = 1;
+
+ // test the settings
+ do
+ {
+
+ // result[07:00] == failing byte lane (MAX 8)
+ result = check_bls_ex( mrc_params, address);
+
+ // check for failures
+ if (result & 0xFF)
+ {
+ // at least 1 byte lane failed
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ if (result & (bl_mask << bl_i))
+ {
+ // adjust the RDQS values accordingly
+ if (side_x == L)
+ {
+ x_coordinate[L][side_y][channel_i][rank_i][bl_i] += RDQS_STEP;
+ }
+ else
+ {
+ x_coordinate[R][side_y][channel_i][rank_i][bl_i] -= RDQS_STEP;
+ }
+ // check that we haven't closed the RDQS_EYE too much
+ if ((x_coordinate[L][side_y][channel_i][rank_i][bl_i] > (RDQS_MAX - MIN_RDQS_EYE)) ||
+ (x_coordinate[R][side_y][channel_i][rank_i][bl_i] < (RDQS_MIN + MIN_RDQS_EYE))
+ ||
+ (x_coordinate[L][side_y][channel_i][rank_i][bl_i]
+ == x_coordinate[R][side_y][channel_i][rank_i][bl_i]))
+ {
+ // not enough RDQS margin available at this VREF
+ // update VREF values accordingly
+ if (side_y == B)
+ {
+ y_coordinate[side_x][B][channel_i][bl_i] += VREF_STEP;
+ }
+ else
+ {
+ y_coordinate[side_x][T][channel_i][bl_i] -= VREF_STEP;
+ }
+ // check that we haven't closed the VREF_EYE too much
+ if ((y_coordinate[side_x][B][channel_i][bl_i] > (VREF_MAX - MIN_VREF_EYE)) ||
+ (y_coordinate[side_x][T][channel_i][bl_i] < (VREF_MIN + MIN_VREF_EYE)) ||
+ (y_coordinate[side_x][B][channel_i][bl_i] == y_coordinate[side_x][T][channel_i][bl_i]))
+ {
+ // VREF_EYE collapsed below MIN_VREF_EYE
+ training_message(channel_i, rank_i, bl_i);
+ post_code(0xEE, (0x70 + (side_y * 2) + (side_x)));
+ }
+ else
+ {
+ // update the VREF setting
+ set_vref(channel_i, bl_i, y_coordinate[side_x][side_y][channel_i][bl_i]);
+ // reset the X coordinate to begin the search at the new VREF
+ x_coordinate[side_x][side_y][channel_i][rank_i][bl_i] =
+ (side_x == L) ? (RDQS_MIN) : (RDQS_MAX);
+ }
+ }
+ // update the RDQS setting
+ set_rdqs(channel_i, rank_i, bl_i, x_coordinate[side_x][side_y][channel_i][rank_i][bl_i]);
+ } // if bl_i failed
+ } // bl_i loop
+ } // at least 1 byte lane failed
+ } while (result & 0xFF);
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+ } // side_x loop
+ } // side_y loop
+
+ post_code(0x07, 0x20);
+
+ // find final RDQS (X coordinate) & final VREF (Y coordinate)
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ uint32_t tempD1;
+ uint32_t tempD2;
+
+ // x_coordinate:
+ DPF(D_INFO, "RDQS T/B eye rank%d lane%d : %d-%d %d-%d\n", rank_i, bl_i,
+ x_coordinate[L][T][channel_i][rank_i][bl_i],
+ x_coordinate[R][T][channel_i][rank_i][bl_i],
+ x_coordinate[L][B][channel_i][rank_i][bl_i],
+ x_coordinate[R][B][channel_i][rank_i][bl_i]);
+
+ tempD1 = (x_coordinate[R][T][channel_i][rank_i][bl_i] + x_coordinate[L][T][channel_i][rank_i][bl_i]) / 2; // average the TOP side LEFT & RIGHT values
+ tempD2 = (x_coordinate[R][B][channel_i][rank_i][bl_i] + x_coordinate[L][B][channel_i][rank_i][bl_i]) / 2; // average the BOTTOM side LEFT & RIGHT values
+ x_center[channel_i][rank_i][bl_i] = (uint8_t) ((tempD1 + tempD2) / 2); // average the above averages
+
+ // y_coordinate:
+ DPF(D_INFO, "VREF R/L eye lane%d : %d-%d %d-%d\n", bl_i,
+ y_coordinate[R][B][channel_i][bl_i],
+ y_coordinate[R][T][channel_i][bl_i],
+ y_coordinate[L][B][channel_i][bl_i],
+ y_coordinate[L][T][channel_i][bl_i]);
+
+ tempD1 = (y_coordinate[R][T][channel_i][bl_i] + y_coordinate[R][B][channel_i][bl_i]) / 2; // average the RIGHT side TOP & BOTTOM values
+ tempD2 = (y_coordinate[L][T][channel_i][bl_i] + y_coordinate[L][B][channel_i][bl_i]) / 2; // average the LEFT side TOP & BOTTOM values
+ y_center[channel_i][bl_i] = (uint8_t) ((tempD1 + tempD2) / 2); // average the above averages
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+
+#ifdef RX_EYE_CHECK
+ // perform an eye check
+ for (side_y=B; side_y<=T; side_y++)
+ {
+ for (side_x=L; side_x<=R; side_x++)
+ {
+
+ post_code(0x07, (0x30 + (side_y * 2) + (side_x)));
+
+ // update the settings for the eye check
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1<<channel_i))
+ {
+ for (rank_i=0; rank_i<NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1<<rank_i))
+ {
+ for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)
+ {
+ if (side_x == L)
+ {
+ set_rdqs(channel_i, rank_i, bl_i, (x_center[channel_i][rank_i][bl_i] - (MIN_RDQS_EYE / 2)));
+ }
+ else
+ {
+ set_rdqs(channel_i, rank_i, bl_i, (x_center[channel_i][rank_i][bl_i] + (MIN_RDQS_EYE / 2)));
+ }
+ if (side_y == B)
+ {
+ set_vref(channel_i, bl_i, (y_center[channel_i][bl_i] - (MIN_VREF_EYE / 2)));
+ }
+ else
+ {
+ set_vref(channel_i, bl_i, (y_center[channel_i][bl_i] + (MIN_VREF_EYE / 2)));
+ }
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+
+ // request HTE reconfiguration
+ mrc_params->hte_setup = 1;
+
+ // check the eye
+ if (check_bls_ex( mrc_params, address) & 0xFF)
+ {
+ // one or more byte lanes failed
+ post_code(0xEE, (0x74 + (side_x * 2) + (side_y)));
+ }
+ } // side_x loop
+ } // side_y loop
+#endif // RX_EYE_CHECK
+
+ post_code(0x07, 0x40);
+
+ // set final placements
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+#ifdef R2R_SHARING
+ // increment "num_ranks_enabled"
+ num_ranks_enabled++;
+#endif // R2R_SHARING
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ // x_coordinate:
+#ifdef R2R_SHARING
+ final_delay[channel_i][bl_i] += x_center[channel_i][rank_i][bl_i];
+ set_rdqs(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled));
+#else
+ set_rdqs(channel_i, rank_i, bl_i, x_center[channel_i][rank_i][bl_i]);
+#endif // R2R_SHARING
+ // y_coordinate:
+ set_vref(channel_i, bl_i, y_center[channel_i][bl_i]);
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+#endif // BACKUP_RDQS
+ LEAVEFN();
+ return;
+}
+
+// wr_train:
+// POST_CODE[major] == 0x08
+//
+// This function will perform the WRITE TRAINING Algorithm on all channels/ranks/byte_lanes simultaneously to minimize execution time.
+// The idea here is to train the WDQ timings to achieve maximum WRITE margins.
+// The algorithm will start with WDQ at the current WDQ setting (tracks WDQS in WR_LVL) +/- 32 PIs (+/- 1/4 CLK) and collapse the eye until all data patterns pass.
+// This is because WDQS will be aligned to WCLK by the Write Leveling algorithm and WDQ will only ever have a 1/2 CLK window of validity.
+static void wr_train(
+ MRCParams_t *mrc_params)
+{
+
+#define WDQ_STEP 1 // how many WDQ codes to jump while margining
+#define L 0 // LEFT side loop value definition
+#define R 1 // RIGHT side loop value definition
+
+ uint8_t channel_i; // channel counter
+ uint8_t rank_i; // rank counter
+ uint8_t bl_i; // byte lane counter
+ uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor
+#ifdef BACKUP_WDQ
+#else
+ uint8_t side_i; // LEFT/RIGHT side indicator (0=L, 1=R)
+ uint32_t tempD; // temporary DWORD
+ uint32_t delay[2/*side_i*/][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES]; // 2 arrays, for L & R side passing delays
+ uint32_t address; // target address for "check_bls_ex()"
+ uint32_t result; // result of "check_bls_ex()"
+ uint32_t bl_mask; // byte lane mask for "result" checking
+#ifdef R2R_SHARING
+ uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES]; // used to find placement for rank2rank sharing configs
+ uint32_t num_ranks_enabled = 0; // used to find placement for rank2rank sharing configs
+#endif // R2R_SHARING
+#endif // BACKUP_WDQ
+
+ // wr_train starts
+ post_code(0x08, 0x00);
+
+ ENTERFN();
+
+#ifdef BACKUP_WDQ
+ for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1<<channel_i))
+ {
+ for (rank_i=0; rank_i<NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1<<rank_i))
+ {
+ for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)
+ {
+ set_wdq(channel_i, rank_i, bl_i, ddr_wdq[PLATFORM_ID]);
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+#else
+ // initialise "delay"
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ // want to start with WDQ = (WDQS - QRTR_CLK) +/- QRTR_CLK
+ tempD = get_wdqs(channel_i, rank_i, bl_i) - QRTR_CLK;
+ delay[L][channel_i][rank_i][bl_i] = tempD - QRTR_CLK;
+ delay[R][channel_i][rank_i][bl_i] = tempD + QRTR_CLK;
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+
+ // initialise other variables
+ bl_mask = byte_lane_mask(mrc_params);
+ address = get_addr(mrc_params, 0, 0);
+
+#ifdef R2R_SHARING
+ // need to set "final_delay[][]" elements to "0"
+ memset((void *) (final_delay), 0x00, (size_t) sizeof(final_delay));
+#endif // R2R_SHARING
+
+ // start algorithm on the LEFT side and train each channel/bl until no failures are observed, then repeat for the RIGHT side.
+ for (side_i = L; side_i <= R; side_i++)
+ {
+ post_code(0x08, (0x10 + (side_i)));
+
+ // set starting values
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ set_wdq(channel_i, rank_i, bl_i, delay[side_i][channel_i][rank_i][bl_i]);
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+
+ // find passing values
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (0x1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (0x1 << rank_i))
+ {
+ // get an address in the target channel/rank
+ address = get_addr(mrc_params, channel_i, rank_i);
+
+ // request HTE reconfiguration
+ mrc_params->hte_setup = 1;
+
+ // check the settings
+ do
+ {
+
+#ifdef SIM
+ // need restore memory to idle state as write can be in bad sync
+ dram_init_command (DCMD_PREA(rank_i));
+#endif
+
+ // result[07:00] == failing byte lane (MAX 8)
+ result = check_bls_ex( mrc_params, address);
+ // check for failures
+ if (result & 0xFF)
+ {
+ // at least 1 byte lane failed
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ if (result & (bl_mask << bl_i))
+ {
+ if (side_i == L)
+ {
+ delay[L][channel_i][rank_i][bl_i] += WDQ_STEP;
+ }
+ else
+ {
+ delay[R][channel_i][rank_i][bl_i] -= WDQ_STEP;
+ }
+ // check for algorithm failure
+ if (delay[L][channel_i][rank_i][bl_i] != delay[R][channel_i][rank_i][bl_i])
+ {
+ // margin available, update delay setting
+ set_wdq(channel_i, rank_i, bl_i, delay[side_i][channel_i][rank_i][bl_i]);
+ }
+ else
+ {
+ // no margin available, notify the user and halt
+ training_message(channel_i, rank_i, bl_i);
+ post_code(0xEE, (0x80 + side_i));
+ }
+ } // if bl_i failed
+ } // bl_i loop
+ } // at least 1 byte lane failed
+ } while (result & 0xFF); // stop when all byte lanes pass
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+ } // side_i loop
+
+ // program WDQ to the middle of passing window
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+#ifdef R2R_SHARING
+ // increment "num_ranks_enabled"
+ num_ranks_enabled++;
+#endif // R2R_SHARING
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+
+ DPF(D_INFO, "WDQ eye rank%d lane%d : %d-%d\n", rank_i, bl_i,
+ delay[L][channel_i][rank_i][bl_i],
+ delay[R][channel_i][rank_i][bl_i]);
+
+ tempD = (delay[R][channel_i][rank_i][bl_i] + delay[L][channel_i][rank_i][bl_i]) / 2;
+
+#ifdef R2R_SHARING
+ final_delay[channel_i][bl_i] += tempD;
+ set_wdq(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled));
+#else
+ set_wdq(channel_i, rank_i, bl_i, tempD);
+#endif // R2R_SHARING
+
+ } // bl_i loop
+ } // if rank is enabled
+ } // rank_i loop
+ } // if channel is enabled
+ } // channel_i loop
+#endif // BACKUP_WDQ
+ LEAVEFN();
+ return;
+}
+
+// Wrapper for jedec initialisation routine
+static void perform_jedec_init(
+ MRCParams_t *mrc_params)
+{
+ jedec_init(mrc_params, 0);
+}
+
+// Configure DDRPHY for Auto-Refresh, Periodic Compensations,
+// Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down
+static void set_auto_refresh(
+ MRCParams_t *mrc_params)
+{
+ uint32_t channel_i;
+ uint32_t rank_i;
+ uint32_t bl_i;
+ uint32_t bl_divisor = /*(mrc_params->channel_width==x16)?2:*/1;
+ uint32_t tempD;
+
+ ENTERFN();
+
+ // enable Auto-Refresh, Periodic Compensations, Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ // Enable Periodic RCOMPS
+ isbM32m(DDRPHY, CMPCTRL, (BIT1), (BIT1));
+
+
+ // Enable Dynamic DiffAmp & Set Read ODT Value
+ switch (mrc_params->rd_odt_value)
+ {
+ case 0: tempD = 0x3F; break; // OFF
+ default: tempD = 0x00; break; // Auto
+ } // rd_odt_value switch
+
+ for (bl_i=0; bl_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_i++)
+ {
+ isbM32m(DDRPHY, (B0OVRCTL + (bl_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)),
+ ((0x00<<16)|(tempD<<10)),
+ ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10))); // Override: DIFFAMP, ODT
+
+ isbM32m(DDRPHY, (B1OVRCTL + (bl_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)),
+ ((0x00<<16)|(tempD<<10)),
+ ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10)));// Override: DIFFAMP, ODT
+ } // bl_i loop
+
+ // Issue ZQCS command
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+ dram_init_command(DCMD_ZQCS(rank_i));
+ } // if rank_i enabled
+ } // rank_i loop
+
+ } // if channel_i enabled
+ } // channel_i loop
+
+ clear_pointers();
+
+ LEAVEFN();
+ return;
+}
+
+// Depending on configuration enables ECC support.
+// Available memory size is decresed, and updated with 0s
+// in order to clear error status. Address mode 2 forced.
+static void ecc_enable(
+ MRCParams_t *mrc_params)
+{
+ RegDRP Drp;
+ RegDSCH Dsch;
+ RegDECCCTRL Ctr;
+
+ if (mrc_params->ecc_enables == 0) return;
+
+ ENTERFN();
+
+ // Configuration required in ECC mode
+ Drp.raw = isbR32m(MCU, DRP);
+ Drp.field.addressMap = 2;
+ Drp.field.split64 = 1;
+ isbW32m(MCU, DRP, Drp.raw);
+
+ // Disable new request bypass
+ Dsch.raw = isbR32m(MCU, DSCH);
+ Dsch.field.NEWBYPDIS = 1;
+ isbW32m(MCU, DSCH, Dsch.raw);
+
+ // Enable ECC
+ Ctr.raw = 0;
+ Ctr.field.SBEEN = 1;
+ Ctr.field.DBEEN = 1;
+ Ctr.field.ENCBGEN = 1;
+ isbW32m(MCU, DECCCTRL, Ctr.raw);
+
+#ifdef SIM
+ // Read back to be sure writing took place
+ Ctr.raw = isbR32m(MCU, DECCCTRL);
+#endif
+
+ // Assume 8 bank memory, one bank is gone for ECC
+ mrc_params->mem_size -= mrc_params->mem_size / 8;
+
+ // For S3 resume memory content has to be preserved
+ if (mrc_params->boot_mode != bmS3)
+ {
+ select_hte(mrc_params);
+ HteMemInit(mrc_params, MrcMemInit, MrcHaltHteEngineOnError);
+ select_memory_manager(mrc_params);
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// Lock MCU registers at the end of initialisation sequence.
+static void lock_registers(
+ MRCParams_t *mrc_params)
+{
+ RegDCO Dco;
+
+ ENTERFN();
+
+ Dco.raw = isbR32m(MCU, DCO);
+ Dco.field.PMIDIS = 0; //0 - PRI enabled
+ Dco.field.PMICTL = 0; //0 - PRI owned by MEMORY_MANAGER
+ Dco.field.DRPLOCK = 1;
+ Dco.field.REUTLOCK = 1;
+ isbW32m(MCU, DCO, Dco.raw);
+
+ LEAVEFN();
+
+}
+
+#ifdef MRC_SV
+
+// cache write back invalidate
+static void asm_wbinvd(void)
+{
+#if defined (SIM) || defined (GCC)
+ asm(
+ "wbinvd;"
+ );
+#else
+ __asm wbinvd;
+#endif
+}
+
+// cache invalidate
+static void asm_invd(void)
+{
+#if defined (SIM) || defined (GCC)
+ asm(
+ "invd;"
+ );
+#else
+ __asm invd;
+#endif
+}
+
+
+static void cpu_read(void)
+{
+ uint32_t adr, dat, limit;
+
+ asm_invd();
+
+ limit = 8 * 1024;
+ for (adr = 0; adr < limit; adr += 4)
+ {
+ dat = *(uint32_t*) adr;
+ if ((adr & 0x0F) == 0)
+ {
+ DPF(D_INFO, "\n%x : ", adr);
+ }
+ DPF(D_INFO, "%x ", dat);
+ }
+ DPF(D_INFO, "\n");
+
+ DPF(D_INFO, "CPU read done\n");
+}
+
+
+static void cpu_write(void)
+{
+ uint32_t adr, limit;
+
+ limit = 8 * 1024;
+ for (adr = 0; adr < limit; adr += 4)
+ {
+ *(uint32_t*) adr = 0xDEAD0000 + adr;
+ }
+
+ asm_wbinvd();
+
+ DPF(D_INFO, "CPU write done\n");
+}
+
+
+static void cpu_memory_test(
+ MRCParams_t *mrc_params)
+{
+ uint32_t result = 0;
+ uint32_t val, dat, adr, adr0, step, limit;
+ uint64_t my_tsc;
+
+ ENTERFN();
+
+ asm_invd();
+
+ adr0 = 1 * 1024 * 1024;
+ limit = 256 * 1024 * 1024;
+
+ for (step = 0; step <= 4; step++)
+ {
+ DPF(D_INFO, "Mem test step %d starting from %xh\n", step, adr0);
+
+ my_tsc = read_tsc();
+ for (adr = adr0; adr < limit; adr += sizeof(uint32_t))
+ {
+ if (step == 0) dat = adr;
+ else if (step == 1) dat = (1 << ((adr >> 2) & 0x1f));
+ else if (step == 2) dat = ~(1 << ((adr >> 2) & 0x1f));
+ else if (step == 3) dat = 0x5555AAAA;
+ else if (step == 4) dat = 0xAAAA5555;
+
+ *(uint32_t*) adr = dat;
+ }
+ DPF(D_INFO, "Write time %llXh\n", read_tsc() - my_tsc);
+
+ my_tsc = read_tsc();
+ for (adr = adr0; adr < limit; adr += sizeof(uint32_t))
+ {
+ if (step == 0) dat = adr;
+ else if (step == 1) dat = (1 << ((adr >> 2) & 0x1f));
+ else if (step == 2) dat = ~(1 << ((adr >> 2) & 0x1f));
+ else if (step == 3) dat = 0x5555AAAA;
+ else if (step == 4) dat = 0xAAAA5555;
+
+ val = *(uint32_t*) adr;
+
+ if (val != dat)
+ {
+ DPF(D_INFO, "%x vs. %x@%x\n", dat, val, adr);
+ result = adr|BIT31;
+ }
+ }
+ DPF(D_INFO, "Read time %llXh\n", read_tsc() - my_tsc);
+ }
+
+ DPF( D_INFO, "Memory test result %x\n", result);
+ LEAVEFN();
+}
+#endif // MRC_SV
+
+
+// Execute memory test, if error dtected it is
+// indicated in mrc_params->status.
+static void memory_test(
+ MRCParams_t *mrc_params)
+{
+ uint32_t result = 0;
+
+ ENTERFN();
+
+ select_hte(mrc_params);
+ result = HteMemInit(mrc_params, MrcMemTest, MrcHaltHteEngineOnError);
+ select_memory_manager(mrc_params);
+
+ DPF(D_INFO, "Memory test result %x\n", result);
+ mrc_params->status = ((result == 0) ? MRC_SUCCESS : MRC_E_MEMTEST);
+ LEAVEFN();
+}
+
+
+// Force same timings as with backup settings
+static void static_timings(
+ MRCParams_t *mrc_params)
+
+{
+ uint8_t ch, rk, bl;
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++)
+ {
+ for (rk = 0; rk < NUM_RANKS; rk++)
+ {
+ for (bl = 0; bl < NUM_BYTE_LANES; bl++)
+ {
+ set_rcvn(ch, rk, bl, 498); // RCVN
+ set_rdqs(ch, rk, bl, 24); // RDQS
+ set_wdqs(ch, rk, bl, 292); // WDQS
+ set_wdq( ch, rk, bl, 260); // WDQ
+ if (rk == 0)
+ {
+ set_vref(ch, bl, 32); // VREF (RANK0 only)
+ }
+ }
+ set_wctl(ch, rk, 217); // WCTL
+ }
+ set_wcmd(ch, 220); // WCMD
+ }
+
+ return;
+}
+
+//
+// Initialise system memory.
+//
+void MemInit(
+ MRCParams_t *mrc_params)
+{
+ static const MemInit_t init[] =
+ {
+ { 0x0101, bmCold|bmFast|bmWarm|bmS3, clear_self_refresh }, //0
+ { 0x0200, bmCold|bmFast|bmWarm|bmS3, prog_ddr_timing_control }, //1 initialise the MCU
+ { 0x0103, bmCold|bmFast , prog_decode_before_jedec }, //2
+ { 0x0104, bmCold|bmFast , perform_ddr_reset }, //3
+ { 0x0300, bmCold|bmFast |bmS3, ddrphy_init }, //4 initialise the DDRPHY
+ { 0x0400, bmCold|bmFast , perform_jedec_init }, //5 perform JEDEC initialisation of DRAMs
+ { 0x0105, bmCold|bmFast , set_ddr_init_complete }, //6
+ { 0x0106, bmFast|bmWarm|bmS3, restore_timings }, //7
+ { 0x0106, bmCold , default_timings }, //8
+ { 0x0500, bmCold , rcvn_cal }, //9 perform RCVN_CAL algorithm
+ { 0x0600, bmCold , wr_level }, //10 perform WR_LEVEL algorithm
+ { 0x0120, bmCold , prog_page_ctrl }, //11
+ { 0x0700, bmCold , rd_train }, //12 perform RD_TRAIN algorithm
+ { 0x0800, bmCold , wr_train }, //13 perform WR_TRAIN algorithm
+ { 0x010B, bmCold , store_timings }, //14
+ { 0x010C, bmCold|bmFast|bmWarm|bmS3, enable_scrambling }, //15
+ { 0x010D, bmCold|bmFast|bmWarm|bmS3, prog_ddr_control }, //16
+ { 0x010E, bmCold|bmFast|bmWarm|bmS3, prog_dra_drb }, //17
+ { 0x010F, bmWarm|bmS3, perform_wake }, //18
+ { 0x0110, bmCold|bmFast|bmWarm|bmS3, change_refresh_period }, //19
+ { 0x0111, bmCold|bmFast|bmWarm|bmS3, set_auto_refresh }, //20
+ { 0x0112, bmCold|bmFast|bmWarm|bmS3, ecc_enable }, //21
+ { 0x0113, bmCold|bmFast , memory_test }, //22
+ { 0x0114, bmCold|bmFast|bmWarm|bmS3, lock_registers } //23 set init done
+ };
+
+ uint32_t i;
+
+ ENTERFN();
+
+ DPF(D_INFO, "Meminit build %s %s\n", __DATE__, __TIME__);
+
+ // MRC started
+ post_code(0x01, 0x00);
+
+ if (mrc_params->boot_mode != bmCold)
+ {
+ if (mrc_params->ddr_speed != mrc_params->timings.ddr_speed)
+ {
+ // full training required as frequency changed
+ mrc_params->boot_mode = bmCold;
+ }
+ }
+
+ for (i = 0; i < MCOUNT(init); i++)
+ {
+ uint64_t my_tsc;
+
+#ifdef MRC_SV
+ if (mrc_params->menu_after_mrc && i > 14)
+ {
+ uint8_t ch;
+
+ mylop:
+
+ DPF(D_INFO, "-- c - continue --\n");
+ DPF(D_INFO, "-- j - move to jedec init --\n");
+ DPF(D_INFO, "-- m - memory test --\n");
+ DPF(D_INFO, "-- r - cpu read --\n");
+ DPF(D_INFO, "-- w - cpu write --\n");
+ DPF(D_INFO, "-- b - hte base test --\n");
+ DPF(D_INFO, "-- g - hte extended test --\n");
+
+ ch = mgetc();
+ switch (ch)
+ {
+ case 'c':
+ break;
+ case 'j': //move to jedec init
+ i = 5;
+ break;
+
+ case 'M':
+ case 'N':
+ {
+ uint32_t n, res, cnt=0;
+
+ for(n=0; mgetch()==0; n++)
+ {
+ if( ch == 'M' || n % 256 == 0)
+ {
+ DPF(D_INFO, "n=%d e=%d\n", n, cnt);
+ }
+
+ res = 0;
+
+ if( ch == 'M')
+ {
+ memory_test(mrc_params);
+ res |= mrc_params->status;
+ }
+
+ mrc_params->hte_setup = 1;
+ res |= check_bls_ex(mrc_params, 0x00000000);
+ res |= check_bls_ex(mrc_params, 0x00000000);
+ res |= check_bls_ex(mrc_params, 0x00000000);
+ res |= check_bls_ex(mrc_params, 0x00000000);
+
+ if( mrc_params->rank_enables & 2)
+ {
+ mrc_params->hte_setup = 1;
+ res |= check_bls_ex(mrc_params, 0x40000000);
+ res |= check_bls_ex(mrc_params, 0x40000000);
+ res |= check_bls_ex(mrc_params, 0x40000000);
+ res |= check_bls_ex(mrc_params, 0x40000000);
+ }
+
+ if( res != 0)
+ {
+ DPF(D_INFO, "###########\n");
+ DPF(D_INFO, "#\n");
+ DPF(D_INFO, "# Error count %d\n", ++cnt);
+ DPF(D_INFO, "#\n");
+ DPF(D_INFO, "###########\n");
+ }
+
+ } // for
+
+ select_memory_manager(mrc_params);
+ }
+ goto mylop;
+ case 'm':
+ memory_test(mrc_params);
+ goto mylop;
+ case 'n':
+ cpu_memory_test(mrc_params);
+ goto mylop;
+
+ case 'l':
+ ch = mgetc();
+ if (ch <= '9') DpfPrintMask ^= (ch - '0') << 3;
+ DPF(D_INFO, "Log mask %x\n", DpfPrintMask);
+ goto mylop;
+ case 'p':
+ print_timings(mrc_params);
+ goto mylop;
+ case 'R':
+ rd_train(mrc_params);
+ goto mylop;
+ case 'W':
+ wr_train(mrc_params);
+ goto mylop;
+
+ case 'r':
+ cpu_read();
+ goto mylop;
+ case 'w':
+ cpu_write();
+ goto mylop;
+
+ case 'g':
+ {
+ uint32_t result;
+ select_hte(mrc_params);
+ mrc_params->hte_setup = 1;
+ result = check_bls_ex(mrc_params, 0);
+ DPF(D_INFO, "Extended test result %x\n", result);
+ select_memory_manager(mrc_params);
+ }
+ goto mylop;
+ case 'b':
+ {
+ uint32_t result;
+ select_hte(mrc_params);
+ mrc_params->hte_setup = 1;
+ result = check_rw_coarse(mrc_params, 0);
+ DPF(D_INFO, "Base test result %x\n", result);
+ select_memory_manager(mrc_params);
+ }
+ goto mylop;
+ case 'B':
+ select_hte(mrc_params);
+ HteMemOp(0x2340, 1, 1);
+ select_memory_manager(mrc_params);
+ goto mylop;
+
+ case '3':
+ {
+ RegDPMC0 DPMC0reg;
+
+ DPF( D_INFO, "===>> Start suspend\n");
+ isbR32m(MCU, DSTAT);
+
+ DPMC0reg.raw = isbR32m(MCU, DPMC0);
+ DPMC0reg.field.DYNSREN = 0;
+ DPMC0reg.field.powerModeOpCode = 0x05; // Disable Master DLL
+ isbW32m(MCU, DPMC0, DPMC0reg.raw);
+
+ // Should be off for negative test case verification
+ #if 1
+ Wr32(MMIO, PCIADDR(0,0,0,SB_PACKET_REG),
+ (uint32_t)SB_COMMAND(SB_SUSPEND_CMND_OPCODE, MCU, 0));
+ #endif
+
+ DPF( D_INFO, "press key\n");
+ mgetc();
+ DPF( D_INFO, "===>> Start resume\n");
+ isbR32m(MCU, DSTAT);
+
+ mrc_params->boot_mode = bmS3;
+ i = 0;
+ }
+
+ } // switch
+
+ } // if( menu
+#endif //MRC_SV
+
+ if (mrc_params->boot_mode & init[i].boot_path)
+ {
+ uint8_t major = init[i].post_code >> 8 & 0xFF;
+ uint8_t minor = init[i].post_code >> 0 & 0xFF;
+ post_code(major, minor);
+
+ my_tsc = read_tsc();
+ init[i].init_fn(mrc_params);
+ DPF(D_TIME, "Execution time %llX", read_tsc() - my_tsc);
+ }
+ }
+
+ // display the timings
+ print_timings(mrc_params);
+
+ // MRC is complete.
+ post_code(0x01, 0xFF);
+
+ LEAVEFN();
+ return;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.h
new file mode 100755
index 0000000..b8b0c44
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.h
@@ -0,0 +1,46 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************/
+#ifndef _MEMINIT_H_
+#define _MEMINIT_H_
+
+// function prototypes
+void MemInit(MRCParams_t *mrc_params);
+
+typedef void (*MemInitFn_t)(MRCParams_t *mrc_params);
+
+typedef struct MemInit_s {
+ uint16_t post_code;
+ uint16_t boot_path;
+ MemInitFn_t init_fn;
+} MemInit_t;
+
+#endif // _MEMINIT_H_
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.c
new file mode 100755
index 0000000..838f066
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.c
@@ -0,0 +1,1598 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ***************************************************************************/
+
+#include "mrc.h"
+#include "memory_options.h"
+
+#include "meminit_utils.h"
+#include "hte.h"
+#include "io.h"
+
+void select_hte(
+ MRCParams_t *mrc_params);
+
+static uint8_t first_run = 0;
+
+const uint8_t vref_codes[64] =
+{ // lowest to highest
+ 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, // 00 - 15
+ 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, // 16 - 31
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 32 - 47
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 48 - 63
+};
+
+#ifdef EMU
+// Track current post code for debugging purpose
+uint32_t PostCode;
+#endif
+
+// set_rcvn:
+//
+// This function will program the RCVEN delays.
+// (currently doesn't comprehend rank)
+void set_rcvn(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane,
+ uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t tempD;
+
+ ENTERFN();
+ DPF(D_TRN, "Rcvn ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);
+
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
+ // BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
+ reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ msk = (byte_lane & BIT0) ? (BIT23 | BIT22 | BIT21 | BIT20) : (BIT11 | BIT10 | BIT9 | BIT8);
+ tempD = (byte_lane & BIT0) ? ((pi_count / HALF_CLK) << 20) : ((pi_count / HALF_CLK) << 8);
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // Adjust PI_COUNT
+ pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
+ // BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
+ reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
+ msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+ tempD = pi_count << 24;
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // DEADBAND
+ // BL0/1 -> B01DBCTL1[08/11] (+1 select)
+ // BL0/1 -> B01DBCTL1[02/05] (enable)
+ reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ msk = 0x00;
+ tempD = 0x00;
+ // enable
+ msk |= (byte_lane & BIT0) ? (BIT5) : (BIT2);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ {
+ tempD |= msk;
+ }
+ // select
+ msk |= (byte_lane & BIT0) ? (BIT11) : (BIT8);
+ if (pi_count < EARLY_DB)
+ {
+ tempD |= msk;
+ }
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // error check
+ if (pi_count > 0x3F)
+ {
+ training_message(channel, rank, byte_lane);
+ post_code(0xEE, 0xE0);
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// get_rcvn:
+//
+// This function will return the current RCVEN delay on the given channel, rank, byte_lane as an absolute PI count.
+// (currently doesn't comprehend rank)
+uint32_t get_rcvn(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane)
+{
+ uint32_t reg;
+ uint32_t tempD;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
+ // BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
+ reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= (byte_lane & BIT0) ? (20) : (8);
+ tempD &= 0xF;
+
+ // Adjust PI_COUNT
+ pi_count = tempD * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
+ // BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
+ reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= 24;
+ tempD &= 0x3F;
+
+ // Adjust PI_COUNT
+ pi_count += tempD;
+
+ LEAVEFN();
+ return pi_count;
+}
+
+// set_rdqs:
+//
+// This function will program the RDQS delays based on an absolute amount of PIs.
+// (currently doesn't comprehend rank)
+void set_rdqs(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane,
+ uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t tempD;
+
+ ENTERFN();
+ DPF(D_TRN, "Rdqs ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);
+
+ // PI (1/128 MCLK)
+ // BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
+ // BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
+ reg = (byte_lane & BIT0) ? (B1RXDQSPICODE) : (B0RXDQSPICODE);
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
+ msk = (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
+ tempD = pi_count << 0;
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // error check (shouldn't go above 0x3F)
+ if (pi_count > 0x47)
+ {
+ training_message(channel, rank, byte_lane);
+ post_code(0xEE, 0xE1);
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// get_rdqs:
+//
+// This function will return the current RDQS delay on the given channel, rank, byte_lane as an absolute PI count.
+// (currently doesn't comprehend rank)
+uint32_t get_rdqs(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane)
+{
+ uint32_t reg;
+ uint32_t tempD;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ // PI (1/128 MCLK)
+ // BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
+ // BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
+ reg = (byte_lane & BIT0) ? (B1RXDQSPICODE) : (B0RXDQSPICODE);
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
+ tempD = isbR32m(DDRPHY, reg);
+
+ // Adjust PI_COUNT
+ pi_count = tempD & 0x7F;
+
+ LEAVEFN();
+ return pi_count;
+}
+
+// set_wdqs:
+//
+// This function will program the WDQS delays based on an absolute amount of PIs.
+// (currently doesn't comprehend rank)
+void set_wdqs(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane,
+ uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t tempD;
+
+ ENTERFN();
+ DPF(D_TRN, "Wdqs ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);
+
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
+ // BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
+ reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ msk = (byte_lane & BIT0) ? (BIT19 | BIT18 | BIT17 | BIT16) : (BIT7 | BIT6 | BIT5 | BIT4);
+ tempD = pi_count / HALF_CLK;
+ tempD <<= (byte_lane & BIT0) ? (16) : (4);
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // Adjust PI_COUNT
+ pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
+ // BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
+ reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
+ msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16);
+ tempD = pi_count << 16;
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // DEADBAND
+ // BL0/1 -> B01DBCTL1[07/10] (+1 select)
+ // BL0/1 -> B01DBCTL1[01/04] (enable)
+ reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ msk = 0x00;
+ tempD = 0x00;
+ // enable
+ msk |= (byte_lane & BIT0) ? (BIT4) : (BIT1);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ {
+ tempD |= msk;
+ }
+ // select
+ msk |= (byte_lane & BIT0) ? (BIT10) : (BIT7);
+ if (pi_count < EARLY_DB)
+ {
+ tempD |= msk;
+ }
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // error check
+ if (pi_count > 0x3F)
+ {
+ training_message(channel, rank, byte_lane);
+ post_code(0xEE, 0xE2);
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// get_wdqs:
+//
+// This function will return the amount of WDQS delay on the given channel, rank, byte_lane as an absolute PI count.
+// (currently doesn't comprehend rank)
+uint32_t get_wdqs(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane)
+{
+ uint32_t reg;
+ uint32_t tempD;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
+ // BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
+ reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= (byte_lane & BIT0) ? (16) : (4);
+ tempD &= 0xF;
+
+ // Adjust PI_COUNT
+ pi_count = (tempD * HALF_CLK);
+
+ // PI (1/64 MCLK, 1 PIs)
+ // BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
+ // BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
+ reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= 16;
+ tempD &= 0x3F;
+
+ // Adjust PI_COUNT
+ pi_count += tempD;
+
+ LEAVEFN();
+ return pi_count;
+}
+
+// set_wdq:
+//
+// This function will program the WDQ delays based on an absolute number of PIs.
+// (currently doesn't comprehend rank)
+void set_wdq(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane,
+ uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t tempD;
+
+ ENTERFN();
+ DPF(D_TRN, "Wdq ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);
+
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
+ // BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
+ reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ msk = (byte_lane & BIT0) ? (BIT15 | BIT14 | BIT13 | BIT12) : (BIT3 | BIT2 | BIT1 | BIT0);
+ tempD = pi_count / HALF_CLK;
+ tempD <<= (byte_lane & BIT0) ? (12) : (0);
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // Adjust PI_COUNT
+ pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
+ // BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
+ reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
+ msk = (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
+ tempD = pi_count << 8;
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // DEADBAND
+ // BL0/1 -> B01DBCTL1[06/09] (+1 select)
+ // BL0/1 -> B01DBCTL1[00/03] (enable)
+ reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ msk = 0x00;
+ tempD = 0x00;
+ // enable
+ msk |= (byte_lane & BIT0) ? (BIT3) : (BIT0);
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ {
+ tempD |= msk;
+ }
+ // select
+ msk |= (byte_lane & BIT0) ? (BIT9) : (BIT6);
+ if (pi_count < EARLY_DB)
+ {
+ tempD |= msk;
+ }
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // error check
+ if (pi_count > 0x3F)
+ {
+ training_message(channel, rank, byte_lane);
+ post_code(0xEE, 0xE3);
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// get_wdq:
+//
+// This function will return the amount of WDQ delay on the given channel, rank, byte_lane as an absolute PI count.
+// (currently doesn't comprehend rank)
+uint32_t get_wdq(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane)
+{
+ uint32_t reg;
+ uint32_t tempD;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
+ // BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
+ reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= (byte_lane & BIT0) ? (12) : (0);
+ tempD &= 0xF;
+
+ // Adjust PI_COUNT
+ pi_count = (tempD * HALF_CLK);
+
+ // PI (1/64 MCLK, 1 PIs)
+ // BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
+ // BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
+ reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
+ reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= 8;
+ tempD &= 0x3F;
+
+ // Adjust PI_COUNT
+ pi_count += tempD;
+
+ LEAVEFN();
+ return pi_count;
+}
+
+// set_wcmd:
+//
+// This function will program the WCMD delays based on an absolute number of PIs.
+void set_wcmd(
+ uint8_t channel,
+ uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t tempD;
+
+ ENTERFN();
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // CMDPTRREG[11:08] (0x0-0xF)
+ reg = CMDPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+ msk = (BIT11 | BIT10 | BIT9 | BIT8);
+ tempD = pi_count / HALF_CLK;
+ tempD <<= 8;
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // Adjust PI_COUNT
+ pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
+ // CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
+ // CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
+ // CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
+ // CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
+ // CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
+ // CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
+ // CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
+ reg = CMDDLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
+
+ msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24) | (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+ | (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8) | (BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
+
+ tempD = (pi_count << 24) | (pi_count << 16) | (pi_count << 8) | (pi_count << 0);
+
+ isbM32m(DDRPHY, reg, tempD, msk);
+ reg = CMDDLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET); // PO
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // DEADBAND
+ // CMDCFGREG0[17] (+1 select)
+ // CMDCFGREG0[16] (enable)
+ reg = CMDCFGREG0 + (channel * DDRIOCCC_CH_OFFSET);
+ msk = 0x00;
+ tempD = 0x00;
+ // enable
+ msk |= BIT16;
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ {
+ tempD |= msk;
+ }
+ // select
+ msk |= BIT17;
+ if (pi_count < EARLY_DB)
+ {
+ tempD |= msk;
+ }
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // error check
+ if (pi_count > 0x3F)
+ {
+ post_code(0xEE, 0xE4);
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// get_wcmd:
+//
+// This function will return the amount of WCMD delay on the given channel as an absolute PI count.
+uint32_t get_wcmd(
+ uint8_t channel)
+{
+ uint32_t reg;
+ uint32_t tempD;
+ uint32_t pi_count;
+
+ ENTERFN();
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // CMDPTRREG[11:08] (0x0-0xF)
+ reg = CMDPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= 8;
+ tempD &= 0xF;
+
+ // Adjust PI_COUNT
+ pi_count = tempD * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
+ // CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
+ // CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
+ // CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
+ // CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
+ // CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
+ // CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
+ // CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
+ reg = CMDDLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= 16;
+ tempD &= 0x3F;
+
+ // Adjust PI_COUNT
+ pi_count += tempD;
+
+ LEAVEFN();
+ return pi_count;
+}
+
+// set_wclk:
+//
+// This function will program the WCLK delays based on an absolute number of PIs.
+void set_wclk(
+ uint8_t channel,
+ uint8_t rank,
+ uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t tempD;
+
+ ENTERFN();
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // CCPTRREG[15:12] -> CLK1 (0x0-0xF)
+ // CCPTRREG[11:08] -> CLK0 (0x0-0xF)
+ reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+ msk = (BIT15 | BIT14 | BIT13 | BIT12) | (BIT11 | BIT10 | BIT9 | BIT8);
+ tempD = ((pi_count / HALF_CLK) << 12) | ((pi_count / HALF_CLK) << 8);
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // Adjust PI_COUNT
+ pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
+ // ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
+ reg = (rank) ? (ECCB1DLLPICODER0) : (ECCB1DLLPICODER0);
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16) | (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
+ tempD = (pi_count << 16) | (pi_count << 8);
+ isbM32m(DDRPHY, reg, tempD, msk);
+ reg = (rank) ? (ECCB1DLLPICODER1) : (ECCB1DLLPICODER1);
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ isbM32m(DDRPHY, reg, tempD, msk);
+ reg = (rank) ? (ECCB1DLLPICODER2) : (ECCB1DLLPICODER2);
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ isbM32m(DDRPHY, reg, tempD, msk);
+ reg = (rank) ? (ECCB1DLLPICODER3) : (ECCB1DLLPICODER3);
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // DEADBAND
+ // CCCFGREG1[11:08] (+1 select)
+ // CCCFGREG1[03:00] (enable)
+ reg = CCCFGREG1 + (channel * DDRIOCCC_CH_OFFSET);
+ msk = 0x00;
+ tempD = 0x00;
+ // enable
+ msk |= (BIT3 | BIT2 | BIT1 | BIT0); // only ??? matters
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ {
+ tempD |= msk;
+ }
+ // select
+ msk |= (BIT11 | BIT10 | BIT9 | BIT8); // only ??? matters
+ if (pi_count < EARLY_DB)
+ {
+ tempD |= msk;
+ }
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // error check
+ if (pi_count > 0x3F)
+ {
+ post_code(0xEE, 0xE5);
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// get_wclk:
+//
+// This function will return the amout of WCLK delay on the given channel, rank as an absolute PI count.
+uint32_t get_wclk(
+ uint8_t channel,
+ uint8_t rank)
+{
+ uint32_t reg;
+ uint32_t tempD;
+ uint32_t pi_count;
+
+ ENTERFN();
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // CCPTRREG[15:12] -> CLK1 (0x0-0xF)
+ // CCPTRREG[11:08] -> CLK0 (0x0-0xF)
+ reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= (rank) ? (12) : (8);
+ tempD &= 0xF;
+
+ // Adjust PI_COUNT
+ pi_count = tempD * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
+ // ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
+ reg = (rank) ? (ECCB1DLLPICODER0) : (ECCB1DLLPICODER0);
+ reg += (channel * DDRIOCCC_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= (rank) ? (16) : (8);
+ tempD &= 0x3F;
+
+ pi_count += tempD;
+
+ LEAVEFN();
+ return pi_count;
+}
+
+// set_wctl:
+//
+// This function will program the WCTL delays based on an absolute number of PIs.
+// (currently doesn't comprehend rank)
+void set_wctl(
+ uint8_t channel,
+ uint8_t rank,
+ uint32_t pi_count)
+{
+ uint32_t reg;
+ uint32_t msk;
+ uint32_t tempD;
+
+ ENTERFN();
+
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // CCPTRREG[31:28] (0x0-0xF)
+ // CCPTRREG[27:24] (0x0-0xF)
+ reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+ msk = (BIT31 | BIT30 | BIT29 | BIT28) | (BIT27 | BIT26 | BIT25 | BIT24);
+ tempD = ((pi_count / HALF_CLK) << 28) | ((pi_count / HALF_CLK) << 24);
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // Adjust PI_COUNT
+ pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+ // ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+ reg = ECCB1DLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);
+ msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+ tempD = (pi_count << 24);
+ isbM32m(DDRPHY, reg, tempD, msk);
+ reg = ECCB1DLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
+ isbM32m(DDRPHY, reg, tempD, msk);
+ reg = ECCB1DLLPICODER2 + (channel * DDRIOCCC_CH_OFFSET);
+ isbM32m(DDRPHY, reg, tempD, msk);
+ reg = ECCB1DLLPICODER3 + (channel * DDRIOCCC_CH_OFFSET);
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // DEADBAND
+ // CCCFGREG1[13:12] (+1 select)
+ // CCCFGREG1[05:04] (enable)
+ reg = CCCFGREG1 + (channel * DDRIOCCC_CH_OFFSET);
+ msk = 0x00;
+ tempD = 0x00;
+ // enable
+ msk |= (BIT5 | BIT4); // only ??? matters
+ if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+ {
+ tempD |= msk;
+ }
+ // select
+ msk |= (BIT13 | BIT12); // only ??? matters
+ if (pi_count < EARLY_DB)
+ {
+ tempD |= msk;
+ }
+ isbM32m(DDRPHY, reg, tempD, msk);
+
+ // error check
+ if (pi_count > 0x3F)
+ {
+ post_code(0xEE, 0xE6);
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// get_wctl:
+//
+// This function will return the amount of WCTL delay on the given channel, rank as an absolute PI count.
+// (currently doesn't comprehend rank)
+uint32_t get_wctl(
+ uint8_t channel,
+ uint8_t rank)
+{
+ uint32_t reg;
+ uint32_t tempD;
+ uint32_t pi_count;
+
+ ENTERFN();
+
+ // RDPTR (1/2 MCLK, 64 PIs)
+ // CCPTRREG[31:28] (0x0-0xF)
+ // CCPTRREG[27:24] (0x0-0xF)
+ reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= 24;
+ tempD &= 0xF;
+
+ // Adjust PI_COUNT
+ pi_count = tempD * HALF_CLK;
+
+ // PI (1/64 MCLK, 1 PIs)
+ // ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+ // ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+ reg = ECCB1DLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);
+ tempD = isbR32m(DDRPHY, reg);
+ tempD >>= 24;
+ tempD &= 0x3F;
+
+ // Adjust PI_COUNT
+ pi_count += tempD;
+
+ LEAVEFN();
+ return pi_count;
+}
+
+// set_vref:
+//
+// This function will program the internal Vref setting in a given byte lane in a given channel.
+void set_vref(
+ uint8_t channel,
+ uint8_t byte_lane,
+ uint32_t setting)
+{
+ uint32_t reg = (byte_lane & 0x1) ? (B1VREFCTL) : (B0VREFCTL);
+
+ ENTERFN();
+ DPF(D_TRN, "Vref ch%d ln%d : val=%03X\n", channel, byte_lane, setting);
+
+ isbM32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)),
+ (vref_codes[setting] << 2), (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));
+ //isbM32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)), (setting<<2), (BIT7|BIT6|BIT5|BIT4|BIT3|BIT2));
+ // need to wait ~300ns for Vref to settle (check that this is necessary)
+ delay_n(300);
+ // ??? may need to clear pointers ???
+ LEAVEFN();
+ return;
+}
+
+// get_vref:
+//
+// This function will return the internal Vref setting for the given channel, byte_lane;
+uint32_t get_vref(
+ uint8_t channel,
+ uint8_t byte_lane)
+{
+ uint8_t j;
+ uint32_t ret_val = sizeof(vref_codes) / 2;
+ uint32_t reg = (byte_lane & 0x1) ? (B1VREFCTL) : (B0VREFCTL);
+
+ uint32_t tempD;
+
+ ENTERFN();
+ tempD = isbR32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)));
+ tempD >>= 2;
+ tempD &= 0x3F;
+ for (j = 0; j < sizeof(vref_codes); j++)
+ {
+ if (vref_codes[j] == tempD)
+ {
+ ret_val = j;
+ break;
+ }
+ }
+ LEAVEFN();
+ return ret_val;
+}
+
+// clear_pointers:
+//
+// This function will be used to clear the pointers in a given byte lane in a given channel.
+void clear_pointers(
+ void)
+{
+ uint8_t channel_i;
+ uint8_t bl_i;
+
+ ENTERFN();
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ for (bl_i = 0; bl_i < NUM_BYTE_LANES; bl_i++)
+ {
+ isbM32m(DDRPHY, (B01PTRCTL1 + (channel_i * DDRIODQ_CH_OFFSET) + ((bl_i >> 1) * DDRIODQ_BL_OFFSET)), ~(BIT8),
+ (BIT8));
+ //delay_m(1); // DEBUG
+ isbM32m(DDRPHY, (B01PTRCTL1 + (channel_i * DDRIODQ_CH_OFFSET) + ((bl_i >> 1) * DDRIODQ_BL_OFFSET)), (BIT8),
+ (BIT8));
+ }
+ }
+ LEAVEFN();
+ return;
+}
+
+// void enable_cache:
+void enable_cache(
+ void)
+{
+ // Cache control not used in Quark MRC
+ return;
+}
+
+// void disable_cache:
+void disable_cache(
+ void)
+{
+ // Cache control not used in Quark MRC
+ return;
+}
+
+// Send DRAM command, data should be formated
+// using DCMD_Xxxx macro or emrsXCommand structure.
+static void dram_init_command(
+ uint32_t data)
+{
+ Wr32(DCMD, 0, data);
+}
+
+// find_rising_edge:
+//
+// This function will find the rising edge transition on RCVN or WDQS.
+void find_rising_edge(
+ MRCParams_t *mrc_params,
+ uint32_t delay[],
+ uint8_t channel,
+ uint8_t rank,
+ bool rcvn)
+{
+
+#define SAMPLE_CNT 3 // number of sample points
+#define SAMPLE_DLY 26 // number of PIs to increment per sample
+#define FORWARD true // indicates to increase delays when looking for edge
+#define BACKWARD false // indicates to decrease delays when looking for edge
+
+ bool all_edges_found; // determines stop condition
+ bool direction[NUM_BYTE_LANES]; // direction indicator
+ uint8_t sample_i; // sample counter
+ uint8_t bl_i; // byte lane counter
+ uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor
+ uint32_t sample_result[SAMPLE_CNT]; // results of "sample_dqs()"
+ uint32_t tempD; // temporary DWORD
+ uint32_t transition_pattern;
+
+ ENTERFN();
+
+ // select hte and request initial configuration
+ select_hte(mrc_params);
+ first_run = 1;
+
+ // Take 3 sample points (T1,T2,T3) to obtain a transition pattern.
+ for (sample_i = 0; sample_i < SAMPLE_CNT; sample_i++)
+ {
+ // program the desired delays for sample
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ // increase sample delay by 26 PI (0.2 CLK)
+ if (rcvn)
+ {
+ set_rcvn(channel, rank, bl_i, delay[bl_i] + (sample_i * SAMPLE_DLY));
+ }
+ else
+ {
+ set_wdqs(channel, rank, bl_i, delay[bl_i] + (sample_i * SAMPLE_DLY));
+ }
+ } // bl_i loop
+ // take samples (Tsample_i)
+ sample_result[sample_i] = sample_dqs(mrc_params, channel, rank, rcvn);
+
+ DPF(D_TRN, "Find rising edge %s ch%d rnk%d: #%d dly=%d dqs=%02X\n",
+ (rcvn ? "RCVN" : "WDQS"), channel, rank,
+ sample_i, sample_i * SAMPLE_DLY, sample_result[sample_i]);
+
+ } // sample_i loop
+
+ // This pattern will help determine where we landed and ultimately how to place RCVEN/WDQS.
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ // build "transition_pattern" (MSB is 1st sample)
+ transition_pattern = 0x00;
+ for (sample_i = 0; sample_i < SAMPLE_CNT; sample_i++)
+ {
+ transition_pattern |= ((sample_result[sample_i] & (1 << bl_i)) >> bl_i) << (SAMPLE_CNT - 1 - sample_i);
+ } // sample_i loop
+
+ DPF(D_TRN, "=== transition pattern %d\n", transition_pattern);
+
+ // set up to look for rising edge based on "transition_pattern"
+ switch (transition_pattern)
+ {
+ case 0x00: // sampled 0->0->0
+ // move forward from T3 looking for 0->1
+ delay[bl_i] += 2 * SAMPLE_DLY;
+ direction[bl_i] = FORWARD;
+ break;
+ case 0x01: // sampled 0->0->1
+ case 0x05: // sampled 1->0->1 (bad duty cycle) *HSD#237503*
+ // move forward from T2 looking for 0->1
+ delay[bl_i] += 1 * SAMPLE_DLY;
+ direction[bl_i] = FORWARD;
+ break;
+// HSD#237503
+// case 0x02: // sampled 0->1->0 (bad duty cycle)
+// training_message(channel, rank, bl_i);
+// post_code(0xEE, 0xE8);
+// break;
+ case 0x02: // sampled 0->1->0 (bad duty cycle) *HSD#237503*
+ case 0x03: // sampled 0->1->1
+ // move forward from T1 looking for 0->1
+ delay[bl_i] += 0 * SAMPLE_DLY;
+ direction[bl_i] = FORWARD;
+ break;
+ case 0x04: // sampled 1->0->0 (assumes BL8, HSD#234975)
+ // move forward from T3 looking for 0->1
+ delay[bl_i] += 2 * SAMPLE_DLY;
+ direction[bl_i] = FORWARD;
+ break;
+// HSD#237503
+// case 0x05: // sampled 1->0->1 (bad duty cycle)
+// training_message(channel, rank, bl_i);
+// post_code(0xEE, 0xE9);
+// break;
+ case 0x06: // sampled 1->1->0
+ case 0x07: // sampled 1->1->1
+ // move backward from T1 looking for 1->0
+ delay[bl_i] += 0 * SAMPLE_DLY;
+ direction[bl_i] = BACKWARD;
+ break;
+ default:
+ post_code(0xEE, 0xEE);
+ break;
+ } // transition_pattern switch
+ // program delays
+ if (rcvn)
+ {
+ set_rcvn(channel, rank, bl_i, delay[bl_i]);
+ }
+ else
+ {
+ set_wdqs(channel, rank, bl_i, delay[bl_i]);
+ }
+ } // bl_i loop
+
+ // Based on the observed transition pattern on the byte lane,
+ // begin looking for a rising edge with single PI granularity.
+ do
+ {
+ all_edges_found = true; // assume all byte lanes passed
+ tempD = sample_dqs(mrc_params, channel, rank, rcvn); // take a sample
+ // check all each byte lane for proper edge
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ if (tempD & (1 << bl_i))
+ {
+ // sampled "1"
+ if (direction[bl_i] == BACKWARD)
+ {
+ // keep looking for edge on this byte lane
+ all_edges_found = false;
+ delay[bl_i] -= 1;
+ if (rcvn)
+ {
+ set_rcvn(channel, rank, bl_i, delay[bl_i]);
+ }
+ else
+ {
+ set_wdqs(channel, rank, bl_i, delay[bl_i]);
+ }
+ }
+ }
+ else
+ {
+ // sampled "0"
+ if (direction[bl_i] == FORWARD)
+ {
+ // keep looking for edge on this byte lane
+ all_edges_found = false;
+ delay[bl_i] += 1;
+ if (rcvn)
+ {
+ set_rcvn(channel, rank, bl_i, delay[bl_i]);
+ }
+ else
+ {
+ set_wdqs(channel, rank, bl_i, delay[bl_i]);
+ }
+ }
+ }
+ } // bl_i loop
+ } while (!all_edges_found);
+
+ // restore DDR idle state
+ dram_init_command(DCMD_PREA(rank));
+
+ DPF(D_TRN, "Delay %03X %03X %03X %03X\n",
+ delay[0], delay[1], delay[2], delay[3]);
+
+ LEAVEFN();
+ return;
+}
+
+// sample_dqs:
+//
+// This function will sample the DQTRAINSTS registers in the given channel/rank SAMPLE_SIZE times looking for a valid '0' or '1'.
+// It will return an encoded DWORD in which each bit corresponds to the sampled value on the byte lane.
+uint32_t sample_dqs(
+ MRCParams_t *mrc_params,
+ uint8_t channel,
+ uint8_t rank,
+ bool rcvn)
+{
+ uint8_t j; // just a counter
+ uint8_t bl_i; // which BL in the module (always 2 per module)
+ uint8_t bl_grp; // which BL module
+ uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor
+ uint32_t msk[2]; // BLx in module
+ uint32_t sampled_val[SAMPLE_SIZE]; // DQTRAINSTS register contents for each sample
+ uint32_t num_0s; // tracks the number of '0' samples
+ uint32_t num_1s; // tracks the number of '1' samples
+ uint32_t ret_val = 0x00; // assume all '0' samples
+ uint32_t address = get_addr(mrc_params, channel, rank);
+
+ // initialise "msk[]"
+ msk[0] = (rcvn) ? (BIT1) : (BIT9); // BL0
+ msk[1] = (rcvn) ? (BIT0) : (BIT8); // BL1
+
+
+ // cycle through each byte lane group
+ for (bl_grp = 0; bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2; bl_grp++)
+ {
+ // take SAMPLE_SIZE samples
+ for (j = 0; j < SAMPLE_SIZE; j++)
+ {
+ HteMemOp(address, first_run, rcvn?0:1);
+ first_run = 0;
+
+ // record the contents of the proper DQTRAINSTS register
+ sampled_val[j] = isbR32m(DDRPHY, (DQTRAINSTS + (bl_grp * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET)));
+ }
+ // look for a majority value ( (SAMPLE_SIZE/2)+1 ) on the byte lane
+ // and set that value in the corresponding "ret_val" bit
+ for (bl_i = 0; bl_i < 2; bl_i++)
+ {
+ num_0s = 0x00; // reset '0' tracker for byte lane
+ num_1s = 0x00; // reset '1' tracker for byte lane
+ for (j = 0; j < SAMPLE_SIZE; j++)
+ {
+ if (sampled_val[j] & msk[bl_i])
+ {
+ num_1s++;
+ }
+ else
+ {
+ num_0s++;
+ }
+ }
+ if (num_1s > num_0s)
+ {
+ ret_val |= (1 << (bl_i + (bl_grp * 2)));
+ }
+ }
+ }
+
+ // "ret_val.0" contains the status of BL0
+ // "ret_val.1" contains the status of BL1
+ // "ret_val.2" contains the status of BL2
+ // etc.
+ return ret_val;
+}
+
+// get_addr:
+//
+// This function will return a 32 bit address in the desired channel and rank.
+uint32_t get_addr(
+ MRCParams_t *mrc_params,
+ uint8_t channel,
+ uint8_t rank)
+{
+ uint32_t offset = 0x02000000; // 32MB
+
+ // Begin product specific code
+ if (channel > 0)
+ {
+ DPF(D_ERROR, "ILLEGAL CHANNEL\n");
+ DEAD_LOOP();
+ }
+
+ if (rank > 1)
+ {
+ DPF(D_ERROR, "ILLEGAL RANK\n");
+ DEAD_LOOP();
+ }
+
+ // use 256MB lowest density as per DRP == 0x0003
+ offset += rank * (256 * 1024 * 1024);
+
+ return offset;
+}
+
+// byte_lane_mask:
+//
+// This function will return a 32 bit mask that will be used to check for byte lane failures.
+uint32_t byte_lane_mask(
+ MRCParams_t *mrc_params)
+{
+ uint32_t j;
+ uint32_t ret_val = 0x00;
+
+ // set "ret_val" based on NUM_BYTE_LANES such that you will check only BL0 in "result"
+ // (each bit in "result" represents a byte lane)
+ for (j = 0; j < MAX_BYTE_LANES; j += NUM_BYTE_LANES)
+ {
+ ret_val |= (1 << ((j / NUM_BYTE_LANES) * NUM_BYTE_LANES));
+ }
+
+ // HSD#235037
+ // need to adjust the mask for 16-bit mode
+ if (mrc_params->channel_width == x16)
+ {
+ ret_val |= (ret_val << 2);
+ }
+
+ return ret_val;
+}
+
+
+// read_tsc:
+//
+// This function will do some assembly to return TSC register contents as a uint64_t.
+uint64_t read_tsc(
+ void)
+{
+ volatile uint64_t tsc; // EDX:EAX
+
+#if defined (SIM) || defined (GCC)
+ volatile uint32_t tscH; // EDX
+ volatile uint32_t tscL;// EAX
+
+ asm("rdtsc":"=a"(tscL),"=d"(tscH));
+ tsc = tscH;
+ tsc = (tsc<<32)|tscL;
+#else
+ tsc = __rdtsc();
+#endif
+
+ return tsc;
+}
+
+// get_tsc_freq:
+//
+// This function returns the TSC frequency in MHz
+uint32_t get_tsc_freq(
+ void)
+{
+ static uint32_t freq[] =
+ { 533, 400, 200, 100 };
+ uint32_t fuse;
+#if 0
+ fuse = (isbR32m(FUSE, 0) >> 12) & (BIT1|BIT0);
+#else
+ // todo!!! Fixed 533MHz for emulation or debugging
+ fuse = 0;
+#endif
+ return freq[fuse];
+}
+
+#ifndef SIM
+// delay_n:
+//
+// This is a simple delay function.
+// It takes "nanoseconds" as a parameter.
+void delay_n(
+ uint32_t nanoseconds)
+{
+ // 1000 MHz clock has 1ns period --> no conversion required
+ uint64_t final_tsc = read_tsc();
+ final_tsc += ((get_tsc_freq() * (nanoseconds)) / 1000);
+
+ while (read_tsc() < final_tsc)
+ ;
+ return;
+}
+#endif
+
+// delay_u:
+//
+// This is a simple delay function.
+// It takes "microseconds as a parameter.
+void delay_u(
+ uint32_t microseconds)
+{
+ // 64 bit math is not an option, just use loops
+ while (microseconds--)
+ {
+ delay_n(1000);
+ }
+ return;
+}
+
+// delay_m:
+//
+// This is a simple delay function.
+// It takes "milliseconds" as a parameter.
+void delay_m(
+ uint32_t milliseconds)
+{
+ // 64 bit math is not an option, just use loops
+ while (milliseconds--)
+ {
+ delay_u(1000);
+ }
+ return;
+}
+
+// delay_s:
+//
+// This is a simple delay function.
+// It takes "seconds" as a parameter.
+void delay_s(
+ uint32_t seconds)
+{
+ // 64 bit math is not an option, just use loops
+ while (seconds--)
+ {
+ delay_m(1000);
+ }
+ return;
+}
+
+// post_code:
+//
+// This function will output the POST CODE to the four 7-Segment LED displays.
+void post_code(
+ uint8_t major,
+ uint8_t minor)
+{
+#ifdef EMU
+ // Update global variable for execution tracking in debug env
+ PostCode = ((major << 8) | minor);
+#endif
+
+ // send message to UART
+ DPF(D_INFO, "POST: 0x%01X%02X\n", major, minor);
+
+ // error check:
+ if (major == 0xEE)
+ {
+ // todo!!! Consider updating error status and exit MRC
+#ifdef SIM
+ // enable Ctrl-C handling
+ for(;;) delay_n(100);
+#else
+ DEAD_LOOP();
+#endif
+ }
+}
+
+void training_message(
+ uint8_t channel,
+ uint8_t rank,
+ uint8_t byte_lane)
+{
+ // send message to UART
+ DPF(D_INFO, "CH%01X RK%01X BL%01X\n", channel, rank, byte_lane);
+ return;
+}
+
+void print_timings(
+ MRCParams_t *mrc_params)
+{
+ uint8_t algo_i;
+ uint8_t channel_i;
+ uint8_t rank_i;
+ uint8_t bl_i;
+ uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1;
+
+ DPF(D_INFO, "\n---------------------------");
+ DPF(D_INFO, "\nALGO[CH:RK] BL0 BL1 BL2 BL3");
+ DPF(D_INFO, "\n===========================");
+ for (algo_i = 0; algo_i < eMAX_ALGOS; algo_i++)
+ {
+ for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
+ {
+ if (mrc_params->channel_enables & (1 << channel_i))
+ {
+ for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
+ {
+ if (mrc_params->rank_enables & (1 << rank_i))
+ {
+ switch (algo_i)
+ {
+ case eRCVN:
+ DPF(D_INFO, "\nRCVN[%02d:%02d]", channel_i, rank_i);
+ break;
+ case eWDQS:
+ DPF(D_INFO, "\nWDQS[%02d:%02d]", channel_i, rank_i);
+ break;
+ case eWDQx:
+ DPF(D_INFO, "\nWDQx[%02d:%02d]", channel_i, rank_i);
+ break;
+ case eRDQS:
+ DPF(D_INFO, "\nRDQS[%02d:%02d]", channel_i, rank_i);
+ break;
+ case eVREF:
+ DPF(D_INFO, "\nVREF[%02d:%02d]", channel_i, rank_i);
+ break;
+ case eWCMD:
+ DPF(D_INFO, "\nWCMD[%02d:%02d]", channel_i, rank_i);
+ break;
+ case eWCTL:
+ DPF(D_INFO, "\nWCTL[%02d:%02d]", channel_i, rank_i);
+ break;
+ case eWCLK:
+ DPF(D_INFO, "\nWCLK[%02d:%02d]", channel_i, rank_i);
+ break;
+ default:
+ break;
+ } // algo_i switch
+ for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
+ {
+ switch (algo_i)
+ {
+ case eRCVN:
+ DPF(D_INFO, " %03d", get_rcvn(channel_i, rank_i, bl_i));
+ break;
+ case eWDQS:
+ DPF(D_INFO, " %03d", get_wdqs(channel_i, rank_i, bl_i));
+ break;
+ case eWDQx:
+ DPF(D_INFO, " %03d", get_wdq(channel_i, rank_i, bl_i));
+ break;
+ case eRDQS:
+ DPF(D_INFO, " %03d", get_rdqs(channel_i, rank_i, bl_i));
+ break;
+ case eVREF:
+ DPF(D_INFO, " %03d", get_vref(channel_i, bl_i));
+ break;
+ case eWCMD:
+ DPF(D_INFO, " %03d", get_wcmd(channel_i));
+ break;
+ case eWCTL:
+ DPF(D_INFO, " %03d", get_wctl(channel_i, rank_i));
+ break;
+ case eWCLK:
+ DPF(D_INFO, " %03d", get_wclk(channel_i, rank_i));
+ break;
+ default:
+ break;
+ } // algo_i switch
+ } // bl_i loop
+ } // if rank_i enabled
+ } // rank_i loop
+ } // if channel_i enabled
+ } // channel_i loop
+ } // algo_i loop
+ DPF(D_INFO, "\n---------------------------");
+ DPF(D_INFO, "\n");
+ return;
+}
+
+// 32 bit LFSR with characteristic polynomial: X^32 + X^22 +X^2 + X^1
+// The function takes pointer to previous 32 bit value and modifies it to next value.
+void lfsr32(
+ uint32_t *lfsr_ptr)
+{
+ uint32_t bit;
+ uint32_t lfsr;
+ uint32_t i;
+
+ lfsr = *lfsr_ptr;
+
+ for (i = 0; i < 32; i++)
+ {
+ bit = 1 ^ (lfsr & BIT0);
+ bit = bit ^ ((lfsr & BIT1) >> 1);
+ bit = bit ^ ((lfsr & BIT2) >> 2);
+ bit = bit ^ ((lfsr & BIT22) >> 22);
+
+ lfsr = ((lfsr >> 1) | (bit << 31));
+ }
+
+ *lfsr_ptr = lfsr;
+ return;
+}
+
+// The purpose of this function is to ensure the SEC comes out of reset
+// and IA initiates the SEC enabling Memory Scrambling.
+void enable_scrambling(
+ MRCParams_t *mrc_params)
+{
+ uint32_t lfsr = 0;
+ uint8_t i;
+
+ if (mrc_params->scrambling_enables == 0)
+ return;
+
+ ENTERFN();
+
+ // 32 bit seed is always stored in BIOS NVM.
+ lfsr = mrc_params->timings.scrambler_seed;
+
+ if (mrc_params->boot_mode == bmCold)
+ {
+ // factory value is 0 and in first boot, a clock based seed is loaded.
+ if (lfsr == 0)
+ {
+ lfsr = read_tsc() & 0x0FFFFFFF; // get seed from system clock and make sure it is not all 1's
+ }
+ // need to replace scrambler
+ // get next 32bit LFSR 16 times which is the last part of the previous scrambler vector.
+ else
+ {
+ for (i = 0; i < 16; i++)
+ {
+ lfsr32(&lfsr);
+ }
+ }
+ mrc_params->timings.scrambler_seed = lfsr; // save new seed.
+ } // if (cold_boot)
+
+ // In warm boot or S3 exit, we have the previous seed.
+ // In cold boot, we have the last 32bit LFSR which is the new seed.
+ lfsr32(&lfsr); // shift to next value
+ isbW32m(MCU, SCRMSEED, (lfsr & 0x0003FFFF));
+ for (i = 0; i < 2; i++)
+ {
+ isbW32m(MCU, SCRMLO + i, (lfsr & 0xAAAAAAAA));
+ }
+
+ LEAVEFN();
+ return;
+}
+
+// This function will store relevant timing data
+// This data will be used on subsequent boots to speed up boot times
+// and is required for Suspend To RAM capabilities.
+void store_timings(
+ MRCParams_t *mrc_params)
+{
+ uint8_t ch, rk, bl;
+ MrcTimings_t *mt = &mrc_params->timings;
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++)
+ {
+ for (rk = 0; rk < NUM_RANKS; rk++)
+ {
+ for (bl = 0; bl < NUM_BYTE_LANES; bl++)
+ {
+ mt->rcvn[ch][rk][bl] = get_rcvn(ch, rk, bl); // RCVN
+ mt->rdqs[ch][rk][bl] = get_rdqs(ch, rk, bl); // RDQS
+ mt->wdqs[ch][rk][bl] = get_wdqs(ch, rk, bl); // WDQS
+ mt->wdq[ch][rk][bl] = get_wdq(ch, rk, bl); // WDQ
+ if (rk == 0)
+ {
+ mt->vref[ch][bl] = get_vref(ch, bl); // VREF (RANK0 only)
+ }
+ }
+ mt->wctl[ch][rk] = get_wctl(ch, rk); // WCTL
+ }
+ mt->wcmd[ch] = get_wcmd(ch); // WCMD
+ }
+
+ // need to save for a case of changing frequency after warm reset
+ mt->ddr_speed = mrc_params->ddr_speed;
+
+ return;
+}
+
+// This function will retrieve relevant timing data
+// This data will be used on subsequent boots to speed up boot times
+// and is required for Suspend To RAM capabilities.
+void restore_timings(
+ MRCParams_t *mrc_params)
+{
+ uint8_t ch, rk, bl;
+ const MrcTimings_t *mt = &mrc_params->timings;
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++)
+ {
+ for (rk = 0; rk < NUM_RANKS; rk++)
+ {
+ for (bl = 0; bl < NUM_BYTE_LANES; bl++)
+ {
+ set_rcvn(ch, rk, bl, mt->rcvn[ch][rk][bl]); // RCVN
+ set_rdqs(ch, rk, bl, mt->rdqs[ch][rk][bl]); // RDQS
+ set_wdqs(ch, rk, bl, mt->wdqs[ch][rk][bl]); // WDQS
+ set_wdq(ch, rk, bl, mt->wdq[ch][rk][bl]); // WDQ
+ if (rk == 0)
+ {
+ set_vref(ch, bl, mt->vref[ch][bl]); // VREF (RANK0 only)
+ }
+ }
+ set_wctl(ch, rk, mt->wctl[ch][rk]); // WCTL
+ }
+ set_wcmd(ch, mt->wcmd[ch]); // WCMD
+ }
+
+ return;
+}
+
+// Configure default settings normally set as part of read training
+// Some defaults have to be set earlier as they may affect earlier
+// training steps.
+void default_timings(
+ MRCParams_t *mrc_params)
+{
+ uint8_t ch, rk, bl;
+
+ for (ch = 0; ch < NUM_CHANNELS; ch++)
+ {
+ for (rk = 0; rk < NUM_RANKS; rk++)
+ {
+ for (bl = 0; bl < NUM_BYTE_LANES; bl++)
+ {
+ set_rdqs(ch, rk, bl, 24); // RDQS
+ if (rk == 0)
+ {
+ set_vref(ch, bl, 32); // VREF (RANK0 only)
+ }
+ }
+ }
+ }
+
+ return;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.h
new file mode 100755
index 0000000..84c194a
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.h
@@ -0,0 +1,115 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ***************************************************************************/
+#ifndef _MEMINIT_UTILS_H_
+#define _MEMINIT_UTILS_H_
+
+// General Definitions:
+#ifdef QUICKSIM
+#define SAMPLE_SIZE 4 // reduce number of training samples in simulation env
+#else
+#define SAMPLE_SIZE 6 // must be odd number
+#endif
+
+#define EARLY_DB (0x12) // must be less than this number to enable early deadband
+#define LATE_DB (0x34) // must be greater than this number to enable late deadband
+#define CHX_REGS (11*4)
+#define FULL_CLK 128
+#define HALF_CLK 64
+#define QRTR_CLK 32
+
+
+
+#define MCEIL(num,den) ((uint8_t)((num+den-1)/den))
+#define MMAX(a,b) ((a)>(b)?(a):(b))
+#define MCOUNT(a) (sizeof(a)/sizeof(*a))
+
+typedef enum ALGOS_enum {
+ eRCVN = 0,
+ eWDQS,
+ eWDQx,
+ eRDQS,
+ eVREF,
+ eWCMD,
+ eWCTL,
+ eWCLK,
+ eMAX_ALGOS,
+} ALGOs_t;
+
+
+// Prototypes:
+void set_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane, uint32_t pi_count);
+void set_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane, uint32_t pi_count);
+void set_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane, uint32_t pi_count);
+void set_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane, uint32_t pi_count);
+void set_wcmd(uint8_t channel, uint32_t pi_count);
+void set_wclk(uint8_t channel, uint8_t grp, uint32_t pi_count);
+void set_wctl(uint8_t channel, uint8_t rank, uint32_t pi_count);
+void set_vref(uint8_t channel, uint8_t byte_lane, uint32_t setting);
+uint32_t get_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+uint32_t get_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+uint32_t get_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+uint32_t get_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+uint32_t get_wcmd(uint8_t channel);
+uint32_t get_wclk(uint8_t channel, uint8_t group);
+uint32_t get_wctl(uint8_t channel, uint8_t rank);
+uint32_t get_vref(uint8_t channel, uint8_t byte_lane);
+
+void clear_pointers(void);
+void enable_cache(void);
+void disable_cache(void);
+void find_rising_edge(MRCParams_t *mrc_params, uint32_t delay[], uint8_t channel, uint8_t rank, bool rcvn);
+uint32_t sample_dqs(MRCParams_t *mrc_params, uint8_t channel, uint8_t rank, bool rcvn);
+uint32_t get_addr(MRCParams_t *mrc_params, uint8_t channel, uint8_t rank);
+uint32_t byte_lane_mask(MRCParams_t *mrc_params);
+
+uint64_t read_tsc(void);
+uint32_t get_tsc_freq(void);
+void delay_n(uint32_t nanoseconds);
+void delay_u(uint32_t microseconds);
+void delay_m(uint32_t milliseconds);
+void delay_s(uint32_t seconds);
+
+void post_code(uint8_t major, uint8_t minor);
+void training_message(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void print_timings(MRCParams_t *mrc_params);
+
+void enable_scrambling(MRCParams_t *mrc_params);
+void store_timings(MRCParams_t *mrc_params);
+void restore_timings(MRCParams_t *mrc_params);
+void default_timings(MRCParams_t *mrc_params);
+
+#ifndef SIM
+void *memset(void *d, int c, size_t n);
+void *memcpy(void *d, const void *s, size_t n);
+#endif
+
+#endif // _MEMINIT_UTILS_H_
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/memory_options.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/memory_options.h
new file mode 100755
index 0000000..1f32368
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/memory_options.h
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ Memory_options.h
+
+Abstract:
+
+ Common definitions and compilation switches for MRC
+
+--*/
+#ifndef __MEMORY_OPTIONS_H
+#define __MEMORY_OPTIONS_H
+
+#include "core_types.h"
+
+// MRC COMPILE TIME SWITCHES:
+// ==========================
+
+
+
+//#define MRC_SV // enable some validation opitons
+
+#if defined (SIM) || defined(EMU)
+#define QUICKSIM // reduce execution time using shorter rd/wr sequences
+#endif
+
+#define CLT // required for Quark project
+
+
+
+//#define BACKUP_RCVN // enable STATIC timing settings for RCVN (BACKUP_MODE)
+//#define BACKUP_WDQS // enable STATIC timing settings for WDQS (BACKUP_MODE)
+//#define BACKUP_RDQS // enable STATIC timing settings for RDQS (BACKUP_MODE)
+//#define BACKUP_WDQ // enable STATIC timing settings for WDQ (BACKUP_MODE)
+
+
+
+//#define BACKUP_COMPS // enable *COMP overrides (BACKUP_MODE)
+//#define RX_EYE_CHECK // enable the RD_TRAIN eye check
+#define HMC_TEST // enable Host to Memory Clock Alignment
+#define R2R_SHARING // enable multi-rank support via rank2rank sharing
+
+#define FORCE_16BIT_DDRIO // disable signals not used in 16bit mode of DDRIO
+
+
+
+//
+// Debug support
+//
+
+#ifdef NDEBUG
+#define DPF if(0) dpf
+#else
+#define DPF dpf
+#endif
+
+void dpf( uint32_t mask, char_t *bla, ...);
+
+
+uint8_t mgetc(void);
+uint8_t mgetch(void);
+
+
+// Debug print type
+#define D_ERROR 0x0001
+#define D_INFO 0x0002
+#define D_REGRD 0x0004
+#define D_REGWR 0x0008
+#define D_FCALL 0x0010
+#define D_TRN 0x0020
+#define D_TIME 0x0040
+
+#define ENTERFN() DPF(D_FCALL, "<%s>\n", __FUNCTION__)
+#define LEAVEFN() DPF(D_FCALL, "</%s>\n", __FUNCTION__)
+#define REPORTFN() DPF(D_FCALL, "<%s/>\n", __FUNCTION__)
+
+extern uint32_t DpfPrintMask;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.c
new file mode 100755
index 0000000..0129ddc
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.c
@@ -0,0 +1,64 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************/
+#include "mrc.h"
+#include "memory_options.h"
+
+#include "meminit.h"
+#include "meminit_utils.h"
+#include "prememinit.h"
+#include "io.h"
+
+// Base address for UART registers
+extern uint32_t UartMmioBase;
+
+//
+// Memory Reference Code entry point when executing from BIOS
+//
+void Mrc( MRCParams_t *mrc_params)
+{
+ // configure uart base address assuming code relocated to eSRAM
+ UartMmioBase = mrc_params->uart_mmio_base;
+
+ ENTERFN();
+
+ DPF(D_INFO, "MRC Version %04X %s %s\n", MRC_VERSION, __DATE__, __TIME__);
+
+ // this will set up the data structures used by MemInit()
+ PreMemInit(mrc_params);
+
+ // this will initialize system memory
+ MemInit(mrc_params);
+
+ LEAVEFN();
+ return;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.h
new file mode 100755
index 0000000..dfb472f
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.h
@@ -0,0 +1,184 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************/
+#ifndef _MRC_H_
+#define _MRC_H_
+
+#include "core_types.h"
+
+// define the MRC Version
+#define MRC_VERSION 0x0111
+
+
+// architectural definitions
+#define NUM_CHANNELS 1 // number of channels
+#define NUM_RANKS 2 // number of ranks per channel
+#define NUM_BYTE_LANES 4 // number of byte lanes per channel
+
+// software limitations
+#define MAX_CHANNELS 1
+#define MAX_RANKS 2
+#define MAX_BYTE_LANES 4
+
+// only to mock MrcWrapper
+#define MAX_SOCKETS 1
+#define MAX_SIDES 1
+#define MAX_ROWS (MAX_SIDES * MAX_SOCKETS)
+// end
+
+
+// Specify DRAM of nenory channel width
+enum {
+ x8, // DRAM width
+ x16, // DRAM width & Channel Width
+ x32 // Channel Width
+};
+
+// Specify DRAM speed
+enum {
+ DDRFREQ_800,
+ DDRFREQ_1066
+};
+
+// Specify DRAM type
+enum {
+ DDR3,
+ DDR3L
+};
+
+// Delay configuration for individual signals
+// Vref setting
+// Scrambler seed
+typedef struct MrcTimings_s
+{
+ uint32_t rcvn[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t rdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t wdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t wdq [NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+ uint32_t vref[NUM_CHANNELS][NUM_BYTE_LANES];
+ uint32_t wctl[NUM_CHANNELS][NUM_RANKS];
+ uint32_t wcmd[NUM_CHANNELS];
+
+ uint32_t scrambler_seed;
+ uint8_t ddr_speed; // need to save for the case of frequency change
+} MrcTimings_t;
+
+
+// DENSITY: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
+// tCL is DRAM CAS Latency in clocks.
+// All other timings are in picoseconds.
+// Refer to JEDEC spec (or DRAM datasheet) when changing these values.
+typedef struct DRAMParams_s {
+ uint8_t DENSITY;
+ uint8_t tCL; // CAS latency in clocks
+ uint32_t tRAS; // ACT to PRE command period
+ uint32_t tWTR; // Delay from start of internal write transaction to internal read command
+ uint32_t tRRD; // ACT to ACT command period (JESD79 specific to page size 1K/2K)
+ uint32_t tFAW; // Four activate window (JESD79 specific to page size 1K/2K)
+} DRAMParams_t;
+
+
+// Boot mode defined as bit mask (1<<n)
+#define bmCold 1 // full training
+#define bmFast 2 // restore timing parameters
+#define bmS3 4 // resume from S3
+#define bmWarm 8
+#define bmUnknown 0
+
+
+// MRC execution status
+#define MRC_SUCCESS 0 // initialization ok
+#define MRC_E_MEMTEST 1 // memtest failed
+
+
+//
+// Input/output/context parameters for Memory Reference Code
+//
+typedef struct MRCParams_s
+{
+ //
+ // Global settings
+ //
+
+ uint32_t boot_mode; // bmCold, bmFast, bmWarm, bmS3
+ uint32_t uart_mmio_base; // pcie serial port base address (force 0 to disable debug)
+
+ uint8_t dram_width; // x8, x16
+ uint8_t ddr_speed; // DDRFREQ_800, DDRFREQ_1066
+ uint8_t ddr_type; // DDR3, DDR3L
+ uint8_t ecc_enables; // 0, 1 (memory size reduced to 7/8)
+ uint8_t scrambling_enables; // 0, 1
+ uint32_t rank_enables; // 1, 3 (1'st rank has to be populated if 2'nd rank present)
+ uint32_t channel_enables; // 1 only
+ uint32_t channel_width; // x16 only
+ uint32_t address_mode; // 0, 1, 2 (mode 2 forced if ecc enabled)
+
+ // memConfig_t begin
+ uint8_t refresh_rate; // REFRESH_RATE : 1=1.95us, 2=3.9us, 3=7.8us, others=RESERVED
+ uint8_t sr_temp_range; // SR_TEMP_RANGE : 0=normal, 1=extended, others=RESERVED
+ uint8_t ron_value; // RON_VALUE : 0=34ohm, 1=40ohm, others=RESERVED (select MRS1.DIC driver impedance control)
+ uint8_t rtt_nom_value; // RTT_NOM_VALUE : 0=40ohm, 1=60ohm, 2=120ohm, others=RESERVED
+ uint8_t rd_odt_value; // RD_ODT_VALUE : 0=off, 1=60ohm, 2=120ohm, 3=180ohm, others=RESERVED
+ // memConfig_t end
+
+ DRAMParams_t params;
+
+ //
+ // Internally used
+ //
+
+ uint32_t board_id; // internally used for board layout (use x8 or x16 memory)
+ uint32_t hte_setup : 1; // when set hte reconfiguration requested
+ uint32_t menu_after_mrc : 1;
+ uint32_t power_down_disable :1;
+ uint32_t tune_rcvn :1;
+
+ uint32_t channel_size[NUM_CHANNELS];
+ uint32_t column_bits[NUM_CHANNELS];
+ uint32_t row_bits[NUM_CHANNELS];
+
+ uint32_t mrs1; // register content saved during training
+
+ //
+ // Output
+ //
+
+ uint32_t status; // initialization result (non zero specifies error code)
+ uint32_t mem_size; // total memory size in bytes (excludes ECC banks)
+
+ MrcTimings_t timings; // training results (also used on input)
+
+} MRCParams_t;
+
+// Alternative type name for consistent naming convention
+#define MRC_PARAMS MRCParams_t
+
+#endif // _MRC_H_
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/platform.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/platform.c
new file mode 100755
index 0000000..cd8b9ea
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/platform.c
@@ -0,0 +1,217 @@
+/*++
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name:
+
+ Platform.c
+
+ Abstract:
+
+ The interface layer for memory controller access.
+ It is supporting both real hardware platform and simulation environment.
+
+ --*/
+#include "mrc.h"
+#include "memory_options.h"
+#include "meminit_utils.h"
+#include "io.h"
+
+#ifdef SIM
+
+void SimMmio32Write (
+ uint32_t be,
+ uint32_t address,
+ uint32_t data );
+
+void SimMmio32Read (
+ uint32_t be,
+ uint32_t address,
+ uint32_t *data );
+
+void SimDelayClk (
+ uint32_t x2clk );
+
+// This is a simple delay function.
+// It takes "nanoseconds" as a parameter.
+void delay_n(uint32_t nanoseconds)
+{
+ SimDelayClk( 800*nanoseconds/1000);
+}
+#endif
+
+/****
+ *
+ ***/
+uint32_t Rd32(
+ uint32_t unit,
+ uint32_t addr)
+{
+ uint32_t data;
+
+ switch (unit)
+ {
+ case MEM:
+ case MMIO:
+#ifdef SIM
+ SimMmio32Read( 1, addr, &data);
+#else
+ data = *PTR32(addr);
+#endif
+ break;
+
+ case MCU:
+ case HOST_BRIDGE:
+ case MEMORY_MANAGER:
+ case HTE:
+ // Handle case addr bigger than 8bit
+ pciwrite32(0, 0, 0, SB_HADR_REG, addr & 0xFFF00);
+ addr &= 0x00FF;
+
+ pciwrite32(0, 0, 0, SB_PACKET_REG,
+ SB_COMMAND(SB_REG_READ_OPCODE, unit, addr));
+ data = pciread32(0, 0, 0, SB_DATA_REG);
+ break;
+
+ case DDRPHY:
+ // Handle case addr bigger than 8bit
+ pciwrite32(0, 0, 0, SB_HADR_REG, addr & 0xFFF00);
+ addr &= 0x00FF;
+
+ pciwrite32(0, 0, 0, SB_PACKET_REG,
+ SB_COMMAND(SB_DDRIO_REG_READ_OPCODE, unit, addr));
+ data = pciread32(0, 0, 0, SB_DATA_REG);
+ break;
+
+ default:
+ DEAD_LOOP()
+ ;
+ }
+
+ if (unit < MEM)
+ DPF(D_REGRD, "RD32 %03X %08X %08X\n", unit, addr, data);
+
+ return data;
+}
+
+/****
+ *
+ ***/
+void Wr32(
+ uint32_t unit,
+ uint32_t addr,
+ uint32_t data)
+{
+ if (unit < MEM)
+ DPF(D_REGWR, "WR32 %03X %08X %08X\n", unit, addr, data);
+
+ switch (unit)
+ {
+ case MEM:
+ case MMIO:
+#ifdef SIM
+ SimMmio32Write( 1, addr, data);
+#else
+ *PTR32(addr) = data;
+#endif
+ break;
+
+ case MCU:
+ case HOST_BRIDGE:
+ case MEMORY_MANAGER:
+ case HTE:
+ // Handle case addr bigger than 8bit
+ pciwrite32(0, 0, 0, SB_HADR_REG, addr & 0xFFF00);
+ addr &= 0x00FF;
+
+ pciwrite32(0, 0, 0, SB_DATA_REG, data);
+ pciwrite32(0, 0, 0, SB_PACKET_REG,
+ SB_COMMAND(SB_REG_WRITE_OPCODE, unit, addr));
+ break;
+
+ case DDRPHY:
+ // Handle case addr bigger than 8bit
+ pciwrite32(0, 0, 0, SB_HADR_REG, addr & 0xFFF00);
+ addr &= 0x00FF;
+
+ pciwrite32(0, 0, 0, SB_DATA_REG, data);
+ pciwrite32(0, 0, 0, SB_PACKET_REG,
+ SB_COMMAND(SB_DDRIO_REG_WRITE_OPCODE, unit, addr));
+ break;
+
+ case DCMD:
+ pciwrite32(0, 0, 0, SB_HADR_REG, 0);
+ pciwrite32(0, 0, 0, SB_DATA_REG, data);
+ pciwrite32(0, 0, 0, SB_PACKET_REG,
+ SB_COMMAND(SB_DRAM_CMND_OPCODE, MCU, 0));
+ break;
+
+ default:
+ DEAD_LOOP()
+ ;
+ }
+}
+
+/****
+ *
+ ***/
+void WrMask32(
+ uint32_t unit,
+ uint32_t addr,
+ uint32_t data,
+ uint32_t mask)
+{
+ Wr32(unit, addr, ((Rd32(unit, addr) & ~mask) | (data & mask)));
+}
+
+/****
+ *
+ ***/
+void pciwrite32(
+ uint32_t bus,
+ uint32_t dev,
+ uint32_t fn,
+ uint32_t reg,
+ uint32_t data)
+{
+ Wr32(MMIO, PCIADDR(bus,dev,fn,reg), data);
+}
+
+/****
+ *
+ ***/
+uint32_t pciread32(
+ uint32_t bus,
+ uint32_t dev,
+ uint32_t fn,
+ uint32_t reg)
+{
+ return Rd32(MMIO, PCIADDR(bus,dev,fn,reg));
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.c
new file mode 100755
index 0000000..ecd2951
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.c
@@ -0,0 +1,211 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************/
+
+#include "mrc.h"
+#include "memory_options.h"
+
+#include "meminit_utils.h"
+#include "prememinit.h"
+#include "io.h"
+
+// Read character from serial console
+uint8_t mgetc(void);
+
+extern uint32_t DpfPrintMask;
+
+// Adjust configuration parameters before initialisation
+// sequence.
+void PreMemInit(
+ MRCParams_t *mrc_params)
+{
+ const DRAMParams_t *dram_params;
+
+ uint8_t dram_width;
+ uint32_t dram_cfg_index;
+ uint32_t channel_i;
+
+ ENTERFN();
+
+#ifdef MRC_SV
+ {
+ uint8_t ch;
+
+ myloop:
+
+ DPF(D_INFO, "- c - continue\n");
+ DPF(D_INFO, "- f - boot mode [%d]\n", mrc_params->boot_mode);
+ DPF(D_INFO, "- r - rank enable [%d]\n", mrc_params->rank_enables);
+ DPF(D_INFO, "- e - ecc switch [%d]\n", mrc_params->ecc_enables);
+ DPF(D_INFO, "- b - scrambling switch [%d]\n", mrc_params->scrambling_enables);
+ DPF(D_INFO, "- a - adr mode [%d]\n", mrc_params->address_mode);
+ DPF(D_INFO, "- m - menu after mrc [%d]\n", mrc_params->menu_after_mrc);
+ DPF(D_INFO, "- t - tune to rcvn [%d]\n", mrc_params->tune_rcvn);
+ DPF(D_INFO, "- o - odt switch [%d]\n", mrc_params->rd_odt_value);
+ DPF(D_INFO, "- d - dram density [%d]\n", mrc_params->params.DENSITY);
+ DPF(D_INFO, "- p - power down disable [%d]\n", mrc_params->power_down_disable);
+ DPF(D_INFO, "- l - log switch 0x%x\n", DpfPrintMask);
+ ch = mgetc();
+
+ switch (ch)
+ {
+ case 'f':
+ mrc_params->boot_mode >>= 1;
+ if(mrc_params->boot_mode == bmUnknown)
+ {
+ mrc_params->boot_mode = bmWarm;
+ }
+ DPF(D_INFO, "Boot mode %d\n", mrc_params->boot_mode);
+ break;
+
+ case 'p':
+ mrc_params->power_down_disable ^= 1;
+ DPF(D_INFO, "Power down disable %d\n", mrc_params->power_down_disable);
+ break;
+
+ case 'r':
+ mrc_params->rank_enables ^= 2;
+ DPF(D_INFO, "Rank enable %d\n", mrc_params->rank_enables);
+ break;
+
+ case 'e':
+ mrc_params->ecc_enables ^= 1;
+ DPF(D_INFO, "Ecc enable %d\n", mrc_params->ecc_enables);
+ break;
+
+ case 'b':
+ mrc_params->scrambling_enables ^= 1;
+ DPF(D_INFO, "Scrambler enable %d\n", mrc_params->scrambling_enables);
+ break;
+
+ case 'a':
+ mrc_params->address_mode = (mrc_params->address_mode + 1) % 3;
+ DPF(D_INFO, "Adr mode %d\n", mrc_params->address_mode);
+ break;
+
+ case 'm':
+ mrc_params->menu_after_mrc ^= 1;
+ DPF(D_INFO, "Menu after mrc %d\n", mrc_params->menu_after_mrc);
+ break;
+
+ case 't':
+ mrc_params->tune_rcvn ^= 1;
+ DPF(D_INFO, "Tune to rcvn %d\n", mrc_params->tune_rcvn);
+ break;
+
+ case 'o':
+ mrc_params->rd_odt_value = (mrc_params->rd_odt_value + 1) % 4;
+ DPF(D_INFO, "Rd_odt_value %d\n", mrc_params->rd_odt_value);
+ break;
+
+ case 'd':
+ mrc_params->params.DENSITY = (mrc_params->params.DENSITY + 1) % 4;
+ DPF(D_INFO, "Dram density %d\n", mrc_params->params.DENSITY);
+ break;
+
+ case 'l':
+ DpfPrintMask ^= 0x30;
+ DPF(D_INFO, "Log mask %x\n", DpfPrintMask);
+ break;
+
+ default:
+ break;
+ }
+
+ if (ch != 'c')
+ goto myloop;
+
+ }
+#endif
+
+ // initially expect success
+ mrc_params->status = MRC_SUCCESS;
+
+ // todo!!! Setup board layout (must be reviewed as is selecting static timings)
+ // 0 == R0 (DDR3 x16), 1 == R1 (DDR3 x16), 2 == DV (DDR3 x8), 3 == SV (DDR3 x8)
+ if (mrc_params->dram_width == x8)
+ {
+ mrc_params->board_id = 2; // select x8 layout
+ }
+ else
+ {
+ mrc_params->board_id = 0; // select x16 layout
+ }
+
+ // initially no memory
+ mrc_params->mem_size = 0;
+ channel_i = 0;
+
+ // begin of channel settings
+ dram_width = mrc_params->dram_width;
+ dram_params = &mrc_params->params;
+ dram_cfg_index = 0;
+
+ // Determine Column & Row Bits:
+ // Column:
+ // 11 for 8Gbx8, else 10
+ mrc_params->column_bits[channel_i] = ((dram_params[dram_cfg_index].DENSITY == 4) && (dram_width == x8)) ? (11) : (10);
+
+ // Row:
+ // 512Mbx16=12 512Mbx8=13
+ // 1Gbx16=13 1Gbx8=14
+ // 2Gbx16=14 2Gbx8=15
+ // 4Gbx16=15 4Gbx8=16
+ // 8Gbx16=16 8Gbx8=16
+ mrc_params->row_bits[channel_i] = 12 + (dram_params[dram_cfg_index].DENSITY)
+ + (((dram_params[dram_cfg_index].DENSITY < 4) && (dram_width == x8)) ? (1) : (0));
+
+ // Determine Per Channel Memory Size:
+ // (For 2 RANKs, multiply by 2)
+ // (For 16 bit data bus, divide by 2)
+ // DENSITY WIDTH MEM_AVAILABLE
+ // 512Mb x16 0x008000000 ( 128MB)
+ // 512Mb x8 0x010000000 ( 256MB)
+ // 1Gb x16 0x010000000 ( 256MB)
+ // 1Gb x8 0x020000000 ( 512MB)
+ // 2Gb x16 0x020000000 ( 512MB)
+ // 2Gb x8 0x040000000 (1024MB)
+ // 4Gb x16 0x040000000 (1024MB)
+ // 4Gb x8 0x080000000 (2048MB)
+ mrc_params->channel_size[channel_i] = (1 << dram_params[dram_cfg_index].DENSITY);
+ mrc_params->channel_size[channel_i] *= ((dram_width == x8) ? (2) : (1));
+ mrc_params->channel_size[channel_i] *= (mrc_params->rank_enables == 0x3) ? (2) : (1);
+ mrc_params->channel_size[channel_i] *= (mrc_params->channel_width == x16) ? (1) : (2);
+
+ // Determine memory size (convert number of 64MB/512Mb units)
+ mrc_params->mem_size += mrc_params->channel_size[channel_i] << 26;
+
+ // end of channel settings
+
+ LEAVEFN();
+ return;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.h
new file mode 100755
index 0000000..55c3862
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.h
@@ -0,0 +1,39 @@
+/************************************************************************
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************/
+#ifndef __PREMEMINIT_H_
+#define __PREMEMINIT_H_
+
+// Function prototypes
+void PreMemInit(MRCParams_t *mrc_params);
+
+
+#endif // _PREMEMINIT_H_
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/CommonHeader.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/CommonHeader.h
new file mode 100644
index 0000000..efcdc7f
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/CommonHeader.h
@@ -0,0 +1,93 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+#include <IntelQNCDxe.h>
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Guid/SmramMemoryReserve.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/SmmAccess2.h>
+#include <Protocol/LegacyRegion2.h>
+#include <Protocol/CpuIo2.h>
+#include <Protocol/MpService.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/Cpu.h>
+#include <Protocol/Timer.h>
+#include <Protocol/PciHotPlugInit.h>
+#include <Protocol/LegacyInterrupt.h>
+#include <Protocol/Legacy8259.h>
+#include <Protocol/SmbusHc.h>
+#include <Protocol/QncS3Support.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/S3PciLib.h>
+#include <Library/S3IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/PciLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/SmbusLib.h>
+
+extern EFI_HANDLE gQNCInitImageHandle;
+extern QNC_DEVICE_ENABLES mQNCDeviceEnables;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.c
new file mode 100644
index 0000000..fdb6caa
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.c
@@ -0,0 +1,636 @@
+/** @file
+ Implementation for SMBus DXE driver entry point and SMBus Host
+ Controller protocol.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "CommonHeader.h"
+
+#include "DxeQNCSmbus.h"
+
+//
+// Interface defintion of SMBUS Host Controller Protocol.
+//
+EFI_SMBUS_HC_PROTOCOL mSmbusHc = {
+ SmbusExecute,
+ SmbusArpDevice,
+ SmbusGetArpMap,
+ SmbusNotify
+};
+
+//
+// Handle to install SMBus Host Controller protocol.
+//
+STATIC EFI_HANDLE mHandle = NULL;
+UINT8 mDeviceMapEntries = 0;
+EFI_SMBUS_DEVICE_MAP mDeviceMap[MAX_SMBUS_DEVICES];
+UINT8 mPlatformNumRsvd = 0;
+UINT8 *mPlatformAddrRsvd = NULL;
+
+//
+// These addresses are reserved by the SMBus 2.0 specification
+//
+static UINT8 mReservedAddress[SMBUS_NUM_RESERVED] = {
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x18, 0x50, 0x6E, 0xC2,
+ 0xF0, 0xF2, 0xF4, 0xF6, 0xF8, 0xFA, 0xFC, 0xFE
+};
+
+
+/**
+ Gets Io port base address of Smbus Host Controller.
+
+ This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress
+ to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base
+ address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always
+ read Pci configuration space to get that value in each Smbus bus transaction.
+
+ @return The Io port base address of Smbus host controller.
+
+**/
+UINTN
+GetSmbusIoPortBaseAddress (
+ VOID
+ )
+{
+ UINTN IoPortBaseAddress;
+
+ if (FeaturePcdGet (PcdSmbaIoBaseAddressFixed)) {
+ IoPortBaseAddress = (UINTN) PcdGet16 (PcdSmbaIoBaseAddress);
+ } else {
+ IoPortBaseAddress = (UINTN) LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) & B_QNC_LPC_SMBUS_BASE_MASK;
+ }
+
+ //
+ // Make sure that the IO port base address has been properly set.
+ //
+ ASSERT (IoPortBaseAddress != 0);
+
+ return IoPortBaseAddress;
+}
+
+
+VOID
+InitializeInternal (
+ )
+{
+ UINTN IoPortBaseAddress;
+
+ IoPortBaseAddress = GetSmbusIoPortBaseAddress ();
+
+ //
+ // Step1: Enable QNC SMBUS I/O space.
+ //
+ LpcPciCfg32Or(R_QNC_LPC_SMBUS_BASE, B_QNC_LPC_SMBUS_BASE_EN);
+
+ //
+ // Step2: Clear Status Register before anyone uses the interfaces.
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
+
+ //
+ // Step3: Program the correct smbus clock
+ //
+ IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCLK, V_QNC_SMBUS_HCLK_100KHZ);
+}
+
+
+
+
+BOOLEAN
+IsAddressAvailable (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress
+ )
+{
+ UINT8 Index;
+
+ //
+ // See if we have already assigned this address to a device
+ //
+ for (Index = 0; Index < mDeviceMapEntries; Index++) {
+ if (SlaveAddress.SmbusDeviceAddress ==
+ mDeviceMap[Index].SmbusDeviceAddress.SmbusDeviceAddress) {
+ return FALSE;
+ }
+ }
+
+ //
+ // See if this address is claimed by a platform non-ARP-capable device
+ //
+ for (Index = 0; Index < mPlatformNumRsvd; Index++) {
+ if ((SlaveAddress.SmbusDeviceAddress << 1) == mPlatformAddrRsvd[Index]) {
+ return FALSE;
+ }
+ }
+
+ //
+ // See if this is a reserved address
+ //
+ for (Index = 0; Index < SMBUS_NUM_RESERVED; Index++) {
+ if (SlaveAddress.SmbusDeviceAddress == (UINTN) mReservedAddress[Index]) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+EFI_STATUS
+GetNextAvailableAddress (
+ IN EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress
+ )
+{
+ for (SlaveAddress->SmbusDeviceAddress = 0x03;
+ SlaveAddress->SmbusDeviceAddress < 0x7F;
+ SlaveAddress->SmbusDeviceAddress++
+ ) {
+ if (IsAddressAvailable (*SlaveAddress)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+EFI_STATUS
+SmbusPrepareToArp (
+ )
+{
+ EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 Buffer;
+
+ SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;
+ Length = 1;
+ Buffer = SMBUS_DATA_PREPARE_TO_ARP;
+
+ Status = Execute (
+ SlaveAddress,
+ 0,
+ EfiSmbusSendByte,
+ TRUE,
+ &Length,
+ &Buffer
+ );
+ return Status;
+}
+
+EFI_STATUS
+SmbusGetUdidGeneral (
+ IN OUT EFI_SMBUS_DEVICE_MAP *DeviceMap
+ )
+{
+ EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 Buffer[SMBUS_GET_UDID_LENGTH];
+
+ SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;
+ Length = SMBUS_GET_UDID_LENGTH;
+
+ Status = Execute (
+ SlaveAddress,
+ SMBUS_DATA_GET_UDID_GENERAL,
+ EfiSmbusReadBlock,
+ TRUE,
+ &Length,
+ Buffer
+ );
+
+ if (!EFI_ERROR(Status)) {
+ if (Length == SMBUS_GET_UDID_LENGTH) {
+ DeviceMap->SmbusDeviceUdid.DeviceCapabilities = Buffer[0];
+ DeviceMap->SmbusDeviceUdid.VendorRevision = Buffer[1];
+ DeviceMap->SmbusDeviceUdid.VendorId = (UINT16)((Buffer[2] << 8) + Buffer[3]);
+ DeviceMap->SmbusDeviceUdid.DeviceId = (UINT16)((Buffer[4] << 8) + Buffer[5]);
+ DeviceMap->SmbusDeviceUdid.Interface = (UINT16)((Buffer[6] << 8) + Buffer[7]);
+ DeviceMap->SmbusDeviceUdid.SubsystemVendorId = (UINT16)((Buffer[8] << 8) + Buffer[9]);
+ DeviceMap->SmbusDeviceUdid.SubsystemDeviceId = (UINT16)((Buffer[10] << 8) + Buffer[11]);
+ DeviceMap->SmbusDeviceUdid.VendorSpecificId = (UINT32)((Buffer[12] << 24) + (Buffer[13] << 16) + (Buffer[14] << 8) + Buffer[15]);
+ DeviceMap->SmbusDeviceAddress.SmbusDeviceAddress = (UINT8)(Buffer[16] >> 1);
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+SmbusAssignAddress (
+ IN OUT EFI_SMBUS_DEVICE_MAP *DeviceMap
+ )
+{
+ EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 Buffer[SMBUS_GET_UDID_LENGTH];
+
+ Buffer[0] = DeviceMap->SmbusDeviceUdid.DeviceCapabilities;
+ Buffer[1] = DeviceMap->SmbusDeviceUdid.VendorRevision;
+ Buffer[2] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorId >> 8);
+ Buffer[3] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorId);
+ Buffer[4] = (UINT8)(DeviceMap->SmbusDeviceUdid.DeviceId >> 8);
+ Buffer[5] = (UINT8)(DeviceMap->SmbusDeviceUdid.DeviceId);
+ Buffer[6] = (UINT8)(DeviceMap->SmbusDeviceUdid.Interface >> 8);
+ Buffer[7] = (UINT8)(DeviceMap->SmbusDeviceUdid.Interface);
+ Buffer[8] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemVendorId >> 8);
+ Buffer[9] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemVendorId);
+ Buffer[10] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemDeviceId >> 8);
+ Buffer[11] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemDeviceId);
+ Buffer[12] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 24);
+ Buffer[13] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 16);
+ Buffer[14] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 8);
+ Buffer[15] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId);
+ Buffer[16] = (UINT8)(DeviceMap->SmbusDeviceAddress.SmbusDeviceAddress << 1);
+
+ SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;
+ Length = SMBUS_GET_UDID_LENGTH;
+
+ Status = Execute (
+ SlaveAddress,
+ SMBUS_DATA_ASSIGN_ADDRESS,
+ EfiSmbusWriteBlock,
+ TRUE,
+ &Length,
+ Buffer
+ );
+ return Status;
+}
+
+
+EFI_STATUS
+SmbusFullArp (
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBUS_DEVICE_MAP *CurrentDeviceMap;
+
+ Status = SmbusPrepareToArp ();
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ //
+ // ARP is complete
+ //
+ return EFI_SUCCESS;
+ } else {
+ return Status;
+ }
+ }
+
+ //
+ // Main loop to ARP all ARP-capable devices
+ //
+ do {
+ CurrentDeviceMap = &mDeviceMap[mDeviceMapEntries];
+ Status = SmbusGetUdidGeneral (CurrentDeviceMap);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+
+ if (CurrentDeviceMap->SmbusDeviceAddress.SmbusDeviceAddress == (0xFF >> 1)) {
+ //
+ // If address is unassigned, assign it
+ //
+ Status = GetNextAvailableAddress (
+ &CurrentDeviceMap->SmbusDeviceAddress
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else if (((CurrentDeviceMap->SmbusDeviceUdid.DeviceCapabilities) & 0xC0) != 0) {
+ //
+ // if address is not fixed, check if the current address is available
+ //
+ if (!IsAddressAvailable (
+ CurrentDeviceMap->SmbusDeviceAddress
+ )) {
+ //
+ // if currently assigned address is already used, get a new one
+ //
+ Status = GetNextAvailableAddress (
+ &CurrentDeviceMap->SmbusDeviceAddress
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ }
+
+ Status = SmbusAssignAddress (CurrentDeviceMap);
+ if (EFI_ERROR(Status)) {
+ //
+ // If there was a device error, just continue on and try again.
+ // Other errors should be reported.
+ //
+ if (Status != EFI_DEVICE_ERROR) {
+ return Status;
+ }
+ } else {
+ //
+ // If there was no error, the address was assigned and we must update our
+ // records.
+ //
+ mDeviceMapEntries++;
+ }
+
+ } while (mDeviceMapEntries < MAX_SMBUS_DEVICES);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+SmbusDirectedArp (
+ IN EFI_SMBUS_UDID *SmbusUdid,
+ IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBUS_DEVICE_MAP *CurrentDeviceMap;
+
+ if (mDeviceMapEntries >= MAX_SMBUS_DEVICES) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentDeviceMap = &mDeviceMap[mDeviceMapEntries];
+
+ //
+ // Find an available address to assign
+ //
+ Status = GetNextAvailableAddress (
+ &CurrentDeviceMap->SmbusDeviceAddress
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentDeviceMap->SmbusDeviceUdid.DeviceCapabilities = SmbusUdid->DeviceCapabilities;
+ CurrentDeviceMap->SmbusDeviceUdid.DeviceId = SmbusUdid->DeviceId;
+ CurrentDeviceMap->SmbusDeviceUdid.Interface = SmbusUdid->Interface;
+ CurrentDeviceMap->SmbusDeviceUdid.SubsystemDeviceId = SmbusUdid->SubsystemDeviceId;
+ CurrentDeviceMap->SmbusDeviceUdid.SubsystemVendorId = SmbusUdid->SubsystemVendorId;
+ CurrentDeviceMap->SmbusDeviceUdid.VendorId = SmbusUdid->VendorId;
+ CurrentDeviceMap->SmbusDeviceUdid.VendorRevision = SmbusUdid->VendorRevision;
+ CurrentDeviceMap->SmbusDeviceUdid.VendorSpecificId = SmbusUdid->VendorSpecificId;
+
+ Status = SmbusAssignAddress (CurrentDeviceMap);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ mDeviceMapEntries++;
+ SlaveAddress->SmbusDeviceAddress = CurrentDeviceMap->SmbusDeviceAddress.SmbusDeviceAddress;
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Executes an SMBus operation to an SMBus controller. Returns when either the command has been
+ executed or an error is encountered in doing the operation.
+
+ The Execute() function provides a standard way to execute an operation as defined in the System
+ Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus
+ slave devices accept this transaction or that this function returns with error.
+
+ @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+ @param SlaveAddress The SMBus slave address of the device with which to communicate.
+ @param Command This command is transmitted by the SMBus host controller to the
+ SMBus slave device and the interpretation is SMBus slave device
+ specific. It can mean the offset to a list of functions inside an
+ SMBus slave device. Not all operations or slave devices support
+ this command's registers.
+ @param Operation Signifies which particular SMBus hardware protocol instance that
+ it will use to execute the SMBus transactions. This SMBus
+ hardware protocol is defined by the SMBus Specification and is
+ not related to EFI.
+ @param PecCheck Defines if Packet Error Code (PEC) checking is required for this
+ operation.
+ @param Length Signifies the number of bytes that this operation will do. The
+ maximum number of bytes can be revision specific and operation
+ specific. This field will contain the actual number of bytes that
+ are executed for this operation. Not all operations require this
+ argument.
+ @param Buffer Contains the value of data to execute to the SMBus slave device.
+ Not all operations require this argument. The length of this
+ buffer is identified by Length.
+
+ @retval EFI_SUCCESS The last data that was returned from the access matched the poll
+ exit criteria.
+ @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect).
+ @retval EFI_TIMEOUT Timeout expired before the operation was completed. Timeout is
+ determined by the SMBus host controller device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The request was not completed because a failure that was
+ reflected in the Host Status Register bit. Device errors are a
+ result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+ @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
+ @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
+ and EfiSmbusQuickWrite. Length is outside the range of valid
+ values.
+ @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusExecute (
+ IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+ IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN CONST EFI_SMBUS_DEVICE_COMMAND Command,
+ IN CONST EFI_SMBUS_OPERATION Operation,
+ IN CONST BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ InitializeInternal ();
+ return Execute (
+ SlaveAddress,
+ Command,
+ Operation,
+ PecCheck,
+ Length,
+ Buffer
+ );
+}
+
+/**
+ Sets the SMBus slave device addresses for the device with a given unique ID or enumerates the
+ entire bus.
+
+ The ArpDevice() function provides a standard way for a device driver to enumerate the entire
+ SMBus or specific devices on the bus.
+
+ @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+ @param ArpAll A Boolean expression that indicates if the host drivers need to
+ enumerate all the devices or enumerate only the device that is
+ identified by SmbusUdid. If ArpAll is TRUE, SmbusUdid and
+ SlaveAddress are optional. If ArpAll is FALSE, ArpDevice will
+ enumerate SmbusUdid and the address will be at SlaveAddress.
+ @param SmbusUdid The Unique Device Identifier (UDID) that is associated with this
+ device.
+ @param SlaveAddress The SMBus slave address that is associated with an SMBus UDID.
+
+ @retval EFI_SUCCESS The last data that was returned from the access matched the poll
+ exit criteria.
+ @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect).
+ @retval EFI_TIMEOUT Timeout expired before the operation was completed. Timeout is
+ determined by the SMBus host controller device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The request was not completed because a failure that was
+ reflected in the Host Status Register bit. Device errors are a
+ result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+ @retval EFI_UNSUPPORTED The corresponding SMBus operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusArpDevice (
+ IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+ IN CONST BOOLEAN ArpAll,
+ IN CONST EFI_SMBUS_UDID *SmbusUdid, OPTIONAL
+ IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL
+ )
+{
+ InitializeInternal ();
+
+ if (ArpAll) {
+ return SmbusFullArp ();
+ } else {
+ if ((SmbusUdid == NULL) || (SlaveAddress == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return SmbusDirectedArp ((EFI_SMBUS_UDID *)SmbusUdid, SlaveAddress);
+ }
+}
+
+/**
+ Returns a pointer to the Address Resolution Protocol (ARP) map that contains the ID/address pair
+ of the slave devices that were enumerated by the SMBus host controller driver.
+
+ The GetArpMap() function returns the mapping of all the SMBus devices that were enumerated by the
+ SMBus host driver.
+
+ @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+ @param Length Size of the buffer that contains the SMBus device map.
+ @param SmbusDeviceMap The pointer to the device map as enumerated by the SMBus
+ controller driver.
+
+ @retval EFI_SUCCESS The SMBus returned the current device map.
+ @retval EFI_UNSUPPORTED The corresponding operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusGetArpMap (
+ IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+ IN OUT UINTN *Length,
+ IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap
+ )
+{
+ *Length = mDeviceMapEntries;
+ *SmbusDeviceMap = mDeviceMap;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Allows a device driver to register for a callback when the bus driver detects a state that it
+ needs to propagate to other drivers that are registered for a callback.
+
+ The Notify() function registers all the callback functions to allow the bus driver to call these
+ functions when the SlaveAddress/Data pair happens.
+ If NotifyFunction is NULL, then ASSERT ().
+
+ @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+ @param SlaveAddress The SMBUS hardware address to which the SMBUS device is
+ preassigned or allocated.
+ @param Data Data of the SMBus host notify command that the caller wants to be
+ called.
+ @param NotifyFunction The function to call when the bus driver detects the SlaveAddress
+ and Data pair.
+
+ @retval EFI_SUCCESS NotifyFunction was registered.
+ @retval EFI_UNSUPPORTED The corresponding operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusNotify (
+ IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+ IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN CONST UINTN Data,
+ IN CONST EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Entry point to the DXE Driver that produces the SMBus Host Controller Protocol.
+
+ @param ImageHandle ImageHandle of the loaded driver.
+ @param SystemTable Pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point of SMBus DXE driver is executed successfully.
+ @retval !EFI_SUCESS Some error occurs in the entry point of SMBus DXE driver.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeQNCSmbus (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mPlatformNumRsvd = (UINT8)PcdGet32 (PcdPlatformSmbusAddrNum);
+ mPlatformAddrRsvd = (UINT8 *)(UINTN) PcdGet64 (PcdPlatformSmbusAddrTable);
+
+ //
+ // Install SMBus Host Controller protocol interface.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiSmbusHcProtocolGuid,
+ &mSmbusHc,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.h
new file mode 100644
index 0000000..2b62542
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.h
@@ -0,0 +1,229 @@
+/** @file
+ Header file for the defintions used in SMBus DXE driver.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#ifndef _DXE_QNC_SMBUS_H_
+#define _DXE_QNC_SMBUS_H_
+#include "CommonHeader.h"
+
+#include "QNCSmbus.h"
+
+#define MAX_SMBUS_DEVICES 107 // Max number of SMBus devices (7 bit
+ // address yields 128 combinations but 21
+ // of those are reserved)
+
+#define MICROSECOND 10
+#define MILLISECOND (1000 * MICROSECOND)
+#define ONESECOND (1000 * MILLISECOND)
+
+#define STALL_TIME 1000000 // 1,000,000 microseconds = 1 second
+#define BUS_TRIES 3 // How many times to retry on Bus Errors
+#define SMBUS_NUM_RESERVED 21 // Number of device addresses that are
+ // reserved by the SMBus spec.
+#define SMBUS_ADDRESS_ARP 0xC2 >> 1
+#define SMBUS_DATA_PREPARE_TO_ARP 0x01
+#define SMBUS_DATA_RESET_DEVICE 0x02
+#define SMBUS_DATA_GET_UDID_GENERAL 0x03
+#define SMBUS_DATA_ASSIGN_ADDRESS 0x04
+#define SMBUS_GET_UDID_LENGTH 17 // 16 byte UDID + 1 byte address
+
+/**
+ Executes an SMBus operation to an SMBus controller. Returns when either the command has been
+ executed or an error is encountered in doing the operation.
+
+ The Execute() function provides a standard way to execute an operation as defined in the System
+ Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus
+ slave devices accept this transaction or that this function returns with error.
+
+ @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+ @param SlaveAddress The SMBus slave address of the device with which to communicate.
+ @param Command This command is transmitted by the SMBus host controller to the
+ SMBus slave device and the interpretation is SMBus slave device
+ specific. It can mean the offset to a list of functions inside an
+ SMBus slave device. Not all operations or slave devices support
+ this command's registers.
+ @param Operation Signifies which particular SMBus hardware protocol instance that
+ it will use to execute the SMBus transactions. This SMBus
+ hardware protocol is defined by the SMBus Specification and is
+ not related to EFI.
+ @param PecCheck Defines if Packet Error Code (PEC) checking is required for this
+ operation.
+ @param Length Signifies the number of bytes that this operation will do. The
+ maximum number of bytes can be revision specific and operation
+ specific. This field will contain the actual number of bytes that
+ are executed for this operation. Not all operations require this
+ argument.
+ @param Buffer Contains the value of data to execute to the SMBus slave device.
+ Not all operations require this argument. The length of this
+ buffer is identified by Length.
+
+ @retval EFI_SUCCESS The last data that was returned from the access matched the poll
+ exit criteria.
+ @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect).
+ @retval EFI_TIMEOUT Timeout expired before the operation was completed. Timeout is
+ determined by the SMBus host controller device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The request was not completed because a failure that was
+ reflected in the Host Status Register bit. Device errors are a
+ result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+ @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
+ @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
+ and EfiSmbusQuickWrite. Length is outside the range of valid
+ values.
+ @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusExecute (
+ IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+ IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN CONST EFI_SMBUS_DEVICE_COMMAND Command,
+ IN CONST EFI_SMBUS_OPERATION Operation,
+ IN CONST BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Sets the SMBus slave device addresses for the device with a given unique ID or enumerates the
+ entire bus.
+
+ The ArpDevice() function provides a standard way for a device driver to enumerate the entire
+ SMBus or specific devices on the bus.
+
+ @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+ @param ArpAll A Boolean expression that indicates if the host drivers need to
+ enumerate all the devices or enumerate only the device that is
+ identified by SmbusUdid. If ArpAll is TRUE, SmbusUdid and
+ SlaveAddress are optional. If ArpAll is FALSE, ArpDevice will
+ enumerate SmbusUdid and the address will be at SlaveAddress.
+ @param SmbusUdid The Unique Device Identifier (UDID) that is associated with this
+ device.
+ @param SlaveAddress The SMBus slave address that is associated with an SMBus UDID.
+
+ @retval EFI_SUCCESS The last data that was returned from the access matched the poll
+ exit criteria.
+ @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect).
+ @retval EFI_TIMEOUT Timeout expired before the operation was completed. Timeout is
+ determined by the SMBus host controller device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The request was not completed because a failure that was
+ reflected in the Host Status Register bit. Device errors are a
+ result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+ @retval EFI_UNSUPPORTED The corresponding operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusArpDevice (
+ IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+ IN CONST BOOLEAN ArpAll,
+ IN CONST EFI_SMBUS_UDID *SmbusUdid, OPTIONAL
+ IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL
+ );
+
+/**
+ Returns a pointer to the Address Resolution Protocol (ARP) map that contains the ID/address pair
+ of the slave devices that were enumerated by the SMBus host controller driver.
+
+ The GetArpMap() function returns the mapping of all the SMBus devices that were enumerated by the
+ SMBus host driver.
+
+ @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+ @param Length Size of the buffer that contains the SMBus device map.
+ @param SmbusDeviceMap The pointer to the device map as enumerated by the SMBus
+ controller driver.
+
+ @retval EFI_SUCCESS The SMBus returned the current device map.
+ @retval EFI_UNSUPPORTED The corresponding operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusGetArpMap (
+ IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+ IN OUT UINTN *Length,
+ IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap
+ );
+
+/**
+ Allows a device driver to register for a callback when the bus driver detects a state that it
+ needs to propagate to other drivers that are registered for a callback.
+
+ The Notify() function registers all the callback functions to allow the bus driver to call these
+ functions when the SlaveAddress/Data pair happens.
+ If NotifyFunction is NULL, then ASSERT ().
+
+ @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+ @param SlaveAddress The SMBUS hardware address to which the SMBUS device is
+ preassigned or allocated.
+ @param Data Data of the SMBus host notify command that the caller wants to be
+ called.
+ @param NotifyFunction The function to call when the bus driver detects the SlaveAddress
+ and Data pair.
+
+ @retval EFI_SUCCESS NotifyFunction was registered.
+ @retval EFI_UNSUPPORTED The corresponding operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusNotify (
+ IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+ IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN CONST UINTN Data,
+ IN CONST EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction
+ );
+
+/**
+ Entry point to the DXE Driver that produces the SMBus Host Controller Protocol.
+
+ @param ImageHandle ImageHandle of the loaded driver.
+ @param SystemTable Pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point of SMBus DXE driver is executed successfully.
+ @retval !EFI_SUCESS Some error occurs in the entry point of SMBus DXE driver.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeQNCSmbus (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyInterrupt.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyInterrupt.c
new file mode 100644
index 0000000..23114c9
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyInterrupt.c
@@ -0,0 +1,240 @@
+/** @file
+ Legacy Interrupt Component.
+
+ This component implements the Legacy Interrupt Protocol defined in the Framework CSM Spec.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+#include "CommonHeader.h"
+#include "LegacyInterrupt.h"
+
+//
+// Protocol interface function prototypes
+//
+
+EFI_STATUS
+EFIAPI
+GetNumberPirqs (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *NumberPirqs
+ );
+
+EFI_STATUS
+EFIAPI
+GetLocation (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device,
+ OUT UINT8 *Function
+ );
+
+EFI_STATUS
+EFIAPI
+ReadPirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ OUT UINT8 *PirqData
+ );
+
+EFI_STATUS
+EFIAPI
+WritePirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ IN UINT8 PirqData
+ );
+
+//
+// Handle for the Legacy Interrupt Protocol instance produced by this driver
+//
+static EFI_HANDLE mLegacyInterruptHandle = NULL;
+
+//
+// The Legacy Interrupt Protocol instance produced by this driver
+//
+static EFI_LEGACY_INTERRUPT_PROTOCOL mLegacyInterrupt = {
+ GetNumberPirqs,
+ GetLocation,
+ ReadPirq,
+ WritePirq
+};
+
+//
+// PIRQ Route Control registers' offsets within the LPC configuration space for PIRQA~H
+//
+static UINT8 mPirqRouteReg[QNC_NUMBER_PIRQS] = {
+ R_QNC_LPC_PIRQA_ROUT,
+ R_QNC_LPC_PIRQB_ROUT,
+ R_QNC_LPC_PIRQC_ROUT,
+ R_QNC_LPC_PIRQD_ROUT,
+ R_QNC_LPC_PIRQE_ROUT,
+ R_QNC_LPC_PIRQF_ROUT,
+ R_QNC_LPC_PIRQG_ROUT,
+ R_QNC_LPC_PIRQH_ROUT
+};
+
+/**
+ Gets the number of PIRQs that this hardware supports.
+
+ @param[in] This Indicates the EFI_LEGACY_INTERRUPT_PROTOCOL instance.
+ @param[out] NumberPirqs Number of PIRQs that are supported.
+
+ @retval EFI_SUCCESS The number of PIRQs was returned successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberPirqs (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *NumberPirqs
+ )
+{
+ ASSERT (NumberPirqs != NULL);
+
+ *NumberPirqs = QNC_NUMBER_PIRQS;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets the PCI location associated with this protocol.
+
+ @param[in] This Indicates the EFI_LEGACY_INTERRUPT_PROTOCOL instance.
+ @param[out] Bus PCI bus number of this device.
+ @param[out] Device PCI device number of this device.
+ @param[out] Function PCI function number of this device.
+
+ @retval EFI_SUCCESS The PCI location was returned successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+GetLocation (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device,
+ OUT UINT8 *Function
+ )
+{
+ ASSERT (Bus != NULL && Device != NULL && Function != NULL);
+
+ *Bus = PCI_BUS_NUMBER_QNC;
+ *Device = PCI_DEVICE_NUMBER_QNC_LPC;
+ *Function = PCI_FUNCTION_NUMBER_QNC_LPC;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads the given PIRQ register and returns the IRQ that is assigned to it.
+
+ @param[in] This Indicates the EFI_LEGACY_INTERRUPT_PROTOCOL instance.
+ @param[in] PirqNumber PIRQ A = 0, PIRQ B = 1, and so on.
+ @param[out] PirqData IRQ assigned to this PIRQ.
+
+ @retval EFI_SUCCESS The data was returned successfully.
+ @retval EFI_INVALID_PARAMETER The PIRQ number invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+ReadPirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ OUT UINT8 *PirqData
+ )
+{
+ if (PirqNumber >= QNC_NUMBER_PIRQS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (PirqData != NULL);
+
+ *PirqData = (UINT8)(PciRead8 (PCI_QNC_LPC_ADDRESS (mPirqRouteReg[PirqNumber])) & 0x7f);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Writes data to the specified PIRQ register.
+
+ @param[in] This Indicates the EFI_LEGACY_INTERRUPT_PROTOCOL instance.
+ @param[in] PirqNumber PIRQ A = 0, PIRQ B = 1, and so on.
+ @param[in] PirqData IRQ assigned to this PIRQ.
+
+ @retval EFI_SUCCESS The PIRQ was programmed.
+ @retval EFI_INVALID_PARAMETER The PIRQ number invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+WritePirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ IN UINT8 PirqData
+ )
+{
+ if (PirqNumber >= QNC_NUMBER_PIRQS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciWrite8 (PCI_QNC_LPC_ADDRESS (mPirqRouteReg[PirqNumber]), PirqData);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Install Legacy Interrupt Protocol.
+
+ @retval EFI_SUCCESS Installed Legacy Interrupt Protocol successfully.
+ @retval !EFI_SUCESS Error installing Legacy Interrupt Protocol.
+
+**/
+EFI_STATUS
+LegacyInterruptInstall (
+ VOID
+ )
+{
+ //
+ // Make sure the Legacy Interrupt Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiLegacyInterruptProtocolGuid);
+
+ //
+ // Make a new handle and install the protocol
+ //
+ return gBS->InstallMultipleProtocolInterfaces (
+ &mLegacyInterruptHandle,
+ &gEfiLegacyInterruptProtocolGuid,
+ &mLegacyInterrupt,
+ NULL
+ );
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyInterrupt.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyInterrupt.h
new file mode 100644
index 0000000..4c700be
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyInterrupt.h
@@ -0,0 +1,58 @@
+/** @file
+ Legacy Interrupt Component.
+
+ This component implements the Legacy Interrupt Protocol defined in the Framework CSM Spec.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+
+#ifndef _LEGACY_INTERRUPT_H_
+#define _LEGACY_INTERRUPT_H_
+
+#include <IndustryStandard/Pci22.h>
+
+#define QNC_NUMBER_PIRQS 8
+
+#define PCI_QNC_LPC_ADDRESS(Register) \
+ ((UINTN)(PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, Register)))
+
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+
+EFI_STATUS
+LegacyInterruptInstall (
+ VOID
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.c
new file mode 100644
index 0000000..4e75af0
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.c
@@ -0,0 +1,261 @@
+/** @file
+ QNC Legacy Region Driver
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "CommonHeader.h"
+#include "LegacyRegion.h"
+
+//
+// Handle used to install the Legacy Region Protocol
+//
+EFI_HANDLE mHandle = NULL;
+
+//
+// Instance of the Legacy Region Protocol to install into the handle database
+//
+EFI_LEGACY_REGION2_PROTOCOL mLegacyRegion2 = {
+ LegacyRegion2Decode,
+ LegacyRegion2Lock,
+ LegacyRegion2BootLock,
+ LegacyRegion2Unlock,
+ LegacyRegionGetInfo
+};
+
+
+/**
+ Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
+
+ If the On parameter evaluates to TRUE, this function enables memory reads in the address range
+ Start to (Start + Length - 1).
+ If the On parameter evaluates to FALSE, this function disables memory reads in the address range
+ Start to (Start + Length - 1).
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose attributes
+ should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address
+ was not aligned to a region's starting address or if the length
+ was greater than the number of bytes in the first region.
+ @param On[in] Decode / Non-Decode flag.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Decode (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity,
+ IN BOOLEAN *On
+ )
+{
+ return QNCLegacyRegionManipulation (Start, Length, On, NULL, Granularity);
+}
+
+
+/**
+ Modify the hardware to disallow memory attribute changes in a region.
+
+ This function makes the attributes of a region read only. Once a region is boot-locked with this
+ function, the read and write attributes of that region cannot be changed until a power cycle has
+ reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+ @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in
+ a way that will not affect memory regions outside the legacy memory
+ region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2BootLock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Modify the hardware to disallow memory writes in a region.
+
+ This function changes the attributes of a memory range to not allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Lock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ BOOLEAN WriteEnable;
+
+ WriteEnable = FALSE;
+ return QNCLegacyRegionManipulation (Start, Length, NULL, &WriteEnable, Granularity);
+}
+
+
+/**
+ Modify the hardware to allow memory writes in a region.
+
+ This function changes the attributes of a memory range to allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Unlock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ BOOLEAN WriteEnable;
+
+ WriteEnable = TRUE;
+ return QNCLegacyRegionManipulation (Start, Length, NULL, &WriteEnable, Granularity);
+}
+
+/**
+ Get region information for the attributes of the Legacy Region.
+
+ This function is used to discover the granularity of the attributes for the memory in the legacy
+ region. Each attribute may have a different granularity and the granularity may not be the same
+ for all memory ranges in the legacy region.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor
+ buffer.
+ @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy
+ region information is deposited. This buffer will contain a list of
+ DescriptorCount number of region descriptors. This function will
+ provide the memory for the buffer.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegionGetInfo (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ OUT UINT32 *DescriptorCount,
+ OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor
+ )
+{
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Entry point to the DXE Driver that produces the Legacy Region Protocol.
+
+ @retval EFI_SUCCESS One or more of the drivers returned a success code.
+ @retval !EFI_SUCESS The return status from the last driver entry point in the list.
+
+**/
+EFI_STATUS
+LegacyRegionInit (
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install the Legacy Region Protocol on a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiLegacyRegion2ProtocolGuid, &mLegacyRegion2,
+ NULL
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.h
new file mode 100644
index 0000000..51d0956
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.h
@@ -0,0 +1,222 @@
+/** @file
+ The header file legacy region initialization in QNC DXE component.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _LEGACY_REGION_H_
+#define _LEGACY_REGION_H_
+#include "CommonHeader.h"
+
+#include <IndustryStandard/Pci.h>
+
+#define LEGACY_REGION_INSTANCE_SIGNATURE SIGNATURE_32('R','E','G','N')
+
+typedef struct {
+ UINT32 Signature;
+
+ EFI_HANDLE Handle;
+ EFI_LEGACY_REGION2_PROTOCOL LegacyRegion2;
+ EFI_HANDLE ImageHandle;
+
+ //
+ // Protocol for PAM register access
+ //
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+} LEGACY_REGION_INSTANCE;
+
+#define LEGACY_REGION_INSTANCE_FROM_THIS(this) \
+ CR(this, LEGACY_REGION_INSTANCE, LegacyRegion2, LEGACY_REGION_INSTANCE_SIGNATURE)
+
+
+EFI_STATUS
+LegacyRegionManipluateRegion (
+ IN LEGACY_REGION_INSTANCE *Private
+ );
+
+EFI_STATUS
+LegacyRegionInit (
+ VOID
+ );
+
+/**
+ Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
+
+ If the On parameter evaluates to TRUE, this function enables memory reads in the address range
+ Start to (Start + Length - 1).
+ If the On parameter evaluates to FALSE, this function disables memory reads in the address range
+ Start to (Start + Length - 1).
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose attributes
+ should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address
+ was not aligned to a region's starting address or if the length
+ was greater than the number of bytes in the first region.
+ @param On[in] Decode / Non-Decode flag.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Decode (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity,
+ IN BOOLEAN *On
+ );
+
+/**
+ Modify the hardware to disallow memory writes in a region.
+
+ This function changes the attributes of a memory range to not allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Lock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Modify the hardware to disallow memory attribute changes in a region.
+
+ This function makes the attributes of a region read only. Once a region is boot-locked with this
+ function, the read and write attributes of that region cannot be changed until a power cycle has
+ reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+ @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in
+ a way that will not affect memory regions outside the legacy memory
+ region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2BootLock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Modify the hardware to allow memory writes in a region.
+
+ This function changes the attributes of a memory range to allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Unlock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Get region information for the attributes of the Legacy Region.
+
+ This function is used to discover the granularity of the attributes for the memory in the legacy
+ region. Each attribute may have a different granularity and the granularity may not be the same
+ for all memory ranges in the legacy region.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor
+ buffer.
+ @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy
+ region information is deposited. This buffer will contain a list of
+ DescriptorCount number of region descriptors. This function will
+ provide the memory for the buffer.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegionGetInfo (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ OUT UINT32 *DescriptorCount,
+ OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor
+ );
+
+#endif //_QNC_LEGACY_REGION_H_
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.c
new file mode 100644
index 0000000..076e5ee
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.c
@@ -0,0 +1,431 @@
+/** @file
+ QuarkNcSocId module initialization module
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "CommonHeader.h"
+
+#include "LegacyRegion.h"
+#include "DxeQNCSmbus.h"
+#include "LegacyInterrupt.h"
+#include "SmartTimer.h"
+#include "QNCInit.h"
+
+//
+// Definitions
+//
+#define QNC_RESERVED_ITEM_IO 0
+#define QNC_RESERVED_ITEM_MEMORYIO 1
+#define DXE_DEVICE_DISABLED 0
+#define DXE_DEVICE_ENABLED 1
+
+typedef struct _QNC_SPACE_TABLE_ITEM {
+ UINTN IoOrMemory;
+ UINTN Type;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ UINTN Alignment;
+ BOOLEAN RuntimeOrNot;
+}QNC_SPACE_TABLE_ITEM;
+
+//
+// Spaces to be reserved in GCD
+// Expand it to add more
+//
+const QNC_SPACE_TABLE_ITEM mQNCReservedSpaceTable[] = {
+ {
+ QNC_RESERVED_ITEM_MEMORYIO,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ FixedPcdGet64 (PcdIoApicBaseAddress),
+ FixedPcdGet64 (PcdIoApicSize),
+ 0,
+ FALSE
+ },
+ {
+ QNC_RESERVED_ITEM_MEMORYIO,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ FixedPcdGet64 (PcdHpetBaseAddress),
+ FixedPcdGet64 (PcdHpetSize),
+ 0,
+ FALSE
+ }
+};
+
+//
+// Global variable for ImageHandle of QNCInit driver
+//
+EFI_HANDLE gQNCInitImageHandle;
+QNC_DEVICE_ENABLES mQNCDeviceEnables;
+
+
+VOID
+QNCInitializeResource (
+ VOID
+ );
+
+EFI_STATUS
+InitializeQNCPolicy (
+ VOID
+ );
+
+/**
+ The entry function for QNCInit driver.
+
+ This function just call initialization function for PciHostBridge,
+ LegacyRegion and QNCSmmAccess module.
+
+ @param ImageHandle The driver image handle for GmchInit driver
+ @param SystemTable The pointer to System Table
+
+ @retval EFI_SUCCESS Success to initialize every module for GMCH driver.
+ @return EFI_STATUS The status of initialization work.
+
+**/
+EFI_STATUS
+EFIAPI
+QNCInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ S3BootScriptSaveInformationAsciiString (
+ "QNCInitDxeEntryBegin"
+ );
+
+ gQNCInitImageHandle = ImageHandle;
+
+ mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);
+
+
+ //
+ // Initialize PCIE root ports
+ //
+ Status = QncInitRootPorts ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "QNC Root Port initialization is failed!\n"));
+ return Status;
+ }
+
+ Status = LegacyRegionInit ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "QNC LegacyRegion initialization is failed!\n"));
+ return Status;
+ }
+
+
+ Status = InitializeQNCPolicy ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "QNC Policy initialization is failed!\n"));
+ return Status;
+ }
+
+ Status = InitializeQNCSmbus (ImageHandle,SystemTable);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "QNC Smbus driver is failed!\n"));
+ return Status;
+ }
+
+ Status = LegacyInterruptInstall ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "QNC Legacy Interrupt driver is failed!\n"));
+ return Status;
+ }
+
+ Status = TimerDriverInitialize (ImageHandle,SystemTable);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "QNC Smart Timer driver is failed!\n"));
+ return Status;
+ }
+
+ QNCInitializeResource ();
+
+ S3BootScriptSaveInformationAsciiString (
+ "QNCInitDxeEntryEnd"
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reserve I/O or memory space in GCD
+
+ @param IoOrMemory Switch of I/O or memory.
+ @param GcdType Type of the space.
+ @param BaseAddress Base address of the space.
+ @param Length Length of the space.
+ @param Alignment Align with 2^Alignment
+ @param RuntimeOrNot For runtime usage or not
+ @param ImageHandle Handle for the image of this driver.
+
+ @retval EFI_SUCCESS Reserve successful
+**/
+EFI_STATUS
+QNCReserveSpaceInGcd(
+ IN UINTN IoOrMemory,
+ IN UINTN GcdType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINTN Alignment,
+ IN BOOLEAN RuntimeOrNot,
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ if (IoOrMemory == QNC_RESERVED_ITEM_MEMORYIO) {
+ Status = gDS->AddMemorySpace (
+ GcdType,
+ BaseAddress,
+ Length,
+ EFI_MEMORY_UC
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "Failed to add memory space :0x%x 0x%x\n",
+ BaseAddress,
+ Length
+ ));
+ }
+ ASSERT_EFI_ERROR (Status);
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ GcdType,
+ Alignment,
+ Length,
+ &BaseAddress,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (RuntimeOrNot) {
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ Status = gDS->AddIoSpace (
+ GcdType,
+ BaseAddress,
+ Length
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = gDS->AllocateIoSpace (
+ EfiGcdAllocateAddress,
+ GcdType,
+ Alignment,
+ Length,
+ &BaseAddress,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ return Status;
+}
+
+
+/**
+ Initialize the memory and io resource which belong to QNC.
+ 1) Report and allocate all BAR's memory to GCD.
+ 2) Report PCI memory and I/O space to GCD.
+ 3) Set memory attribute for <1M memory space.
+**/
+VOID
+QNCInitializeResource (
+ )
+{
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_STATUS Status;
+ UINT64 ExtraRegionLength;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
+ UINTN Index;
+
+ // Report TSEG range
+ // This range maybe has been reportted in PEI phase via Resource Hob.
+ //
+ QNCGetTSEGMemoryRange (&BaseAddress, &ExtraRegionLength);
+ if (ExtraRegionLength != 0) {
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &Descriptor);
+ if (Status == EFI_NOT_FOUND) {
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeReserved,
+ BaseAddress,
+ ExtraRegionLength,
+ EFI_MEMORY_UC
+ );
+ }
+ }
+
+ //
+ // < 1M resource setting. The memory ranges <1M has been added into GCD via
+ // resource hob produced by PEI phase. Here will set memory attribute of these
+ // ranges for DXE phase.
+ //
+
+ //
+ // Dos Area (0 ~ 0x9FFFFh)
+ //
+ Status = gDS->GetMemorySpaceDescriptor (0, &Descriptor);
+ DEBUG ((
+ EFI_D_INFO,
+ "DOS Area Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",
+ Descriptor.BaseAddress,
+ Descriptor.Length,
+ Descriptor.Attributes
+ ));
+ ASSERT_EFI_ERROR (Status);
+ Status = gDS->SetMemorySpaceAttributes(
+ 0,
+ 0xA0000,
+ EFI_MEMORY_WB
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE
+ // Workaround to make default SMRAM UnCachable
+ //
+ Status = gDS->SetMemorySpaceAttributes(
+ 0x30000,
+ 0x10000,
+ EFI_MEMORY_UC
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Default SMM ABSEG area. (0xA0000 ~ 0xBFFFF)
+ //
+ Status = gDS->GetMemorySpaceDescriptor (0xA0000, &Descriptor);
+ DEBUG ((
+ EFI_D_INFO,
+ "ABSEG Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",
+ Descriptor.BaseAddress,
+ Descriptor.Length,
+ Descriptor.Attributes
+ ));
+ ASSERT_EFI_ERROR (Status);
+ Status = gDS->SetMemorySpaceAttributes(
+ 0xA0000,
+ 0x20000,
+ EFI_MEMORY_UC
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Expansion BIOS area.
+ //
+ Status = gDS->GetMemorySpaceDescriptor (0xC0000, &Descriptor);
+ DEBUG ((
+ EFI_D_INFO,
+ "Memory base = 0x%x, length = 0x%x, attribute = 0x%x\n",
+ Descriptor.BaseAddress,
+ Descriptor.Length,
+ Descriptor.Attributes
+ ));
+ ASSERT_EFI_ERROR (Status);
+ Status = gDS->SetMemorySpaceAttributes(
+ 0xC0000,
+ 0x30000,
+ EFI_MEMORY_UC
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Report other IO resources from mQNCReservedSpaceTable in GCD
+ //
+ for (Index = 0; Index < sizeof (mQNCReservedSpaceTable) / sizeof (QNC_SPACE_TABLE_ITEM); Index++) {
+ Status = QNCReserveSpaceInGcd (
+ mQNCReservedSpaceTable[Index].IoOrMemory,
+ mQNCReservedSpaceTable[Index].Type,
+ mQNCReservedSpaceTable[Index].BaseAddress,
+ mQNCReservedSpaceTable[Index].Length,
+ mQNCReservedSpaceTable[Index].Alignment,
+ mQNCReservedSpaceTable[Index].RuntimeOrNot,
+ gQNCInitImageHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Report unused PCIe config space as reserved.
+ //
+ if (FixedPcdGet64 (PcdPciExpressSize) < SIZE_256MB) {
+ Status = QNCReserveSpaceInGcd (
+ QNC_RESERVED_ITEM_MEMORYIO,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ (PcdGet64(PcdPciExpressBaseAddress) + PcdGet64(PcdPciExpressSize)),
+ (SIZE_256MB - PcdGet64(PcdPciExpressSize)),
+ 0,
+ FALSE,
+ gQNCInitImageHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+/**
+ Use the platform PCD to initialize devices in the QNC
+
+ @param ImageHandle Handle for the image of this driver.
+ @retval EFI_SUCCESS Initialize successful
+**/
+EFI_STATUS
+InitializeQNCPolicy (
+ )
+{
+ UINT8 RevisionID;
+ UINT32 PciD31F0RegBase; // LPC
+
+ RevisionID = LpcPciCfg8(R_QNC_LPC_REV_ID);
+
+ PciD31F0RegBase = PciDeviceMmBase (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC);
+
+ //
+ // Disable for smbus
+ //
+ if (mQNCDeviceEnables.Bits.Smbus == DXE_DEVICE_DISABLED) {
+ S3MmioAnd32 (PciD31F0RegBase + R_QNC_LPC_SMBUS_BASE, (~B_QNC_LPC_SMBUS_BASE_EN));
+ }
+
+ //
+ // Initialize 8254 Timer #1
+ //
+ S3IoWrite8 (TIMER_CONTROL_PORT, 0x54);
+ S3IoWrite8 (TIMER1_COUNT_PORT, 0x12);
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.h
new file mode 100644
index 0000000..78557bf
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.h
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QncInit.h
+
+Abstract:
+
+ Header file for QNC Initialization Driver.
+
+--*/
+#ifndef _QNC_INITIALIZATION_DRIVER_H_
+#define _QNC_INITIALIZATION_DRIVER_H_
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+#include <Protocol/QncS3Support.h>
+#include <Library/IntelQNCLib.h>
+
+EFI_STATUS
+QncInitRootPorts (
+ )
+/*++
+
+Routine Description:
+
+ Perform Initialization of the Downstream Root Ports.
+
+Arguments:
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+SetInitRootPortDownstreamS3Item (
+ )
+/*++
+
+Routine Description:
+
+ Set an Init Root Port Downstream devices S3 dispatch item, this function may assert if any error happend
+
+Arguments:
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully
+
+--*/
+;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf
new file mode 100644
index 0000000..57b2307
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf
@@ -0,0 +1,148 @@
+## @file
+# Component description file for QNCInit driver.
+#
+# QNCInit driver implement QuarkNcSocId related drivers, includes:
+# PciHostBridge, PciExpress, SmmAccess driver and LegacyRegion driver.
+#
+# This driver mainly do full initialization for the QNC chipet includes:
+# 1. Initialize the PCI Express device.
+# 2. Initialize the PciHostBridge, and allocate the I/O and memory space from GCD service.
+# 3. Initialize the SmmAccess module and install EFI_SMM_ACCESS_PROTOCOL
+# 4. Initialize the LegacyRegion module, install EFI_LEGACY_REGION_PROTOCOL and set below 1M
+# memory attribute from MTRR.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QNCInitDxe
+ FILE_GUID = 74D3B506-EE9C-47ed-B749-41261401DA78
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = QNCInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ LegacyRegion.h
+ LegacyRegion.c
+ DxeQNCSmbus.c
+ DxeQNCSmbus.h
+ QNCSmbusExec.c
+ QNCSmbus.h
+ LegacyInterrupt.c
+ LegacyInterrupt.h
+ SmartTimer.c
+ SmartTimer.h
+ QNCInit.c
+ QNCInit.h
+ CommonHeader.h
+ QNCRootPorts.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[LibraryClasses]
+ S3BootScriptLib
+ PcdLib
+ HobLib
+ PciLib
+ IntelQNCLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ S3PciLib
+ UefiLib
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+ UefiDriverEntryPoint
+ BaseLib
+ TimerLib
+ S3IoLib
+ IoLib
+ DevicePathLib
+ QNCAccessLib
+ SmbusLib
+
+[Guids]
+ gEfiSmmPeiSmramMemoryReserveGuid # ALWAYS_CONSUMED
+
+[Protocols]
+ gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSmmAccess2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiLegacyRegion2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiPciRootBridgeIoProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiPciHostBridgeResourceAllocationProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiMetronomeArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiPciHotPlugInitProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmbusHcProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmControlProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiTimerArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiLegacy8259ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyInterruptProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiCpuArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiQncS3SupportProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[FeaturePcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddressFixed
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdUseAcpiTimerInSmartTimer
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciexpressHotplugEnabled
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciExpressSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeIoBase
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeIoSize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPlatformSmbusAddrNum
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPlatformSmbusAddrTable
+
+[Depex]
+ gEfiPlatformPolicyProtocolGuid AND gEfiCpuIo2ProtocolGuid AND gEfiMetronomeArchProtocolGuid AND gEfiCpuArchProtocolGuid AND gEfiS3SaveStateProtocolGuid
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCRootPorts.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCRootPorts.c
new file mode 100644
index 0000000..2aae22e
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCRootPorts.c
@@ -0,0 +1,123 @@
+/** @file
+ PciHostBridge driver module, part of QNC module.
+
+ Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "CommonHeader.h"
+#include "QNCInit.h"
+
+EFI_STATUS
+QncInitRootPorts (
+ )
+/*++
+
+Routine Description:
+
+ Perform Initialization of the Downstream Root Ports
+
+Arguments:
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = PciExpressInit ();
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SetInitRootPortDownstreamS3Item ();
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+EFI_STATUS
+SetInitRootPortDownstreamS3Item (
+ )
+/*++
+
+Routine Description:
+
+ Set an Init Root Port Downstream devices S3 dispatch item, this function may assert if any error happend
+
+Arguments:
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *Context;
+ VOID *S3DispatchEntryPoint;
+ STATIC EFI_QNC_S3_SUPPORT_PROTOCOL *QncS3Support;
+ STATIC UINT32 S3ParameterRootPortDownstream=0;
+ STATIC EFI_QNC_S3_DISPATCH_ITEM S3DispatchItem = {
+ QncS3ItemTypeInitPcieRootPortDownstream,
+ &S3ParameterRootPortDownstream
+ };
+
+ if (!QncS3Support) {
+ //
+ // Get the QNC S3 Support Protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiQncS3SupportProtocolGuid,
+ NULL,
+ &QncS3Support
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = QncS3Support->SetDispatchItem (
+ QncS3Support,
+ &S3DispatchItem,
+ &S3DispatchEntryPoint,
+ &Context
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Save the script dispatch item in the Boot Script
+ //
+ Status = S3BootScriptSaveDispatch2 (S3DispatchEntryPoint, Context);
+ ASSERT_EFI_ERROR (Status);
+ //
+ return Status;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbus.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbus.h
new file mode 100644
index 0000000..1e28622
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbus.h
@@ -0,0 +1,104 @@
+/** @file
+ Common definitons for SMBus PEIM/DXE driver. Smbus PEI and DXE
+ modules share the same version of this file.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _QNC_SMBUS_H_
+#define _QNC_SMBUS_H_
+
+#include "CommonHeader.h"
+
+//
+// Minimum and maximum length for SMBus bus block protocols defined in SMBus spec 2.0.
+//
+#define MIN_SMBUS_BLOCK_LEN 1
+#define MAX_SMBUS_BLOCK_LEN 32
+#define ADD_LENGTH(SmbusAddress, Length) ((SmbusAddress) + SMBUS_LIB_ADDRESS (0, 0, (Length), FALSE))
+
+/**
+ Executes an SMBus operation to an SMBus controller. Returns when either the command has been
+ executed or an error is encountered in doing the operation.
+
+ The internal worker function provides a standard way to execute an operation as defined in the
+ System Management Bus (SMBus) Specification. The resulting transaction will be either that the
+ SMBus slave devices accept this transaction or that this function returns with error.
+
+ @param SlaveAddress The SMBus slave address of the device with which to communicate.
+ @param Command This command is transmitted by the SMBus host controller to the
+ SMBus slave device and the interpretation is SMBus slave device
+ specific. It can mean the offset to a list of functions inside an
+ SMBus slave device. Not all operations or slave devices support
+ this command's registers.
+ @param Operation Signifies which particular SMBus hardware protocol instance that
+ it will use to execute the SMBus transactions. This SMBus
+ hardware protocol is defined by the SMBus Specification and is
+ not related to EFI.
+ @param PecCheck Defines if Packet Error Code (PEC) checking is required for this
+ operation.
+ @param Length Signifies the number of bytes that this operation will do. The
+ maximum number of bytes can be revision specific and operation
+ specific. This field will contain the actual number of bytes that
+ are executed for this operation. Not all operations require this
+ argument.
+ @param Buffer Contains the value of data to execute to the SMBus slave device.
+ Not all operations require this argument. The length of this
+ buffer is identified by Length.
+
+ @retval EFI_SUCCESS The last data that was returned from the access matched the poll
+ exit criteria.
+ @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect).
+ @retval EFI_TIMEOUT Timeout expired before the operation was completed. Timeout is
+ determined by the SMBus host controller device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The request was not completed because a failure that was
+ reflected in the Host Status Register bit. Device errors are a
+ result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+ @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
+ @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
+ and EfiSmbusQuickWrite. Length is outside the range of valid
+ values.
+ @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+Execute (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbusExec.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbusExec.c
new file mode 100644
index 0000000..de080d0
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbusExec.c
@@ -0,0 +1,264 @@
+/** @file
+ Common code to implement SMBus bus protocols. Smbus PEI and DXE modules
+ share the same version of this file.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "CommonHeader.h"
+
+#include "QNCSmbus.h"
+
+/**
+ Checks the parameter of SmbusExecute().
+
+ This function checks the input parameters of SmbusExecute(). If the input parameters are valid
+ for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain
+ error code based on the input SMBus bus protocol.
+
+ @param SlaveAddress The SMBus slave address of the device with which to communicate.
+ @param Command This command is transmitted by the SMBus host controller to the
+ SMBus slave device and the interpretation is SMBus slave device
+ specific. It can mean the offset to a list of functions inside an
+ SMBus slave device. Not all operations or slave devices support
+ this command's registers.
+ @param Operation Signifies which particular SMBus hardware protocol instance that
+ it will use to execute the SMBus transactions. This SMBus
+ hardware protocol is defined by the SMBus Specification and is
+ not related to EFI.
+ @param PecCheck Defines if Packet Error Code (PEC) checking is required for this
+ operation.
+ @param Length Signifies the number of bytes that this operation will do. The
+ maximum number of bytes can be revision specific and operation
+ specific. This field will contain the actual number of bytes that
+ are executed for this operation. Not all operations require this
+ argument.
+ @param Buffer Contains the value of data to execute to the SMBus slave device.
+ Not all operations require this argument. The length of this
+ buffer is identified by Length.
+
+ @retval EFI_SUCCESS All the parameters are valid for the corresponding SMBus bus
+ protocol.
+ @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
+ @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
+ and EfiSmbusQuickWrite. Length is outside the range of valid
+ values.
+ @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+CheckParameters (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN RequiredLen;
+
+ //
+ // Set default value to be 2:
+ // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.
+ //
+ RequiredLen = 2;
+ Status = EFI_SUCCESS;
+ switch (Operation) {
+ case EfiSmbusQuickRead:
+ case EfiSmbusQuickWrite:
+ if (PecCheck || Command != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ break;
+ case EfiSmbusReceiveByte:
+ case EfiSmbusSendByte:
+ if (Command != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Cascade to check length parameter.
+ //
+ case EfiSmbusReadByte:
+ case EfiSmbusWriteByte:
+ RequiredLen = 1;
+ //
+ // Cascade to check length parameter.
+ //
+ case EfiSmbusReadWord:
+ case EfiSmbusWriteWord:
+ case EfiSmbusProcessCall:
+ if (Buffer == NULL || Length == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else if (*Length < RequiredLen) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ *Length = RequiredLen;
+ break;
+ case EfiSmbusReadBlock:
+ case EfiSmbusWriteBlock:
+ if ((Buffer == NULL) ||
+ (Length == NULL) ||
+ (*Length < MIN_SMBUS_BLOCK_LEN) ||
+ (*Length > MAX_SMBUS_BLOCK_LEN)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ case EfiSmbusBWBRProcessCall:
+ return EFI_UNSUPPORTED;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ return Status;
+}
+
+/**
+ Executes an SMBus operation to an SMBus controller. Returns when either the command has been
+ executed or an error is encountered in doing the operation.
+
+ The internal worker function provides a standard way to execute an operation as defined in the
+ System Management Bus (SMBus) Specification. The resulting transaction will be either that the
+ SMBus slave devices accept this transaction or that this function returns with error.
+
+ @param SlaveAddress The SMBus slave address of the device with which to communicate.
+ @param Command This command is transmitted by the SMBus host controller to the
+ SMBus slave device and the interpretation is SMBus slave device
+ specific. It can mean the offset to a list of functions inside an
+ SMBus slave device. Not all operations or slave devices support
+ this command's registers.
+ @param Operation Signifies which particular SMBus hardware protocol instance that
+ it will use to execute the SMBus transactions. This SMBus
+ hardware protocol is defined by the SMBus Specification and is
+ not related to EFI.
+ @param PecCheck Defines if Packet Error Code (PEC) checking is required for this
+ operation.
+ @param Length Signifies the number of bytes that this operation will do. The
+ maximum number of bytes can be revision specific and operation
+ specific. This field will contain the actual number of bytes that
+ are executed for this operation. Not all operations require this
+ argument.
+ @param Buffer Contains the value of data to execute to the SMBus slave device.
+ Not all operations require this argument. The length of this
+ buffer is identified by Length.
+
+ @retval EFI_SUCCESS The last data that was returned from the access matched the poll
+ exit criteria.
+ @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect).
+ @retval EFI_TIMEOUT Timeout expired before the operation was completed. Timeout is
+ determined by the SMBus host controller device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_DEVICE_ERROR The request was not completed because a failure that was
+ reflected in the Host Status Register bit. Device errors are a
+ result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+ @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
+ @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
+ and EfiSmbusQuickWrite. Length is outside the range of valid
+ values.
+ @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+Execute (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN SmbusAddress;
+ UINTN WorkBufferLen;
+ UINT8 WorkBuffer[MAX_SMBUS_BLOCK_LEN];
+
+ Status = CheckParameters (SlaveAddress, Command, Operation, PecCheck, Length, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SmbusAddress = SMBUS_LIB_ADDRESS (SlaveAddress.SmbusDeviceAddress, Command, *Length, PecCheck);
+
+ switch (Operation) {
+ case EfiSmbusQuickRead:
+ SmBusQuickRead (SmbusAddress, &Status);
+ break;
+ case EfiSmbusQuickWrite:
+ SmBusQuickWrite (SmbusAddress, &Status);
+ break;
+ case EfiSmbusReceiveByte:
+ *(UINT8 *) Buffer = SmBusReceiveByte (SmbusAddress, &Status);
+ break;
+ case EfiSmbusSendByte:
+ SmBusSendByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
+ break;
+ case EfiSmbusReadByte:
+ *(UINT8 *) Buffer = SmBusReadDataByte (SmbusAddress, &Status);
+ break;
+ case EfiSmbusWriteByte:
+ SmBusWriteDataByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
+ break;
+ case EfiSmbusReadWord:
+ *(UINT16 *) Buffer = SmBusReadDataWord (SmbusAddress, &Status);
+ break;
+ case EfiSmbusWriteWord:
+ SmBusWriteDataWord (SmbusAddress, *(UINT16 *) Buffer, &Status);
+ break;
+ case EfiSmbusProcessCall:
+ *(UINT16 *) Buffer = SmBusProcessCall (SmbusAddress, *(UINT16 *) Buffer, &Status);
+ break;
+ case EfiSmbusReadBlock:
+ WorkBufferLen = SmBusReadBlock (SmbusAddress, WorkBuffer, &Status);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Read block transaction is complete successfully, and then
+ // check whether the output buffer is large enough.
+ //
+ if (*Length >= WorkBufferLen) {
+ CopyMem (Buffer, WorkBuffer, WorkBufferLen);
+ } else {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ *Length = WorkBufferLen;
+ }
+ break;
+ case EfiSmbusWriteBlock:
+ SmBusWriteBlock (ADD_LENGTH (SmbusAddress, *Length), Buffer, &Status);
+ break;
+ default:
+ break;
+ }
+
+ return Status;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/SmartTimer.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/SmartTimer.c
new file mode 100644
index 0000000..d19daad
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/SmartTimer.c
@@ -0,0 +1,480 @@
+/** @file
+ Timer Architectural Protocol as defined in the DXE CIS.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: SmartTimer.c
+
+*/
+#include "CommonHeader.h"
+
+#include "SmartTimer.h"
+
+//
+// The handle onto which the Timer Architectural Protocol will be installed
+//
+EFI_HANDLE mTimerHandle = NULL;
+
+//
+// The Timer Architectural Protocol that this driver produces
+//
+EFI_TIMER_ARCH_PROTOCOL mTimer = {
+ TimerDriverRegisterHandler,
+ TimerDriverSetTimerPeriod,
+ TimerDriverGetTimerPeriod,
+ TimerDriverGenerateSoftInterrupt
+};
+
+//
+// Pointer to the CPU Architectural Protocol instance
+//
+EFI_CPU_ARCH_PROTOCOL *mCpu;
+
+//
+// Pointer to the Legacy 8259 Protocol instance
+//
+EFI_LEGACY_8259_PROTOCOL *mLegacy8259;
+
+//
+// The notification function to call on every timer interrupt.
+//
+volatile EFI_TIMER_NOTIFY mTimerNotifyFunction = NULL;
+
+//
+// The current period of the timer interrupt
+//
+volatile UINT64 mTimerPeriod = 0;
+
+//
+// The time of twice timer interrupt duration
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mPreAcpiTick = 0;
+
+//
+// Worker Functions
+//
+
+/**
+ Sets the counter value for Timer #0 in a legacy 8254 timer.
+
+ @param Count - The 16-bit counter value to program into Timer #0 of the legacy 8254 timer.
+
+*/
+VOID
+SetPitCount (
+ IN UINT16 Count
+ )
+{
+ IoWrite8 (TIMER_CONTROL_PORT, TIMER0_CONTROL_WORD);
+ IoWrite8 (TIMER0_COUNT_PORT, (UINT8) (Count & 0xFF));
+ IoWrite8 (TIMER0_COUNT_PORT, (UINT8) ((Count>>8) & 0xFF));
+}
+
+/**
+ Measure the 8254 timer interrupt use the ACPI time counter
+
+ @param TimePeriod - The Time Period between two Timer Interrupt
+
+ @return The real system time pass between the sequence 8254 timer interrupt
+
+*/
+UINT64
+MeasureTimeLost (
+ IN UINT64 TimePeriod
+ )
+{
+ if (FeaturePcdGet(PcdUseAcpiTimerInSmartTimer)){
+ UINT32 CurrentTick;
+ UINT32 EndTick;
+ UINT64 LostTime;
+
+ CurrentTick = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T);
+ EndTick = CurrentTick;
+
+ if (CurrentTick < mPreAcpiTick) {
+ EndTick = CurrentTick + 0x1000000; // PM1_TMR Timer Value uses BIT(23:0), 0x1000000 = 1 << 24;
+ }
+
+ //
+ // If there are timer interrupts missed, ACPI time counter is used to retrieve the time elapsed,
+ // It is used to avoid some issues while system enter read mode and disable IRQ during the boot.
+ // The time should be accurate, shift is used for more accurate value.,the original formula is:
+ // (EndTick - mPreAcpiTick) * 10,000,000
+ // LostTime = (--------------------------------------- * 0x1000000) >> 24
+ // 3,579,545 Hz
+ //
+ // Note: the 3,579,545 Hz is the ACPI timer's clock; The time unit of the result
+ // is 100ns, which is same with 8254 Timer.
+ //
+ LostTime = RShiftU64 (
+ MultU64x32 ((UINT64) (EndTick - mPreAcpiTick),
+ ACPI_TIMER_FACTOR) + 0x00FFFFFF,
+ 24
+ );
+
+ if (LostTime != 0) {
+ mPreAcpiTick = CurrentTick;
+ }
+
+ return LostTime;
+ } else {
+ return TimePeriod;
+ }
+}
+
+/**
+ 8254 Timer #0 Interrupt Handler
+
+ @param InterruptType - The type of interrupt that occured
+ @param SystemContext - A pointer to the system context when the interrupt occured
+
+*/
+VOID
+EFIAPI
+TimerInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ EFI_TPL OriginalTPL;
+ UINT64 TimeLost;
+
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq0);
+
+ if (mTimerNotifyFunction) {
+ TimeLost = MeasureTimeLost (mTimerPeriod);
+ mTimerNotifyFunction (TimeLost);
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+}
+
+/**
+ This function registers the handler NotifyFunction so it is called every time
+ the timer interrupt fires. It also passes the amount of time since the last
+ handler call to the NotifyFunction. If NotifyFunction is NULL, then the
+ handler is unregistered. If the handler is registered, then EFI_SUCCESS is
+ returned. If the CPU does not support registering a timer interrupt handler,
+ then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
+ when a handler is already registered, then EFI_ALREADY_STARTED is returned.
+ If an attempt is made to unregister a handler when a handler is not registered,
+ then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
+ register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
+ is returned.
+
+ @param This - The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @param NotifyFunction - The function to call when a timer interrupt fires. This
+ function executes at TPL_HIGH_LEVEL. The DXE Core will
+ register a handler for the timer interrupt, so it can know
+ how much time has passed. This information is used to
+ signal timer based events. NULL will unregister the handler.
+
+ @retval EFI_SUCCESS - The timer handler was registered.
+ @retval EFI_UNSUPPORTED - The platform does not support timer interrupts.
+ @retval EFI_ALREADY_STARTED - NotifyFunction is not NULL, and a handler is already
+ registered.
+ @retval EFI_INVALID_PARAMETER - NotifyFunction is NULL, and a handler was not
+ previously registered.
+ @retval EFI_DEVICE_ERROR - The timer handler could not be registered.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+ )
+{
+ //
+ // Check for invalid parameters
+ //
+ if (NotifyFunction == NULL && mTimerNotifyFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (NotifyFunction != NULL && mTimerNotifyFunction != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mTimerNotifyFunction = NotifyFunction;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+ @param This - The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod - The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+ @retval EFI_SUCCESS - The timer period was changed.
+ @retval EFI_UNSUPPORTED - The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR - The timer period could not be changed due to a device error.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ )
+{
+ UINT64 TimerCount;
+
+ //
+ // The basic clock is 1.19318 MHz or 0.119318 ticks per 100 ns.
+ // TimerPeriod * 0.119318 = 8254 timer divisor. Using integer arithmetic
+ // TimerCount = (TimerPeriod * 119318)/1000000.
+ //
+ // Round up to next highest integer. This guarantees that the timer is
+ // equal to or slightly longer than the requested time.
+ // TimerCount = ((TimerPeriod * 119318) + 500000)/1000000
+ //
+ // Note that a TimerCount of 0 is equivalent to a count of 65,536
+ //
+ // Since TimerCount is limited to 16 bits for IA32, TimerPeriod is limited
+ // to 20 bits.
+ //
+ if (TimerPeriod == 0) {
+ //
+ // Disable timer interrupt for a TimerPeriod of 0
+ //
+ mLegacy8259->DisableIrq (mLegacy8259, Efi8259Irq0);
+ } else {
+ //
+ // Convert TimerPeriod into 8254 counts
+ //
+ TimerCount = DivU64x32 (MultU64x32 (119318, (UINT32) TimerPeriod) + 500000, 1000000);
+
+ //
+ // Check for overflow
+ //
+ if (TimerCount >= 65536) {
+ TimerCount = 0;
+ if (TimerPeriod >= DEFAULT_TIMER_TICK_DURATION) {
+ TimerPeriod = DEFAULT_TIMER_TICK_DURATION;
+ }
+ }
+ //
+ // Program the 8254 timer with the new count value
+ //
+ SetPitCount ((UINT16) TimerCount);
+
+ //
+ // Enable timer interrupt
+ //
+ mLegacy8259->EnableIrq (mLegacy8259, Efi8259Irq0, FALSE);
+ }
+ //
+ // Save the new timer period
+ //
+ mTimerPeriod = TimerPeriod;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+ @param This - The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod - A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+ @retval EFI_SUCCESS - The timer period was returned in TimerPeriod.
+ @retval EFI_INVALID_PARAMETER - TimerPeriod is NULL.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ )
+{
+ if (TimerPeriod == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerPeriod = mTimerPeriod;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function generates a soft timer interrupt. If the platform does not support soft
+ timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
+ If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
+ service, then a soft timer interrupt will be generated. If the timer interrupt is
+ enabled when this service is called, then the registered handler will be invoked. The
+ registered handler should not be able to distinguish a hardware-generated timer
+ interrupt from a software-generated timer interrupt.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS - The soft timer interrupt was generated.
+ @retval EFI_UNSUPPORTEDT - The platform does not support the generation of soft timer interrupts.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ UINT16 IRQMask;
+ EFI_TPL OriginalTPL;
+ UINT64 TimeLost;
+
+ //
+ // If the timer interrupt is enabled, then the registered handler will be invoked.
+ //
+ Status = mLegacy8259->GetMask (mLegacy8259, NULL, NULL, &IRQMask, NULL);
+ ASSERT_EFI_ERROR (Status);
+ if ((IRQMask & 0x1) == 0) {
+ //
+ // Invoke the registered handler
+ //
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ if (mTimerNotifyFunction) {
+ TimeLost = MeasureTimeLost (mTimerPeriod);
+ mTimerNotifyFunction (TimeLost);
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the Timer Architectural Protocol driver
+
+ @param ImageHandle - ImageHandle of the loaded driver
+ @param SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - Timer Architectural Protocol created
+ @retval EFI_OUT_OF_RESOURCES - Not enough resources available to initialize driver.
+ @retval EFI_DEVICE_ERROR - A device error occured attempting to initialize the driver.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TimerVector;
+
+ //
+ // Make sure the Timer Architectural Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid);
+
+ //
+ // Find the CPU architectural protocol. ASSERT if not found.
+ //
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &mCpu);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find the Legacy8259 protocol. ASSERT if not found.
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Force the timer to be disabled
+ //
+ Status = TimerDriverSetTimerPeriod (&mTimer, 0);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver
+ //
+ TimerVector = 0;
+ Status = mLegacy8259->GetVector (mLegacy8259, Efi8259Irq0, (UINT8 *) &TimerVector);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install interrupt handler for 8254 Timer #0 (ISA IRQ0)
+ //
+ Status = mCpu->RegisterInterruptHandler (mCpu, TimerVector, TimerInterruptHandler);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Force the timer to be enabled at its default period
+ //
+ Status = TimerDriverSetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATION);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Begin the ACPI timer counter
+ //
+ if (FeaturePcdGet(PcdUseAcpiTimerInSmartTimer)){
+ mPreAcpiTick = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T);
+ }
+
+ //
+ // Install the Timer Architectural Protocol onto a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mTimerHandle,
+ &gEfiTimerArchProtocolGuid,
+ &mTimer,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/SmartTimer.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/SmartTimer.h
new file mode 100644
index 0000000..237126f
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/SmartTimer.h
@@ -0,0 +1,195 @@
+/** @file
+ Declaration of SmartTimer specific functions and Macros
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: SmartTimer.h
+
+*/
+
+#ifndef _SMART_TIMER_H_
+#define _SMART_TIMER_H_
+#include "CommonHeader.h"
+
+//
+// 8254 Timer
+//
+#define TIMER0_COUNT_PORT 0x40
+#define TIMER1_COUNT_PORT 0x41
+#define TIMER2_COUNT_PORT 0x42
+#define TIMER_CONTROL_PORT 0x43
+
+//
+// The PCAT 8253/8254 has an input clock at 1.193182 MHz and Timer 0 is
+// initialized as a 16 bit free running counter that generates an interrupt(IRQ0)
+// each time the counter rolls over.
+//
+// 65536 counts
+// ---------------- * 1,000,000 uS/S = 54925.4 uS = 549254 * 100 ns
+// 1,193,182 Hz
+//
+#define DEFAULT_TIMER_TICK_DURATION 549254
+#define TIMER0_CONTROL_WORD 0x36 //Time0, Read/Write LSB then MSB, Square wave output, binary count use.
+
+//
+// ACPI timer factor
+//
+#define ACPI_TIMER_FACTOR 46869689 // 10*0x1000000/3.579545, the 3.579545 MHz is the ACPI timer's clock;
+
+/**
+ This function registers the handler NotifyFunction so it is called every time
+ the timer interrupt fires. It also passes the amount of time since the last
+ handler call to the NotifyFunction. If NotifyFunction is NULL, then the
+ handler is unregistered. If the handler is registered, then EFI_SUCCESS is
+ returned. If the CPU does not support registering a timer interrupt handler,
+ then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
+ when a handler is already registered, then EFI_ALREADY_STARTED is returned.
+ If an attempt is made to unregister a handler when a handler is not registered,
+ then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
+ register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
+ is returned.
+
+ @param This - The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @param NotifyFunction - The function to call when a timer interrupt fires. This
+ function executes at TPL_HIGH_LEVEL. The DXE Core will
+ register a handler for the timer interrupt, so it can know
+ how much time has passed. This information is used to
+ signal timer based events. NULL will unregister the handler.
+
+ @retval EFI_SUCCESS - The timer handler was registered.
+ @retval EFI_UNSUPPORTED - The platform does not support timer interrupts.
+ @retval EFI_ALREADY_STARTED - NotifyFunction is not NULL, and a handler is already
+ registered.
+ @retval EFI_INVALID_PARAMETER - NotifyFunction is NULL, and a handler was not
+ previously registered.
+ @retval EFI_DEVICE_ERROR - The timer handler could not be registered.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+ );
+
+/**
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+ @param This - The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod - The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+ @retval EFI_SUCCESS - The timer period was changed.
+ @retval EFI_UNSUPPORTED - The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR - The timer period could not be changed due to a device error.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ );
+
+
+/**
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+ @param This - The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod - A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+ @retval EFI_SUCCESS - The timer period was returned in TimerPeriod.
+ @retval EFI_INVALID_PARAMETER - TimerPeriod is NULL.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ );
+
+/**
+ This function generates a soft timer interrupt. If the platform does not support soft
+ timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
+ If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
+ service, then a soft timer interrupt will be generated. If the timer interrupt is
+ enabled when this service is called, then the registered handler will be invoked. The
+ registered handler should not be able to distinguish a hardware-generated timer
+ interrupt from a software-generated timer interrupt.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS - The soft timer interrupt was generated.
+ @retval EFI_UNSUPPORTEDT - The platform does not support the generation of soft timer interrupts.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ );
+/**
+ Initialize the Timer Architectural Protocol driver
+
+ @param ImageHandle - ImageHandle of the loaded driver
+ @param SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - Timer Architectural Protocol created
+ @retval EFI_OUT_OF_RESOURCES - Not enough resources available to initialize driver.
+ @retval EFI_DEVICE_ERROR - A device error occured attempting to initialize the driver.
+
+*/
+EFI_STATUS
+EFIAPI
+TimerDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.c b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.c
new file mode 100644
index 0000000..d6e531a
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.c
@@ -0,0 +1,448 @@
+/*++
+ This is the driver that implements the QNC S3 Support protocol
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "QncS3Support.h"
+
+//
+// Global Variables
+//
+EFI_QNC_S3_SUPPORT_PROTOCOL mQncS3SupportProtocol;
+QNC_S3_PARAMETER_HEADER *mS3Parameter;
+UINT32 mQncS3ImageEntryPoint;
+VOID *mQncS3ImageAddress;
+UINTN mQncS3ImageSize;
+
+extern EFI_GUID gQncS3CodeInLockBoxGuid;
+extern EFI_GUID gQncS3ContextInLockBoxGuid;
+
+/**
+
+ Create a buffer that is used to store context information for use with
+ dispatch functions.
+
+ @retval EFI_SUCCESS - Buffer allocated and initialized.
+
+**/
+EFI_STATUS
+CreateContextBuffer (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+ UINT32 ContextStoreSize;
+
+ ContextStoreSize = EFI_PAGE_SIZE;
+
+ //
+ // Allcoate <4G EfiReservedMemory
+ //
+ Address = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (AllocateMaxAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (ContextStoreSize), &Address);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mS3Parameter = (QNC_S3_PARAMETER_HEADER *) (UINTN) Address;
+
+ //
+ // Determine the maximum number of context entries that can be stored in this
+ // table.
+ //
+ mS3Parameter->MaxContexts = ((ContextStoreSize - sizeof(QNC_S3_PARAMETER_HEADER)) / sizeof(EFI_DISPATCH_CONTEXT_UNION)) + 1;
+ mS3Parameter->StorePosition = 0;
+
+ return Status;
+}
+
+//
+// Functions
+//
+EFI_STATUS
+EFIAPI
+QncS3SupportEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+ Routine Description:
+
+ QNC S3 support driver entry point
+
+ Arguments:
+
+ ImageHandle - Handle for the image of this driver
+ SystemTable - Pointer to the EFI System Table
+
+ Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *TmpPtr;
+ EFI_EVENT Event;
+ VOID *Registration;
+
+ //
+ // If the protocol is found execution is happening in ACPI NVS memory. If it
+ // is not found copy the driver into ACPI NVS memory and pass control to it.
+ //
+ Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &TmpPtr);
+
+ //
+ // Load the QNC S3 image
+ //
+ if (EFI_ERROR (Status)) {
+ Status = LoadQncS3Image (SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ } else {
+ DEBUG ((DEBUG_INFO, "QncS3SupportEntryPoint() in reserved memory - Begin\n"));
+ //
+ // Allocate and initialize context buffer.
+ //
+ Status = CreateContextBuffer ();
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Install the QNC S3 Support protocol
+ //
+ mQncS3SupportProtocol.SetDispatchItem = QncS3SetDispatchItem;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiQncS3SupportProtocolGuid,
+ &mQncS3SupportProtocol,
+ NULL
+ );
+
+ mQncS3ImageAddress = (VOID *)(UINTN)PcdGet64(PcdQncS3CodeInLockBoxAddress);
+ mQncS3ImageSize = (UINTN)PcdGet64(PcdQncS3CodeInLockBoxSize);
+ DEBUG ((DEBUG_INFO, "QncS3SupportEntry Code = %08x, Size = %08x\n", (UINTN)mQncS3ImageAddress, mQncS3ImageSize));
+ DEBUG ((DEBUG_INFO, "QncS3SupportEntry Contex = %08x, Size = %08x\n", (UINTN)mS3Parameter, EFI_PAGE_SIZE));
+ ASSERT (mQncS3ImageAddress != 0);
+
+
+ //
+ // Create the event for QncS3 to do the LockBox,
+ //
+ Event = EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ TPL_CALLBACK,
+ QncS3BootEvent,
+ NULL,
+ &Registration
+ );
+ ASSERT (Event != NULL);
+
+ DEBUG ((DEBUG_INFO, "QncS3SupportEntryPoint() in reserved memory - End\n"));
+ }
+
+
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+QncS3SetDispatchItem (
+ IN EFI_QNC_S3_SUPPORT_PROTOCOL *This,
+ IN EFI_QNC_S3_DISPATCH_ITEM *DispatchItem,
+ OUT VOID **S3DispatchEntryPoint,
+ OUT VOID **Context
+ )
+/*++
+
+Routine Description:
+
+ Set an item to be dispatched at S3 resume time. At the same time, the entry point
+ of the QNC S3 support image is returned to be used in subsequent boot script save
+ call
+
+Arguments:
+
+ This - Pointer to the protocol instance.
+ DispatchItem - The item to be dispatched.
+ S3DispatchEntryPoint - The entry point of the QNC S3 support image.
+
+Returns:
+
+ EFI_STATUS - Successfully completed.
+ EFI_OUT_OF_RESOURCES - Out of resources.
+
+--*/
+{
+
+ DEBUG ((DEBUG_INFO, "QncS3SetDispatchItem() Start\n"));
+
+ //
+ // Set default values.
+ //
+ *S3DispatchEntryPoint = NULL;
+ *Context = NULL;
+
+ //
+ // Determine if this entry will fit.
+ //
+ if (mS3Parameter->StorePosition >= mS3Parameter->MaxContexts) {
+ DEBUG ((DEBUG_INFO, "QncS3SetDispatchItem exceeds max length - 0x%08x\n", (UINTN)mS3Parameter->MaxContexts));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Calculate the size required;
+ // ** Always round up to be 8 byte aligned
+ //
+ switch (DispatchItem->Type) {
+ case QncS3ItemTypeInitPcieRootPortDownstream:
+ *S3DispatchEntryPoint = (VOID*) (UINTN)QncS3InitPcieRootPortDownstream;
+ *Context = &mS3Parameter->Contexts[mS3Parameter->StorePosition];
+ CopyMem (&mS3Parameter->Contexts[mS3Parameter->StorePosition], DispatchItem->Parameter, sizeof(UINT32));
+ DEBUG ((DEBUG_INFO, "QncS3InitPcieRootPortDownstream @ 0x%08x - context 0x%08x\n", (UINTN)*S3DispatchEntryPoint, (UINTN)*Context));
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+
+ }
+
+ mS3Parameter->StorePosition ++;
+ DEBUG ((DEBUG_INFO, "QncS3SetDispatchItem() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LoadQncS3Image (
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Load the QNC S3 Image into Efi Reserved Memory below 4G.
+
+Arguments:
+
+ ImageEntryPoint the ImageEntryPoint after success loading
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+ UINTN BufferSize;
+ VOID *FfsBuffer;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ EFI_HANDLE NewImageHandle;
+
+ //
+ // Install NULL protocol on module file handle to indicate that the entry point
+ // has been called for the first time.
+ //
+ NewImageHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewImageHandle,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+
+
+ //
+ // Find this module so it can be loaded again.
+ //
+ Status = GetSectionFromAnyFv (
+ &gEfiCallerIdGuid,
+ EFI_SECTION_PE32,
+ 0,
+ (VOID**) &Buffer,
+ &BufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+
+ //
+ // Get information about the image being loaded.
+ //
+ ImageContext.Handle = Buffer;
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+
+ //
+ // Get information about the image being loaded
+ //
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiReservedMemoryType,
+ BufferSize + ImageContext.SectionAlignment,
+ &FfsBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "LoadQncS3Image failed for no enough space! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mQncS3ImageAddress = FfsBuffer;
+ mQncS3ImageSize = BufferSize + ImageContext.SectionAlignment;
+ PcdSet64(PcdQncS3CodeInLockBoxAddress, (UINT64)(UINTN)mQncS3ImageAddress);
+ PcdSet64(PcdQncS3CodeInLockBoxSize, (UINT64)mQncS3ImageSize);
+ //
+ // Align buffer on section boundry
+ //
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
+ if (ImageContext.SectionAlignment != 0) {
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+ ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
+ }
+
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (FfsBuffer);
+ DEBUG ((DEBUG_INFO, "LoadQncS3Image failed for PeCoffLoaderLoadImage failure! \n"));
+ return Status;
+ }
+
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ PeCoffLoaderUnloadImage (&ImageContext);
+ gBS->FreePool (FfsBuffer);
+ DEBUG ((DEBUG_INFO, "LoadQncS3Image failed for PeCoffLoaderRelocateImage failure! \n"));
+ return Status;
+ }
+
+ //
+ // Invalidate instruction cache and pass control to the image. This will perform
+ // the initialization of the module and publish the supporting protocols.
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+ Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (FfsBuffer);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+QncS3InitPcieRootPortDownstream (
+ IN EFI_HANDLE ImageHandle,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+ Perform Init Root Port Downstream devices on S3 resume
+
+ Arguments:
+ Parameter Parameters passed in from DXE
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "QncS3InitPcieRootPortDownstream() Begin\n"));
+
+ //
+ // Initialize the device behind the root port.
+ //
+ Status = PciExpressInit ();
+
+ //
+ // Not checking the error status here - downstream device not present does not
+ // mean an error of this root port. Our return status of EFI_SUCCESS means this
+ // port is enabled and outer function depends on this return status to do
+ // subsequent initializations.
+ //
+
+ if (Status != EFI_SUCCESS){
+ DEBUG ((DEBUG_INFO, "QncS3InitPcieRootPortDownstream() failed\n"));
+ }
+
+ DEBUG ((DEBUG_INFO, "QncS3InitPcieRootPortDownstream() End\n"));
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+QncS3BootEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID * PmAuthProt = NULL;
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &PmAuthProt);
+ if (Status != EFI_SUCCESS){
+ DEBUG ((DEBUG_INFO, "QncS3BootEvent triggered but not valid.\n"));
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ //
+ // These 2 boxes will be restored by RestoreAllLockBoxInPlace in S3Resume automatically
+ //
+ DEBUG ((DEBUG_INFO, "SaveLockBox QncS3Code = %08x, Size = %08x\n", (UINTN)mQncS3ImageAddress, mQncS3ImageSize));
+ SaveLockBox(&gQncS3CodeInLockBoxGuid, mQncS3ImageAddress, mQncS3ImageSize);
+ Status = SetLockBoxAttributes (&gQncS3CodeInLockBoxGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "SaveLockBox QncS3Context = %08x, Size = %08x\n", (UINTN)mS3Parameter, EFI_PAGE_SIZE));
+ SaveLockBox(&gQncS3ContextInLockBoxGuid, (VOID *)mS3Parameter, EFI_PAGE_SIZE);
+ Status = SetLockBoxAttributes (&gQncS3ContextInLockBoxGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.h b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.h
new file mode 100644
index 0000000..57504c7
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.h
@@ -0,0 +1,142 @@
+/**@file
+ Header file for QNC S3 Support driver
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef _QNC_S3_SUPPORT_H_
+#define _QNC_S3_SUPPORT_H_
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/FirmwareVolume2.h>
+#include <Library/UefiLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+//
+// Driver Produced Protocol Prototypes
+//
+#include <Protocol/LoadedImage.h>
+#include <Protocol/QncS3Support.h>
+#include <Protocol/ExitPmAuth.h>
+
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/IntelQNCLib.h>
+//
+// Define the header of the context region.
+//
+typedef struct {
+ UINT32 MaxContexts;
+ UINT32 StorePosition;
+ EFI_DISPATCH_CONTEXT_UNION Contexts[1];
+} QNC_S3_PARAMETER_HEADER;
+//
+// Function prototypes
+//
+EFI_STATUS
+EFIAPI
+QncS3SetDispatchItem (
+ IN EFI_QNC_S3_SUPPORT_PROTOCOL *This,
+ IN EFI_QNC_S3_DISPATCH_ITEM *DispatchItem,
+ OUT VOID **S3DispatchEntryPoint,
+ OUT VOID **Context
+ )
+/*++
+
+Routine Description:
+
+ Set an item to be dispatched at S3 resume time. At the same time, the entry point
+ of the QNC S3 support image is returned to be used in subsequent boot script save
+ call
+
+Arguments:
+
+ This - Pointer to the protocol instance.
+ DispatchItem - The item to be dispatched.
+ S3DispatchEntryPoint - The entry point of the QNC S3 support image.
+
+Returns:
+
+ EFI_STATUS - Successfully completed.
+ EFI_OUT_OF_RESOURCES - Out of resources.
+
+--*/
+;
+
+EFI_STATUS
+LoadQncS3Image (
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Load the QNC S3 Image into Efi Reserved Memory below 4G.
+
+Arguments:
+
+ ImageEntryPoint the ImageEntryPoint after success loading
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+QncS3InitPcieRootPortDownstream (
+ IN EFI_HANDLE ImageHandle,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+EFIAPI
+QncS3BootEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf
new file mode 100755
index 0000000..993b361
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf
@@ -0,0 +1,90 @@
+## @file
+# Component description file for Qnc Initialization driver
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QncS3Support
+ FILE_GUID = C7EA9787-CA0A-43b4-B1E5-25EF87391F8D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = QncS3SupportEntryPoint
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ QncS3Support.h
+ QncS3Support.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ DxeServicesLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ PeCoffLib
+ LockBoxLib
+ S3BootScriptLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ CacheMaintenanceLib
+ IntelQNCLib
+
+[Protocols]
+ gEfiQncS3SupportProtocolGuid ## PRODUCES
+ gEfiLoadPeImageProtocolGuid ## CONSUMES
+ gEfiFirmwareVolume2ProtocolGuid ## CONSUMES
+ gExitPmAuthProtocolGuid ## CONSUMES
+
+[Guids]
+ gQncS3CodeInLockBoxGuid
+ gQncS3ContextInLockBoxGuid
+
+[Pcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQncS3CodeInLockBoxAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQncS3CodeInLockBoxSize
+
+[Depex]
+ gEfiFirmwareVolume2ProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf
new file mode 100644
index 0000000..760afa1
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf
@@ -0,0 +1,80 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Module Name:
+#
+# SmmAccess.inf
+#
+# Abstract:
+#
+# Component description file for SmmAccess module
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmAccess
+ FILE_GUID = 274F0C8F-9E57-41d8-9966-29CCD48D31C2
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SmmAccessDriverEntryPoint
+
+[Sources]
+ SmmAccessDriver.h
+ SmmAccessDriver.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ HobLib
+ DebugLib
+ UefiLib
+ BaseLib
+ BaseMemoryLib
+ S3BootScriptLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ PcdLib
+ IntelQNCLib
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiSmmAccess2ProtocolGuid
+
+[Guids]
+ gEfiSmmPeiSmramMemoryReserveGuid
+
+[Depex]
+ gEfiPciRootBridgeIoProtocolGuid
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c
new file mode 100755
index 0000000..aab3aed
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c
@@ -0,0 +1,422 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SmmAccessDriver.c
+
+Abstract:
+
+ This is the driver that publishes the SMM Access Protocol
+ instance for the Tylersburg chipset.
+
+Revision History:
+
+--*/
+
+#include "SmmAccessDriver.h"
+
+
+
+STATIC SMM_ACCESS_PRIVATE_DATA mSmmAccess;
+
+VOID
+SmmAccessOnBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+);
+
+EFI_STATUS
+EFIAPI
+SmmAccessDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Installs an SMM Access Protocol.
+
+Arguments:
+
+ ImageHandle - Handle for the image of this driver.
+ SystemTable - Pointer to the EFI System Table.
+
+Returns:
+
+ EFI_SUCCESS - Protocol successfully started and installed.
+ EFI_UNSUPPORTED - Protocol can't be started.
+ EFI_NOT_FOUND - Protocol not found.
+--*/
+{
+
+ EFI_STATUS Status;
+ STATIC EFI_EVENT BootEvent;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINTN Index;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+
+ //
+ // Initialize private data
+ //
+ ZeroMem (&mSmmAccess, sizeof (mSmmAccess));
+
+ Status = gBS->LocateProtocol (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &PciRootBridgeIo
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Build SMM related information
+ //
+ mSmmAccess.Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;
+ mSmmAccess.Handle = NULL;
+ mSmmAccess.PciRootBridgeIo = PciRootBridgeIo;
+
+ //
+ // Get Hob list
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (DescriptorBlock);
+
+
+ //
+ // Get CPU Max bus number
+ //
+ mSmmAccess.MaxBusNumber = PCI_BUS_NUMBER_QNC;
+ for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {
+ mSmmAccess.SocketPopulated[Index] = TRUE;
+ }
+
+ //
+ // Use the hob to publish SMRAM capabilities
+ //
+ ASSERT (DescriptorBlock->NumberOfSmmReservedRegions <= MAX_SMRAM_RANGES);
+ for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {
+ mSmmAccess.SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;
+ mSmmAccess.SmramDesc[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart;
+ mSmmAccess.SmramDesc[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize;
+ mSmmAccess.SmramDesc[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState;
+ DEBUG ((EFI_D_INFO, "SM RAM index[%d] startaddr:%08X Size :%08X\n", Index, mSmmAccess.SmramDesc[Index].CpuStart,
+ mSmmAccess.SmramDesc[Index].PhysicalSize));
+ }
+
+ mSmmAccess.NumberRegions = Index;
+ mSmmAccess.SmmAccess.Open = Open;
+ mSmmAccess.SmmAccess.Close = Close;
+ mSmmAccess.SmmAccess.Lock = Lock;
+ mSmmAccess.SmmAccess.GetCapabilities = GetCapabilities;
+ mSmmAccess.SmmAccess.LockState = FALSE;
+ mSmmAccess.SmmAccess.OpenState = FALSE;
+ mSmmAccess.SMMRegionState = EFI_SMRAM_CLOSED;
+
+ //
+ // Install our protocol interfaces on the device's handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mSmmAccess.Handle,
+ &gEfiSmmAccess2ProtocolGuid,
+ &mSmmAccess.SmmAccess,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", (UINT32)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalStart)));
+ DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", (UINT32)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalSize)));
+
+ mSmmAccess.TsegSize = (UINT8)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalSize);
+ //
+ // T Seg setting done in QPI RC
+ //
+
+ //
+ // Prior ReadyToBoot, lock CSEG as required by the sighting 3427224
+ //
+ Status = EfiCreateEventReadyToBootEx(
+ TPL_NOTIFY,
+ SmmAccessOnBoot,
+ NULL,
+ &BootEvent );
+ ASSERT (!EFI_ERROR (Status));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+Open (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "open" a region of SMRAM. The
+ region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
+ The use of "open" means that the memory is visible from all boot-service
+ and SMM agents.
+
+Arguments:
+
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Open.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully opened.
+ EFI_DEVICE_ERROR - The region could not be opened because locked by
+ chipset.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+{
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {
+ DEBUG ((EFI_D_ERROR, "Cannot open a locked SMRAM region\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Open TSEG
+ //
+ if (!QNCOpenSmramRegion ()) {
+ mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;
+ return EFI_DEVICE_ERROR;
+ }
+
+ mSmmAccess.SMMRegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+ SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~(EFI_SMRAM_CLOSED | EFI_ALLOCATED)));
+ mSmmAccess.SMMRegionState |= EFI_SMRAM_OPEN;
+ SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_OPEN);
+ SmmAccess->SmmAccess.OpenState = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+Close (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "close" a region of SMRAM. This is valid for
+ compatible SMRAM region.
+
+Arguments:
+
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Close.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully closed.
+ EFI_DEVICE_ERROR - The region could not be closed because locked by
+ chipset.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+{
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+ BOOLEAN OpenState;
+ UINTN Index;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {
+ //
+ // Cannot close a "locked" region
+ //
+ DEBUG ((EFI_D_WARN, "Cannot close the locked SMRAM Region\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (mSmmAccess.SMMRegionState & EFI_SMRAM_CLOSED) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Close TSEG
+ //
+ if (!QNCCloseSmramRegion ()) {
+ mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;
+ return EFI_DEVICE_ERROR;
+ }
+
+ mSmmAccess.SMMRegionState &= ~EFI_SMRAM_OPEN;
+ SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~EFI_SMRAM_OPEN));
+ mSmmAccess.SMMRegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+ SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+
+ //
+ // Find out if any regions are still open
+ //
+ OpenState = FALSE;
+ for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {
+ if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {
+ OpenState = TRUE;
+ }
+ }
+
+ SmmAccess->SmmAccess.OpenState = OpenState;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+Lock (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "lock" SMRAM. The
+ region could be legacy AB or TSEG near top of physical memory.
+ The use of "lock" means that the memory can no longer be opened
+ to BS state..
+
+Arguments:
+
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Lock.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully locked.
+ EFI_DEVICE_ERROR - The region could not be locked because at least
+ one range is still open.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+{
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ if (SmmAccess->SmmAccess.OpenState) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;
+ SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_LOCKED);
+ SmmAccess->SmmAccess.LockState = TRUE;
+
+ //
+ // Lock TSEG
+ //
+ QNCLockSmramRegion ();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetCapabilities (
+ IN CONST EFI_SMM_ACCESS2_PROTOCOL *This,
+ IN OUT UINTN *SmramMapSize,
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
+ )
+/*++
+
+Routine Description:
+
+ This routine services a user request to discover the SMRAM
+ capabilities of this platform. This will report the possible
+ ranges that are possible for SMRAM access, based upon the
+ memory controller capabilities.
+
+Arguments:
+
+ This - Pointer to the SMRAM Access Interface.
+ SmramMapSize - Pointer to the variable containing size of the
+ buffer to contain the description information.
+ SmramMap - Buffer containing the data describing the Smram
+ region descriptors.
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
+ EFI_SUCCESS - The user provided a sufficiently-sized buffer.
+
+--*/
+{
+ EFI_STATUS Status;
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+ UINTN BufferSize;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+ BufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);
+
+ if (*SmramMapSize < BufferSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ } else {
+ CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);
+ Status = EFI_SUCCESS;
+ }
+ *SmramMapSize = BufferSize;
+
+ return Status;
+}
+
+VOID
+SmmAccessOnBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+
+}
+VOID
+SyncRegionState2SmramDesc(
+ IN BOOLEAN OrAnd,
+ IN UINT64 Value
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {
+ if (OrAnd) {
+ mSmmAccess.SmramDesc[Index].RegionState |= Value;
+ } else {
+ mSmmAccess.SmramDesc[Index].RegionState &= Value;
+ }
+ }
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.h b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.h
new file mode 100644
index 0000000..7754326
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.h
@@ -0,0 +1,253 @@
+/**@file
+ Header file for SMM Access Driver.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef _SMM_ACCESS_DRIVER_H
+#define _SMM_ACCESS_DRIVER_H
+
+#include <PiDxe.h>
+#include <IndustryStandard/Pci.h>
+
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/PciRootBridgeIo.h>
+
+//
+// Driver Consumed GUID Prototypes
+//
+#include <Guid/SmramMemoryReserve.h>
+
+//
+// Driver produced protocol
+//
+#include <Protocol/SmmAccess2.h>
+
+#include <Library/IntelQNCLib.h>
+#include <QNCAccess.h>
+
+#define MAX_CPU_SOCKET 1
+#define MAX_SMRAM_RANGES 4
+
+//
+// Private data structure
+//
+#define SMM_ACCESS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', 's', 'm', 'a')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SMM_ACCESS2_PROTOCOL SmmAccess;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINTN NumberRegions;
+ EFI_SMRAM_DESCRIPTOR SmramDesc[MAX_SMRAM_RANGES];
+ UINT8 TsegSize;
+ UINT8 MaxBusNumber;
+ UINT8 SocketPopulated[MAX_CPU_SOCKET];
+ UINT64 SMMRegionState;
+ UINT8 ActualNLIioBusNumber;
+} SMM_ACCESS_PRIVATE_DATA;
+
+
+#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \
+ CR ( \
+ a, \
+ SMM_ACCESS_PRIVATE_DATA, \
+ SmmAccess, \
+ SMM_ACCESS_PRIVATE_DATA_SIGNATURE \
+ )
+
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+EFI_STATUS
+EFIAPI
+SmmAccessDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ This is the standard EFI driver point that detects
+ whether there is an proper chipset in the system
+ and if so, installs an SMM Access Protocol.
+
+Arguments:
+
+ ImageHandle - Handle for the image of this driver.
+ SystemTable - Pointer to the EFI System Table.
+
+Returns:
+
+ EFI_SUCCESS - Protocol successfully started and installed.
+ EFI_UNSUPPORTED - Protocol can't be started.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+Open (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "open" a region of SMRAM. The
+ region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
+ The use of "open" means that the memory is visible from all boot-service
+ and SMM agents.
+
+Arguments:
+
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Open.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully opened.
+ EFI_DEVICE_ERROR - The region could not be opened because locked by
+ chipset.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+Close (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "close" a region of SMRAM. This is valid for
+ compatible SMRAM region.
+
+Arguments:
+
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Close.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully closed.
+ EFI_DEVICE_ERROR - The region could not be closed because locked by
+ chipset.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+Lock (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "lock" SMRAM. The
+ region could be legacy AB or TSEG near top of physical memory.
+ The use of "lock" means that the memory can no longer be opened
+ to BS state..
+
+Arguments:
+
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Lock.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully locked.
+ EFI_DEVICE_ERROR - The region could not be locked because at least
+ one range is still open.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+GetCapabilities (
+ IN CONST EFI_SMM_ACCESS2_PROTOCOL *This,
+ IN OUT UINTN *SmramMapSize,
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
+ )
+/*++
+
+Routine Description:
+
+ This routine services a user request to discover the SMRAM
+ capabilities of this platform. This will report the possible
+ ranges that are possible for SMRAM access, based upon the
+ memory controller capabilities.
+
+Arguments:
+
+ This - Pointer to the SMRAM Access Interface.
+ SmramMapSize - Pointer to the variable containing size of the
+ buffer to contain the description information.
+ SmramMap - Buffer containing the data describing the Smram
+ region descriptors.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
+ EFI_SUCCESS - The user provided a sufficiently-sized buffer.
+
+--*/
+;
+VOID
+SyncRegionState2SmramDesc(
+ IN BOOLEAN OrAnd,
+ IN UINT64 Value
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDriver.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDriver.c
new file mode 100755
index 0000000..11d5d33
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDriver.c
@@ -0,0 +1,384 @@
+/** @file
+ This module produces the SMM COntrol2 Protocol for QNC
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiDxe.h>
+#include <Protocol/SmmControl2.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <IntelQNCDxe.h>
+#include <Library/QNCAccessLib.h>
+#include <Uefi/UefiBaseType.h>
+
+#define EFI_INTERNAL_POINTER 0x00000004
+
+extern EFI_GUID gEfiEventVirtualAddressChangeGuid;
+
+/**
+ Generates an SMI using the parameters passed in.
+
+ @param This A pointer to an instance of
+ EFI_SMM_CONTROL2_PROTOCOL
+ @param ArgumentBuffer The argument buffer
+ @param ArgumentBufferSize The size of the argument buffer
+ @param Periodic TRUE to indicate a periodical SMI
+ @param ActivationInterval Interval of the periodical SMI
+
+ @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
+ @return Return value from SmmTrigger().
+
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN OUT UINT8 *CommandPort OPTIONAL,
+ IN OUT UINT8 *DataPort OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
+ );
+
+/**
+ Clears an SMI.
+
+ @param This Pointer to an instance of EFI_SMM_CONTROL2_PROTOCOL
+ @param Periodic TRUE to indicate a periodical SMI
+
+ @return Return value from SmmClear()
+
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN BOOLEAN Periodic OPTIONAL
+ );
+
+///
+/// Handle for the SMM Control2 Protocol
+///
+EFI_HANDLE mSmmControl2Handle = NULL;
+
+///
+/// SMM COntrol2 Protocol instance
+///
+EFI_SMM_CONTROL2_PROTOCOL mSmmControl2 = {
+ Activate,
+ Deactivate,
+ 0
+};
+
+VOID
+EFIAPI
+SmmControlVirtualddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+Arguments:
+
+ Event The event registered.
+ Context Event context.
+
+Returns:
+
+ None.
+
+--*/
+{
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl2.Trigger));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl2.Clear));
+}
+
+/**
+ Clear SMI related chipset status and re-enable SMI by setting the EOS bit.
+
+ @retval EFI_SUCCESS The requested operation has been carried out successfully
+ @retval EFI_DEVICE_ERROR The EOS bit could not be set.
+
+**/
+EFI_STATUS
+SmmClear (
+ VOID
+ )
+{
+ UINT16 PM1BLK_Base;
+ UINT16 GPE0BLK_Base;
+
+ //
+ // Get PM1BLK_Base & GPE0BLK_Base
+ //
+ PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);
+ GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
+
+ //
+ // Clear the Power Button Override Status Bit, it gates EOS from being set.
+ // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.
+ //
+
+ //
+ // Clear the APM SMI Status Bit
+ //
+ IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);
+
+ //
+ // Set the EOS Bit
+ //
+ IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates an SMI using the parameters passed in.
+
+ @param This A pointer to an instance of
+ EFI_SMM_CONTROL_PROTOCOL
+ @param ArgumentBuffer The argument buffer
+ @param ArgumentBufferSize The size of the argument buffer
+ @param Periodic TRUE to indicate a periodical SMI
+ @param ActivationInterval Interval of the periodical SMI
+
+ @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
+ @retval EFI_SUCCESS SMI generated
+
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN OUT UINT8 *CommandPort OPTIONAL,
+ IN OUT UINT8 *DataPort OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
+ )
+{
+ UINT16 GPE0BLK_Base;
+ UINT32 NewValue;
+
+ //
+ // Get GPE0BLK_Base
+ //
+ GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
+
+ if (Periodic) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Clear any pending the APM SMI
+ //
+ if (EFI_ERROR (SmmClear())) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Enable the APMC SMI
+ //
+ IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM);
+
+ //
+ // Enable SMI globally
+ //
+ NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ NewValue |= SMI_EN;
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
+
+
+ //
+ // Set APMC_STS
+ //
+ if (DataPort == NULL) {
+ IoWrite8 (PcdGet16 (PcdSmmDataPort), 0xFF);
+ } else {
+ IoWrite8 (PcdGet16 (PcdSmmDataPort), *DataPort);
+ }
+
+ //
+ // Generate the APMC SMI
+ //
+ if (CommandPort == NULL) {
+ IoWrite8 (PcdGet16 (PcdSmmActivationPort), 0xFF);
+ } else {
+ IoWrite8 (PcdGet16 (PcdSmmActivationPort), *CommandPort);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clears an SMI.
+
+ @param This Pointer to an instance of EFI_SMM_CONTROL_PROTOCOL
+ @param Periodic TRUE to indicate a periodical SMI
+
+ @return Return value from SmmClear()
+
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN BOOLEAN Periodic
+ )
+{
+ if (Periodic) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return SmmClear();
+}
+
+/**
+ This is the constructor for the SMM Control protocol.
+
+ This function installs EFI_SMM_CONTROL2_PROTOCOL.
+
+ @param ImageHandle Handle for the image of this driver
+ @param SystemTable Pointer to the EFI System Table
+
+ @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
+ @return The status returned from InstallProtocolInterface().
+
+--*/
+EFI_STATUS
+SmmControl2Init (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+ UINT16 PM1BLK_Base;
+ UINT16 GPE0BLK_Base;
+ BOOLEAN SciEn;
+ UINT32 NewValue;
+
+ //
+ // Get PM1BLK_Base & GPE0BLK_Base
+ //
+ PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);
+ GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
+
+ //
+ // Install our protocol interfaces on the device's handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mSmmControl2Handle,
+ &gEfiSmmControl2ProtocolGuid, &mSmmControl2,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Determine whether an ACPI OS is present (via the SCI_EN bit)
+ //
+ SciEn = (BOOLEAN)((IoRead16 (PM1BLK_Base + R_QNC_PM1BLK_PM1C) & B_QNC_PM1BLK_PM1C_SCIEN) != 0);
+ if (!SciEn) {
+ //
+ // Clear any SMIs that double as SCIs (when SCI_EN==0)
+ //
+ IoWrite16 ((PM1BLK_Base + R_QNC_PM1BLK_PM1S), B_QNC_PM1BLK_PM1S_ALL);
+ IoWrite16 ((PM1BLK_Base + R_QNC_PM1BLK_PM1E), 0x00000000);
+ IoWrite32 ((PM1BLK_Base + R_QNC_PM1BLK_PM1C), 0x00000000);
+ IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_GPE0S), B_QNC_GPE0BLK_GPE0S_ALL);
+ IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_GPE0E), 0x00000000);
+ }
+
+ //
+ // Clear and disable all SMIs that are unaffected by SCI_EN
+ // Set EOS
+ //
+ IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), 0x00000000);
+ IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), (B_QNC_GPE0BLK_SMIS_EOS + B_QNC_GPE0BLK_SMIS_ALL));
+
+ //
+ // Enable SMI globally
+ //
+ NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ NewValue |= SMI_EN;
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
+
+ //
+ // Make sure to write this register last -- EOS re-enables SMIs for the QNC
+ //
+ IoAndThenOr32 (
+ GPE0BLK_Base + R_QNC_GPE0BLK_SMIE,
+ (UINT32)(~B_QNC_GPE0BLK_SMIE_ALL),
+ B_QNC_GPE0BLK_SMIE_APM
+ );
+
+ //
+ // Make sure EOS bit cleared
+ //
+ DEBUG_CODE_BEGIN ();
+ if (IoRead32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS) & B_QNC_GPE0BLK_SMIS_EOS) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "******************************************************************************\n"
+ "BIG ERROR: SmmControl constructor couldn't properly initialize the ACPI table.\n"
+ " SmmControl->Clear will probably hang. \n"
+ " NOTE: SCI_EN = %d \n"
+ "******************************************************************************\n",
+ SciEn
+ ));
+
+ //
+ // If we want the system to stop, then keep the ASSERT(FALSE).
+ // Otherwise, comment it out.
+ //
+ ASSERT (FALSE);
+ }
+ DEBUG_CODE_END ();
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ SmmControlVirtualddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf
new file mode 100755
index 0000000..08295da
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf
@@ -0,0 +1,80 @@
+## @file
+# QNC SmmControl driver to install EFI_SMM_CONTROL_PROTOCOL.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmControlDxe
+ FILE_GUID = A03A9429-C570-4ef9-9E00-C7A673976E5F
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SmmControl2Init
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SmmControlDriver.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ PcdLib
+ IoLib
+ PciLib
+ QNCAccessLib
+
+[Protocols]
+ gEfiSmmControl2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmDataPort
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
+
+[Depex]
+ TRUE
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.c
new file mode 100644
index 0000000..6515a7c
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.c
@@ -0,0 +1,890 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmmRuntime.c
+
+Abstract:
+
+ SMM Runtime Infrastructutre for the IA32 Runtime drivers.
+
+--*/
+
+#include "SmmRuntime.h"
+
+EFI_SMM_RT_GLOBAL *SmmRtGlobal;
+EFI_SMM_RUNTIME_PROTOCOL *mSmmRT = NULL;
+
+EFI_STATUS
+CheckCallbacks (
+ IN EFI_GUID *Protocol
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Protocol - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINTN i;
+
+ //
+ // Check if any notifications are pending.
+ //
+ for (i = 0; i < MAX_CALLBACK; i++) {
+ if (SmmRtGlobal->Callback[i].Valid) {
+ if (CompareGuid (Protocol, &SmmRtGlobal->Callback[i].ProtocolGuid)) {
+ SmmRtGlobal->Callback[i].CallbackFunction (
+ &SmmRtGlobal->Callback[i],
+ SmmRtGlobal->Callback[i].Context
+ );
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SmmSignalCallback (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Event - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_SMM_CALLBACK_SERVICES *Callback;
+
+ Callback = (EFI_SMM_CALLBACK_SERVICES *) Event;
+
+ if (Callback->CallbackFunction != NULL) {
+ Callback->CallbackFunction (Event, Callback->Context);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SmmEnableProtocolNotifyCallback (
+ EFI_EVENT_NOTIFY CallbackFunction,
+ VOID *Context,
+ EFI_GUID *ProtocolGuid,
+ EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ CallbackFunction - GC_TODO: add argument description
+ Context - GC_TODO: add argument description
+ ProtocolGuid - GC_TODO: add argument description
+ Event - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
+
+--*/
+{
+ UINTN i;
+
+ for (i = 0; i < MAX_CALLBACK; i++) {
+ if (!SmmRtGlobal->Callback[i].Valid) {
+ SmmRtGlobal->Callback[i].Context = Context;
+ SmmRtGlobal->Callback[i].CallbackFunction = CallbackFunction;
+ CopyMem (&SmmRtGlobal->Callback[i].ProtocolGuid, ProtocolGuid, sizeof (EFI_GUID));
+ SmmRtGlobal->Callback[i].Valid = TRUE;
+ *Event = (EFI_EVENT) & SmmRtGlobal->Callback[i];
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+EFI_STATUS
+EFIAPI
+SmmDisableProtocolNotifyCallback (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Event - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_SMM_CALLBACK_SERVICES *Callback;
+
+ Callback = (EFI_SMM_CALLBACK_SERVICES *) Event;
+
+ Callback->Valid = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CheckServiceIndex (
+ IN UINTN Index,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ )
+/*++
+
+ Routine Description:
+ This Function gets the protocol interface related with the Index and updates the
+ internal data index when protocol match is found.
+
+ Arguments:
+ Index - Relative Index where protocol match should be done
+ Protocol - Protocol that should be matched with at the input Index.
+ Interface - Pointer to the Interface that matches with the protocol at a given Index.
+
+ Returns:
+ EFI_SUCCESS - Protocol Match done successfully.
+ EFI_NOT_FOUND - Protocol Match couldn't be done.
+
+--*/
+{
+ if (SmmRtGlobal->Services[Index].Valid) {
+ if (CompareGuid (Protocol, &SmmRtGlobal->Services[Index].ProtocolGuid)) {
+ *Interface = SmmRtGlobal->Services[Index].Protocol;
+ SmmRtGlobal->CurrentIndex = Index;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+LocateSmmProtocol (
+ EFI_GUID *Protocol,
+ VOID *Registration, OPTIONAL
+ VOID **Interface
+ )
+/*++
+
+ Routine Description:
+ This Function locates the protocol interrface that satisfy the protocol GUID defination
+
+ Arguments:
+ Protocol - Protocol GUID.
+ Registration - Optional per EFI specifications. Not required in SMM scope.
+ Interface - Pointer to the Interface that contains the protocol.
+
+ Returns:
+ EFI_SUCCESS - Protocol Interface located within SMM scope.
+
+--*/
+// GC_TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ UINTN i;
+
+ for (i = SmmRtGlobal->CurrentIndex; i < MAX_SMM_PROTOCOL; i++) {
+ if (CheckServiceIndex (i, Protocol, Interface) == EFI_SUCCESS) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ for (i = 0; i < SmmRtGlobal->CurrentIndex; i++) {
+ if (CheckServiceIndex (i, Protocol, Interface) == EFI_SUCCESS) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+LocateSmmProtocolHandles (
+ IN EFI_GUID *Protocol,
+ OUT EFI_HANDLE **Handles,
+ OUT UINTN *HandlesCount
+ )
+/*++
+
+ Routine Description:
+ This Function get the handles for a specific protocol.
+
+ Arguments:
+ Protocol - Protocol GUID.
+ Handles - Array of handles that satisfy the protocol defination.
+ HandlesCount - Number of handles found
+
+ Returns:
+ EFI_SUCCESS - Protocol handles located within SMM scope.
+
+--*/
+{
+ UINTN Index;
+ UINTN NumHandles;
+ UINTN Size;
+ EFI_HANDLE *Buffer;
+ EFI_STATUS Status;
+ NumHandles = 0;
+ Buffer = NULL;
+
+
+ for (Index = 0; Index < MAX_SMM_PROTOCOL; Index++) {
+ if (SmmRtGlobal->Services[Index].Valid) {
+ if (CompareGuid (Protocol, &SmmRtGlobal->Services[Index].ProtocolGuid)) {
+ SmmRtGlobal->HandleBuffer[NumHandles] = SmmRtGlobal->Services[Index].Handle;
+ NumHandles++;
+ }
+ }
+ }
+
+ Size = NumHandles * sizeof (EFI_HANDLE);
+ if (Size > 0) {
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, Size, (VOID *)&Buffer);
+ CopyMem (Buffer, SmmRtGlobal->HandleBuffer, Size);
+ *Handles = Buffer;
+ *HandlesCount = NumHandles;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SmmHandleProtocol (
+ IN EFI_HANDLE Handle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ )
+/*++
+
+ Routine Description:
+ This Function gets the interface pointer based upon the handle
+
+ Arguments:
+ Handle - Protocol handle that is Installed within SMM space.
+ Protocol - Protocol GUID.
+ Interface - Interface pointer that points to a protocol.
+
+ Returns:
+ EFI_SUCCESS - Protocol Interface found within SMM scope.
+ EFI_NOT_FOUND - Protocol not found.
+
+--*/
+{
+ EFI_SMM_PROTO_SERVICES *SmmServices;
+
+ SmmServices = (EFI_SMM_PROTO_SERVICES *) Handle;
+
+ if (SmmServices->Valid) {
+ *Interface = SmmServices->Protocol;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+}
+
+EFI_STATUS
+EFIAPI
+InstallSmmProtocolInterface (
+ IN OUT EFI_HANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface
+ )
+/*++
+
+ Routine Description:
+ This Function Installs the protocol interface within SMM scope.
+
+ Arguments:
+ Handle - Protocol handle that is to be Installed within SMM space. On NULL we gat a new Protocol
+ Handle
+ Protocol - Protocol GUID that is to be Installed.
+ InterfaceType - Type of Interface per EFI specification.
+ Interface - Interface that needs to be Installed.
+
+ Returns:
+ EFI_SUCCESS - Protocol Installed within SMM scope.
+ EFI_OUT_OF_RESOURCES - No more resources available to install another interface.
+
+--*/
+{
+ UINTN i;
+
+ for (i = 0; i < MAX_SMM_PROTOCOL; i++) {
+ if (!SmmRtGlobal->Services[i].Valid) {
+ SmmRtGlobal->Services[i].InterfaceType = InterfaceType;
+ SmmRtGlobal->Services[i].Protocol = Interface;
+ CopyMem (&SmmRtGlobal->Services[i].ProtocolGuid, Protocol, sizeof (EFI_GUID));
+ SmmRtGlobal->Services[i].Valid = TRUE;
+ if (*Handle == NULL) {
+ SmmRtGlobal->Services[i].Handle = &SmmRtGlobal->Services[i];
+ *Handle = SmmRtGlobal->Services[i].Handle;
+ } else {
+ SmmRtGlobal->Services[i].Handle = *Handle;
+ }
+
+ CheckCallbacks (Protocol);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+EFI_STATUS
+EFIAPI
+ReinstallSmmProtocolInterface (
+ IN EFI_HANDLE SmmProtocolHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *OldInterface,
+ IN VOID *NewInterface
+ )
+/*++
+
+ Routine Description:
+ This Function Re-Installs the protocol interface within SMM scope.
+
+ Arguments:
+ SmmProtocolHandle - Protocol handle that is to be Un-Installed.
+ Protocol - Protocol GUID that is to be Un-Installed.
+ OldInterface - Current Interface that needs to be Re-Installed.
+ NewInterface - New Interface that needs to be Re-Installed over OldInterface.
+
+ Returns:
+ EFI_SUCCESS - Protocol Re-Installed within SMM scope.
+ EFI_NOT_FOUND - Old Interface Not Found.
+
+--*/
+{
+ UINTN i;
+
+ for (i = 0; i < MAX_SMM_PROTOCOL; i++) {
+ if (SmmRtGlobal->Services[i].Valid) {
+ if (SmmProtocolHandle == SmmRtGlobal->Services[i].Handle) {
+ if (OldInterface == SmmRtGlobal->Services[i].Protocol) {
+ SmmRtGlobal->Services[i].Protocol = NewInterface;
+ CheckCallbacks (NewInterface);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+UninstallSmmProtocolInterface (
+ IN EFI_HANDLE SmmProtocolHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+ Routine Description:
+ This Function Un-Installs the protocol interface from within SMM scope.
+
+ Arguments:
+ SmmProtocolHandle - Protocol handle that is to be Un-Installed.
+ Protocol - Protocol GUID that is to be Un-Installed.
+ Interface - Interface Pointer that needs to be Un-Installed.
+ Returns:
+ EFI_SUCCESS - Protocol Uninstalled from within SMM scope.
+ EFI_NOT_FOUND - Protocol Not Found.
+
+--*/
+{
+ UINTN i;
+
+ for (i = 0; i < MAX_SMM_PROTOCOL; i++) {
+ if (SmmRtGlobal->Services[i].Valid) {
+ if (SmmProtocolHandle == SmmRtGlobal->Services[i].Handle) {
+ if (CompareGuid (Protocol, &SmmRtGlobal->Services[i].ProtocolGuid)) {
+ if (Interface == SmmRtGlobal->Services[i].Protocol) {
+ SmmRtGlobal->Services[i].Valid = FALSE;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+InstallVendorConfigurationTable (
+ IN EFI_GUID *Guid,
+ IN VOID *Table
+ )
+/*++
+
+ Routine Description:
+ This Function installs the configuration table within SMM scope.
+
+ Arguments:
+ Guid - Vandor GUID
+ Table - Pointer to the Table. This table should be located within SMM scope.
+
+ Returns:
+ EFI_SUCCESS - Vendor table Found
+ EFI_OUT_OF_RESOURCES - Vendor Table cannot be registered because no more SMM resources are there.
+
+--*/
+{
+ UINTN i;
+
+ //
+ // Check if the vendor GUID already exists.
+ //
+ for (i = 0; i < MAX_SMM_PROTOCOL; i++) {
+ if (SmmRtGlobal->ConfigTable[i].VendorTable != NULL) {
+ if (CompareGuid (&SmmRtGlobal->ConfigTable[i].VendorGuid, Guid)) {
+ SmmRtGlobal->ConfigTable[i].VendorTable = Table;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // If the Vendor GUID don't exist, Find an empty slot.
+ //
+ for (i = 0; i < MAX_SMM_PROTOCOL; i++) {
+ if (SmmRtGlobal->ConfigTable[i].VendorTable == NULL) {
+ CopyMem (&SmmRtGlobal->ConfigTable[i].VendorGuid, Guid, sizeof (EFI_GUID));
+ SmmRtGlobal->ConfigTable[i].VendorTable = Table;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+EFI_STATUS
+EFIAPI
+GetVendorConfigurationTable (
+ IN EFI_GUID *Guid,
+ OUT VOID **Table
+ )
+/*++
+
+ Routine Description:
+ This Function gets the configuration table that has been registered within SMM scope.
+
+ Arguments:
+ Guid - Vandor GUID
+ Table - Pointer to the Table. This table should be located within SMM scope.
+
+ Returns:
+ EFI_SUCCESS - Vendor table Found
+ EFI_NOT_FOUND - Vendor Table not found.
+
+--*/
+{
+ UINTN i;
+
+ //
+ // Check if the vendor GUID already exists.
+ //
+ for (i = 0; i < MAX_SMM_PROTOCOL; i++) {
+ if (SmmRtGlobal->ConfigTable[i].VendorTable != NULL) {
+ if (CompareGuid (&SmmRtGlobal->ConfigTable[i].VendorGuid, Guid)) {
+ *Table = SmmRtGlobal->ConfigTable[i].VendorTable;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+EfiRegisterRuntimeCallback (
+ IN EFI_SMM_RUNTIME_CALLBACK SmmRuntimeCallback,
+ IN VOID *Context,
+ OUT EFI_HANDLE *SmmRuntimeCallHandle
+ )
+/*++
+
+ Routine Description:
+ This Function Registers the Callback Function from executing.
+
+ Arguments:
+ SmmRuntimeCallback - Callback Function Name.
+ Context - Context, that is saved and restored when callback function is called.
+ ChildRuntimeBuffer - Returns the pointer to the messaging buffer that is to be used for SMM communication.
+ SmmRuntimeCallHandle - EFI Handle for the callback function. This handle is valid within SMM scope only.
+
+ Returns:
+ EFI_SUCCESS - Callback Function Registered Successfully.
+ EFI_OUT_OF_RESOURCES - All SMM resources have been used up. So more callback functions cannot
+ be registered.
+--*/
+{
+ UINTN i;
+
+ for (i = 0; i < MAX_SM_RT_CALLBACK; i++) {
+ if (SmmRtGlobal->RtCallback[i].CallbackFunction == NULL) {
+ SmmRtGlobal->RtCallback[i].CallbackFunction = SmmRuntimeCallback;
+ SmmRtGlobal->RtCallback[i].Context = Context;
+ *SmmRuntimeCallHandle = &SmmRtGlobal->RtCallback[i];
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+EFI_STATUS
+EFIAPI
+EfiUnRegisterRuntimeCallback (
+ IN EFI_SMM_RUNTIME_CALLBACK SmmRuntimeCallback
+ )
+/*++
+
+ Routine Description:
+ This Function Un-Registers the Callback Function from executing.
+
+ Arguments:
+ SmmRuntimeCallback - Callback Function Name.
+
+ Returns:
+ EFI_SUCCESS - Callback Function UnRegistered.
+ EFI_NOT_FOUND - Callback Function not found.
+--*/
+{
+ UINTN i;
+
+ for (i = 0; i < MAX_SM_RT_CALLBACK; i++) {
+ if (SmmRtGlobal->RtCallback[i].CallbackFunction == SmmRuntimeCallback) {
+ SmmRtGlobal->RtCallback[i].CallbackFunction = NULL;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+SmmRuntimeManagementCallback (
+ IN EFI_HANDLE SmmImageHandle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+/*++
+
+ Routine Description:
+ This Function executes the Callback Function. This function is called at every SMI occurance.
+ At the SMI occurance, it investigates if somebody asked for the Runtime Service. On a valid
+ RT Service request, it executes the callback function.
+
+ Arguments:
+ SmmImageHandle - Handle for the smm image of this driver
+ Smst - Pointer to the SMM System Table
+ CommunicationBuffer - Pointer to the buffer that contains the communication Message
+ Source Size - Size of the memory image to be used for handler.
+
+ Returns:
+ EFI_SUCCESS - Callback Function Executed
+--*/
+// GC_TODO: SourceSize - add argument and description to function comment
+{
+ SMM_RUNTIME_COMMUNICATION_STRUCTURE *SmmRtStruct;
+ EFI_SMM_RT_CALLBACK_SERVICES *RtServices;
+
+ RtServices = NULL;
+
+ SmmRtStruct = (SMM_RUNTIME_COMMUNICATION_STRUCTURE *) CommunicationBuffer;
+ RtServices = (EFI_SMM_RT_CALLBACK_SERVICES *) SmmRtStruct->PrivateData.SmmRuntimeCallHandle;
+
+ if (RtServices != NULL) {
+ RtServices->CallbackFunction (RtServices->Context, gSmst, (VOID *) &SmmRtStruct->PrivateData);
+ SmmRtStruct->PrivateData.SmmRuntimeCallHandle = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+UINTN
+DevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ DevicePath - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *Start;
+
+ if (DevicePath == NULL) {
+ return 0;
+ }
+ //
+ // Search for the end of the device path structure
+ //
+ Start = DevicePath;
+ while (!IsDevicePathEnd (DevicePath)) {
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+ //
+ // Compute the size and add back in the size of the end device path structure
+ //
+ return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
+}
+
+EFI_STATUS
+SmmRuntimeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ ImageHandle - GC_TODO: add argument description
+ SystemTable - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_SMM_BASE2_PROTOCOL *SmmBase;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ UINTN Size;
+ BOOLEAN InSmm;
+ EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication;
+ EFI_SMM_RT_GLOBAL *RtGlobal;
+ RtGlobal = NULL;
+
+
+
+
+ Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, &SmmBase);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ SmmBase->InSmm (SmmBase, &InSmm);
+
+ SmmBase->GetSmstLocation (SmmBase, &gSmst);
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (EFI_SMM_RT_GLOBAL), &SmmRtGlobal);
+/****************************************************
+** **
+** EST override - begins here **
+** **
+****************************************************/
+ ASSERT_EFI_ERROR (Status);
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++
+++ ++
+++ EST override - ends here ++
+++ ++
++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+ if (Status == EFI_SUCCESS) {
+ ZeroMem (SmmRtGlobal, sizeof (EFI_SMM_RT_GLOBAL));
+ }
+
+ Status = gBS->AllocatePool (
+ EfiReservedMemoryType,
+ sizeof (SMM_RUNTIME_COMMUNICATION_STRUCTURE),
+ &SmmRtGlobal->SmmRtServices.ChildRuntimeBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem (SmmRtGlobal->SmmRtServices.ChildRuntimeBuffer, sizeof (SMM_RUNTIME_COMMUNICATION_STRUCTURE));
+
+ Status = gBS->AllocatePool (EfiReservedMemoryType, sizeof (EFI_SMM_RT_GLOBAL), &RtGlobal);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem (RtGlobal, sizeof (EFI_SMM_RT_GLOBAL));
+
+ //
+ // Register the Callback function that acts as a parent dispatcher for all the Runtime Functions.
+ // Any RT function call should be a child of this callback.
+ //
+ SmmRtGlobal->SmmRtServices.ChildRuntimeBuffer->MessageLength = sizeof (SMM_RUNTIME_COMMUNICATION_STRUCTURE);
+ SmmRtGlobal->SmmRtServices.ChildRuntimeBuffer->HeaderGuid = gEfiSmmRuntimeProtocolGuid;
+
+ Status = gSmst->SmiHandlerRegister (
+ SmmRuntimeManagementCallback,
+ &gEfiSmmRuntimeProtocolGuid,
+ &ImageHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ SmmRtGlobal->CallbackEntryPoint = SmmRuntimeManagementCallback;
+
+ Size = sizeof (SMM_RUNTIME_COMMUNICATION_STRUCTURE);
+
+ Status = gBS->LocateProtocol (
+ &gEfiSmmCommunicationProtocolGuid,
+ NULL,
+ (VOID **)&SmmCommunication
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SmmCommunication->Communicate (
+ SmmCommunication,
+ (VOID *) SmmRtGlobal->SmmRtServices.ChildRuntimeBuffer,
+ &Size
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the services that are called within the SMM scope. All Runtime Libraries will use these
+ // functions to create the services required for driver bindings within the SMM space.
+ //
+ SmmRtGlobal->Signature = SMM_RT_SIGNATURE;
+ SmmRtGlobal->SmmRtServices.InstallProtocolInterface = InstallSmmProtocolInterface;
+ SmmRtGlobal->SmmRtServices.LocateProtocol = LocateSmmProtocol;
+ SmmRtGlobal->SmmRtServices.ReinstallProtocolInterface = ReinstallSmmProtocolInterface;
+ SmmRtGlobal->SmmRtServices.UninstallProtocolInterface = UninstallSmmProtocolInterface;
+ SmmRtGlobal->SmmRtServices.SignalProtocol = SmmSignalCallback;
+ SmmRtGlobal->SmmRtServices.EnableProtocolNotify = SmmEnableProtocolNotifyCallback;
+ SmmRtGlobal->SmmRtServices.DisableProtocolNotify = SmmDisableProtocolNotifyCallback;
+ SmmRtGlobal->SmmRtServices.LocateProtocolHandles = LocateSmmProtocolHandles;
+ SmmRtGlobal->SmmRtServices.HandleProtocol = SmmHandleProtocol;
+ SmmRtGlobal->SmmRtServices.InstallVendorConfigTable = InstallVendorConfigurationTable;
+ SmmRtGlobal->SmmRtServices.GetVendorConfigTable = GetVendorConfigurationTable;
+ SmmRtGlobal->SmmRtServices.RegisterSmmRuntimeChild = EfiRegisterRuntimeCallback;
+ SmmRtGlobal->SmmRtServices.UnRegisterSmmRuntimeChild = EfiUnRegisterRuntimeCallback;
+
+ SmmRtGlobal->SmmRtServices.SmmRuntime.Hdr.Signature = 0;
+ SmmRtGlobal->SmmRtServices.SmmRuntime.Hdr.Revision = EFI_RUNTIME_SERVICES_REVISION;
+ SmmRtGlobal->SmmRtServices.SmmRuntime.Hdr.HeaderSize = sizeof (EFI_TABLE_HEADER);
+
+/****************************************************
+** **
+** EST override - begins here **
+** **
+****************************************************/
+
+ CopyMem (&SmmRtGlobal->SmmRtServices.SmmRuntime, SystemTable->RuntimeServices, sizeof (EFI_RUNTIME_SERVICES));
+
+/****************************************************
+** **
+** EST override - ends here **
+** **
+****************************************************/
+
+ //
+ // Install the Driver within the SMM scope so that drivers created within the SMM scope can find it
+ // and use the functionality. Runtime Library searches the protocol for performing the above functions.
+ //
+ Handle = NULL;
+ Status = InstallSmmProtocolInterface (
+ &Handle,
+ &gEfiSmmRuntimeProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(SmmRtGlobal->SmmRtServices)
+ );
+ ASSERT_EFI_ERROR (Status);
+ mSmmRT = &SmmRtGlobal->SmmRtServices;
+
+ //
+ // Install the Protocol Interface in the Boot Time Space. This is requires to satisfy the
+ // dependency within the drivers that are dependent upon Smm Runtime Driver.
+ //
+ Handle = NULL;
+ CopyMem (RtGlobal, SmmRtGlobal, sizeof (EFI_SMM_RT_GLOBAL));
+
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiSmmRuntimeProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(RtGlobal->SmmRtServices)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.h b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.h
new file mode 100644
index 0000000..c740028
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.h
@@ -0,0 +1,114 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ SmmRuntime.h
+
+Abstract:
+
+ Implementation specific SMM Runtime stuff
+
+--*/
+
+#ifndef _SMM_RUNTIME_H_
+#define _SMM_RUNTIME_H_
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SmmServicesTableLib.h>
+
+#include <Protocol/SmmBase2.h>
+/****************************************************
+** **
+** EST override - begins here **
+** **
+****************************************************/
+#include <Protocol/SmmAccess2.h>
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++
+++ ++
+++ EST override - ends here ++
+++ ++
++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SmmRtProtocol.h>
+#include <Protocol/SmmCommunication.h>
+
+#define MAX_SMM_PROTOCOL 100
+#define MAX_CALLBACK 100
+#define MAX_HANDLES 100
+#define MAX_CONFIG_TABLE 100
+#define MAX_SM_RT_CALLBACK 100
+
+typedef struct {
+ BOOLEAN Valid;
+ EFI_GUID ProtocolGuid;
+ EFI_INTERFACE_TYPE InterfaceType;
+ VOID *Protocol;
+ EFI_HANDLE Handle;
+} EFI_SMM_PROTO_SERVICES;
+
+typedef struct {
+ BOOLEAN Valid;
+ VOID *Context;
+ EFI_GUID ProtocolGuid;
+ EFI_EVENT_NOTIFY CallbackFunction;
+} EFI_SMM_CALLBACK_SERVICES;
+
+typedef struct {
+ VOID *Context;
+ EFI_SMM_RUNTIME_CALLBACK CallbackFunction;
+} EFI_SMM_RT_CALLBACK_SERVICES;
+
+typedef struct {
+ UINTN Signature;
+ UINTN CurrentIndex;
+ EFI_SMM_PROTO_SERVICES Services[MAX_SMM_PROTOCOL];
+ EFI_SMM_CALLBACK_SERVICES Callback[MAX_CALLBACK];
+ EFI_SMM_RT_CALLBACK_SERVICES RtCallback[MAX_SM_RT_CALLBACK];
+ EFI_HANDLE HandleBuffer[MAX_HANDLES];
+ EFI_CONFIGURATION_TABLE ConfigTable[MAX_CONFIG_TABLE];
+ EFI_SMM_RUNTIME_PROTOCOL SmmRtServices;
+ EFI_SMM_HANDLER_ENTRY_POINT2 CallbackEntryPoint;
+} EFI_SMM_RT_GLOBAL;
+
+//
+// BMC Elog Instance signature
+//
+#define SMM_RT_SIGNATURE SIGNATURE_32 ('s', 'm', 'r', 't')
+
+#define INSTANCE_FROM_EFI_SMM_RT_THIS(a) CR (a, EFI_SMM_RT_GLOBAL, SmmRtServices, SMM_RT_SIGNATURE)
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.inf
new file mode 100644
index 0000000..6e1b4d8
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.inf
@@ -0,0 +1,78 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Module Name:
+#
+# SmmRuntime.inf
+#
+# Abstract:
+#
+# Component description file for SMM Runtime module.
+#
+--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmRuntime
+ FILE_GUID = 7C79AC8C-5E6C-4e3d-BA6F-C260EE7C172E
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SmmRuntimeInitialize
+
+[Sources]
+ SmmRuntime.c
+ SmmRuntime.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DevicePathLib
+ MemoryAllocationLib
+ SmmServicesTableLib
+
+[Protocols]
+ gEfiSmmRuntimeProtocolGuid #always produces
+ gEfiSmmBase2ProtocolGuid
+ gEfiSmmAccess2ProtocolGuid
+ gEfiSmmCommunicationProtocolGuid
+
+[Depex]
+ gEfiSmmBase2ProtocolGuid AND
+ gEfiSmmAccess2ProtocolGuid
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/CommonHeader.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/CommonHeader.h
new file mode 100644
index 0000000..b4d6f1b
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/CommonHeader.h
@@ -0,0 +1,69 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+
+#include <FrameworkSmm.h>
+#include <IntelQNCDxe.h>
+
+#include <Protocol/SmmUsbDispatch2.h>
+#include <Protocol/SmmPeriodicTimerDispatch2.h>
+#include <Protocol/SmmIchnDispatch2.h>
+#include <Protocol/SmmPowerButtonDispatch2.h>
+#include <Protocol/SmmGpiDispatch2.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Protocol/SmmCpu.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/S3IoLib.h>
+#include <Library/QNCAccessLib.h>
+
+#include <Uefi/UefiBaseType.h>
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmGpi.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmGpi.c
new file mode 100644
index 0000000..74ee352
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmGpi.c
@@ -0,0 +1,63 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCSmmGpi.c
+
+Abstract:
+
+ File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmmHelpers.h"
+
+CONST QNC_SMM_SOURCE_DESC GPI_SOURCE_DESC = {
+ QNC_SMM_NO_FLAGS,
+ {
+ {
+ {GPE_ADDR_TYPE, R_QNC_GPE0BLK_SMIE}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_GPIO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {GPE_ADDR_TYPE, R_QNC_GPE0BLK_SMIS}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_GPIO
+ }
+ }
+};
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmHelpers.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmHelpers.c
new file mode 100755
index 0000000..52e99fc
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmHelpers.c
@@ -0,0 +1,573 @@
+/*++
+
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the QNC SMI sources.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmmHelpers.h"
+
+//
+// Help handle porting bit shifts to IA-64.
+//
+#define BIT_ZERO 0x00000001
+
+
+VOID
+QNCSmmPublishDispatchProtocols(
+ VOID
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+
+ //
+ // Install protocol interfaces.
+ //
+ for (Index = 0; Index < NUM_PROTOCOLS; Index++) {
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mPrivateData.InstallMultProtHandle,
+ mPrivateData.Protocols[Index].Guid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.Protocols[Index].Protocols.Generic
+ );
+
+ ASSERT_EFI_ERROR (Status);
+}
+}
+
+EFI_STATUS
+QNCSmmInitHardware(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize bits that aren't necessarily related to an SMI source.
+
+Dependencies:
+
+ gSmst - SMM System Table; contains an entry for SMM CPU IO
+
+Returns:
+
+ EFI_SUCCESS. Asserts, otherwise.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Clear all SMIs
+ //
+ QNCSmmClearSmi();
+
+ Status = QNCSmmEnableGlobalSmiBit ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Be *really* sure to clear all SMIs
+ //
+ QNCSmmClearSmi ();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+QNCSmmEnableGlobalSmiBit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enables the QNC to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS.
+ Asserts, otherwise.
+
+--*/
+{
+ UINT32 NewValue;
+
+ //
+ // Enable SMI globally
+ //
+ NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ NewValue |= SMI_EN;
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+QNCSmmClearSmi(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+Returns:
+
+ EFI_SUCCESS.
+ Asserts, otherwise.
+
+--*/
+{
+ BOOLEAN EosSet;
+ BOOLEAN SciEn;
+
+ UINT32 Pm1Cnt = 0;
+ UINT16 Pm1Sts = 0;
+ UINT32 Gpe0Sts = 0;
+ UINT32 SmiSts = 0;
+
+ //
+ // Determine whether an ACPI OS is present (via the SCI_EN bit)
+ //
+ Pm1Cnt = IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
+ SciEn = (BOOLEAN)((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == B_QNC_PM1BLK_PM1C_SCIEN);
+
+ if (SciEn == FALSE) {
+
+ //
+ // Clear any SMIs that double as SCIs (when SCI_EN==0)
+ //
+ Pm1Sts = (B_QNC_PM1BLK_PM1S_WAKE | B_QNC_PM1BLK_PM1S_PCIEWSTS | B_QNC_PM1BLK_PM1S_RTC | B_QNC_PM1BLK_PM1S_GLOB | B_QNC_PM1BLK_PM1S_TO);
+
+ Gpe0Sts = B_QNC_GPE0BLK_GPE0S_ALL;
+
+ IoOr16((PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S), Pm1Sts);
+ IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S), Gpe0Sts);
+ }
+
+ //
+ // Clear all SMIs that are unaffected by SCI_EN
+ //
+ SmiSts = IoRead32((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);
+ SmiSts |= B_QNC_GPE0BLK_SMIS_ALL;
+ IoWrite32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS), SmiSts);
+
+ //
+ // Try to clear the EOS bit. ASSERT on an error
+ //
+ EosSet = QNCSmmSetAndCheckEos();
+ ASSERT (EosSet);
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+QNCSmmSetAndCheckEos(
+ VOID
+ )
+{
+ //
+ // Reset the QNC to generate subsequent SMIs
+ //
+ IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
+ return TRUE;
+}
+
+BOOLEAN
+QNCSmmGetSciEn(
+ )
+{
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+
+ //
+ // Determine whether an ACPI OS is present (via the SCI_EN bit)
+ //
+ Pm1Cnt = IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
+
+ SciEn = (BOOLEAN)((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == B_QNC_PM1BLK_PM1C_SCIEN);
+
+ return SciEn;
+}
+
+//
+// These may or may not need to change w/ the QNC version; they're highly IA-32 dependent, though.
+//
+
+BOOLEAN
+ReadBitDesc (
+ CONST QNC_SMM_BIT_DESC *BitDesc
+ )
+{
+ UINT64 Register;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ BOOLEAN BitWasOne;
+
+ ASSERT (BitDesc != NULL );
+ ASSERT (!IS_BIT_DESC_NULL( *BitDesc ) );
+
+ Register = 0;
+ BitWasOne = FALSE;
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ //
+ // Double check that we correctly read in the acpi base address
+ //
+ ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress) & 0x1) != 0x1) );
+
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized.
+ // Check your assignments to bit descriptions.
+ //
+ ASSERT (FALSE );
+ break;
+
+ case 1:
+ Register = (UINT64) IoRead8 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);
+ break;
+
+ case 2:
+ Register = (UINT64) IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);
+ break;
+
+ case 4:
+ Register = (UINT64) IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE );
+ break;
+ };
+
+ if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case GPE_ADDR_TYPE:
+ //
+ // Double check that we correctly read in the gpe base address
+ //
+ ASSERT (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) != 0x0) && (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) & 0x1) != 0x1) );
+
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized.
+ // Check your assignments to bit descriptions.
+ //
+ ASSERT (FALSE );
+ break;
+
+ case 1:
+ Register = (UINT64) IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);
+ break;
+
+ case 2:
+ Register = (UINT64) IoRead16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);
+ break;
+
+ case 4:
+ Register = (UINT64) IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE );
+ break;
+ };
+
+ if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ //
+ // Read the register, and it with the bit to read
+ //
+
+ //
+ // This code does not support reads greater then 64 bits
+ //
+ ASSERT (BitDesc->SizeInBytes <= 8);
+ CopyMem (&Register, BitDesc->Reg.Data.Mmio, BitDesc->SizeInBytes);
+ Register &= LShiftU64 (BIT0, BitDesc->Bit);
+ if (Register) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case PCI_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pci.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pci.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pci.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pci.Fields.Reg;
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized.
+ // Check your assignments to bit descriptions.
+ ASSERT (FALSE );
+ break;
+
+ case 1:
+ Register = (UINT64) PciRead8 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg));
+ break;
+
+ case 2:
+ Register = (UINT64) PciRead16 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg));
+ break;
+
+ case 4:
+ Register = (UINT64) PciRead32 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg));
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE );
+ break;
+ };
+
+ if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ default:
+ //
+ // This address type is not yet implemented
+ //
+ ASSERT (FALSE );
+ break;
+ };
+
+ return BitWasOne;
+}
+
+VOID
+WriteBitDesc (
+ CONST QNC_SMM_BIT_DESC *BitDesc,
+ CONST BOOLEAN ValueToWrite
+ )
+{
+ UINT64 Register;
+ UINT64 AndVal;
+ UINT64 OrVal;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL(*BitDesc));
+
+ AndVal = ~(BIT_ZERO << (BitDesc->Bit));
+ OrVal = ((UINT32)ValueToWrite) << (BitDesc->Bit);
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ //
+ // Double check that we correctly read in the acpi base address
+ //
+ ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress) & 0x1) != 0x1));
+
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized.
+ // Check your assignments to bit descriptions.
+ //
+ ASSERT (FALSE );
+ break;
+
+ case 1:
+ IoAndThenOr8 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT8)AndVal, (UINT8)OrVal);
+ break;
+
+ case 2:
+ IoAndThenOr16 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT16)AndVal, (UINT16)OrVal);
+ break;
+
+ case 4:
+ IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT32)AndVal, (UINT32)OrVal);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE );
+ break;
+ };
+ break;
+
+ case GPE_ADDR_TYPE:
+ //
+ // Double check that we correctly read in the gpe base address
+ //
+ ASSERT (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) != 0x0) && (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) & 0x1) != 0x1));
+
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized.
+ // Check your assignments to bit descriptions.
+ //
+ ASSERT (FALSE );
+ break;
+
+ case 1:
+ IoAndThenOr8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT8)AndVal, (UINT8)OrVal);
+ break;
+
+ case 2:
+ IoAndThenOr16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT16)AndVal, (UINT16)OrVal);
+ break;
+
+ case 4:
+ IoAndThenOr32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT32)AndVal, (UINT32)OrVal);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE );
+ break;
+ };
+ break;
+
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ //
+ // Read the register, or it with the bit to set, then write it back.
+ //
+
+ //
+ // This code does not support writes greater then 64 bits
+ //
+ ASSERT (BitDesc->SizeInBytes <= 8);
+ CopyMem (&Register, BitDesc->Reg.Data.Mmio, BitDesc->SizeInBytes);
+ Register &= AndVal;
+ Register |= OrVal;
+ CopyMem (BitDesc->Reg.Data.Mmio, &Register, BitDesc->SizeInBytes);
+ break;
+
+ case PCI_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pci.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pci.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pci.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pci.Fields.Reg;
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized -- check your assignments
+ // to bit descriptions.
+ //
+ ASSERT (FALSE );
+ break;
+
+ case 1:
+ PciAndThenOr8 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ PciAndThenOr16 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ PciAndThenOr32 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE );
+ break;
+ };
+ break;
+
+ default:
+ //
+ // This address type is not yet implemented
+ //
+ ASSERT (FALSE );
+ break;
+ };
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmPeriodicTimer.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmPeriodicTimer.c
new file mode 100644
index 0000000..c905de5
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmPeriodicTimer.c
@@ -0,0 +1,455 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCSmmPeriodicTimer.c
+
+Abstract:
+
+ File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmmHelpers.h"
+
+typedef enum {
+ PERIODIC_TIMER = 0,
+ NUM_TIMERS
+} SUPPORTED_TIMER;
+
+typedef struct _TIMER_INTERVAL
+{
+ UINT64 Interval;
+ UINT8 AssociatedTimer;
+} TIMER_INTERVAL;
+
+//
+// Time constants, in 100 nano-second units
+//
+#define TIME_64s 640000000 /* 64 s */
+#define TIME_32s 320000000 /* 32 s */
+#define TIME_16s 160000000 /* 16 s */
+#define TIME_8s 80000000 /* 8 s */
+#define TIME_64ms 640000 /* 64 ms */
+#define TIME_32ms 320000 /* 32 ms */
+#define TIME_16ms 160000 /* 16 ms */
+#define TIME_1_5ms 15000 /* 1.5 ms */
+
+// PMCW (GPE+28h) [2:0] Periodic SMI Rate selection
+// 000 1.5ms
+// 001 16ms
+// 010 32ms
+// 011 64ms
+// 100 8s
+// 101 16s
+// 110 32s
+// 111 64s
+
+typedef enum {
+ INDEX_TIME_1_5ms = 0,
+ INDEX_TIME_16ms,
+ INDEX_TIME_32ms,
+ INDEX_TIME_64ms,
+ INDEX_TIME_8s,
+ INDEX_TIME_16s,
+ INDEX_TIME_32s,
+ INDEX_TIME_64s,
+ INDEX_TIME_MAX
+} TIMER_INTERVAL_INDEX;
+
+STATIC TIMER_INTERVAL mSmmPeriodicTimerIntervals[INDEX_TIME_MAX] = {
+ {TIME_1_5ms, PERIODIC_TIMER},
+ {TIME_16ms, PERIODIC_TIMER},
+ {TIME_32ms, PERIODIC_TIMER},
+ {TIME_64ms, PERIODIC_TIMER},
+ { TIME_8s, PERIODIC_TIMER },
+ {TIME_16s, PERIODIC_TIMER},
+ {TIME_32s, PERIODIC_TIMER},
+ {TIME_64s, PERIODIC_TIMER}
+};
+
+typedef struct _TIMER_INFO {
+ UINTN NumChildren; // number of children using this timer
+ UINT64 MinReqInterval; // minimum interval required by children
+ UINTN CurrentSetting; // interval this timer is set at right now (index into interval table)
+} TIMER_INFO;
+
+TIMER_INFO mTimers[NUM_TIMERS];
+
+QNC_SMM_SOURCE_DESC mTIMER_SOURCE_DESCS[NUM_TIMERS] = {
+ {
+ QNC_SMM_NO_FLAGS,
+ {
+ {{GPE_ADDR_TYPE, R_QNC_GPE0BLK_SMIE}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SWT},
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {{GPE_ADDR_TYPE, R_QNC_GPE0BLK_SMIS}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SWT}
+ }
+ }
+};
+
+VOID
+QNCSmmPeriodicTimerProgramTimers(
+ VOID
+ );
+
+
+TIMER_INTERVAL *
+ContextToTimerInterval (
+ IN QNC_SMM_CONTEXT *RegisterContext
+ )
+{
+ UINTN loopvar;
+
+ //
+ // Determine which timer this child is using
+ //
+ for (loopvar = 0; loopvar < INDEX_TIME_MAX; loopvar++) {
+ if (((RegisterContext->PeriodicTimer.SmiTickInterval == 0) && (RegisterContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||
+ (RegisterContext->PeriodicTimer.SmiTickInterval == mSmmPeriodicTimerIntervals[loopvar].Interval)
+ ) {
+ return &mSmmPeriodicTimerIntervals[loopvar];
+ }
+ }
+
+ //
+ // If this assertion fires, then either:
+ // (1) the context contains an invalid interval
+ // (2) the timer interval table is corrupt
+ //
+ // ASSERT (FALSE);
+
+ return NULL;
+}
+
+EFI_STATUS
+MapPeriodicTimerToSrcDesc (
+ IN QNC_SMM_CONTEXT *RegisterContext,
+ OUT QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ //
+ // Figure out which timer the child is requesting and
+ // send back the source description
+ //
+ TimerInterval = ContextToTimerInterval (RegisterContext);
+ if (TimerInterval == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ CopyMem (SrcDesc, &mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer], sizeof (QNC_SMM_SOURCE_DESC));;
+
+ //
+ // Program the value of the interval into hardware
+ //
+ QNCSmmPeriodicTimerProgramTimers ();
+
+ return EFI_SUCCESS;
+}
+
+VOID
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT QNC_SMM_CONTEXT *HwContext
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+ TimerInterval = ContextToTimerInterval (&Record->ChildContext);
+
+ if (TimerInterval != NULL) {
+ //
+ // Ignore the hardware context. It's not required for this protocol.
+ // Instead, just increment the child's context.
+ // Update the elapsed time w/ the data from our tables
+ //
+ Record->CommBuffer.PeriodicTimer.ElapsedTime += TimerInterval->Interval;
+ *HwContext = Record->ChildContext;
+ }
+}
+
+BOOLEAN
+PeriodicTimerCmpContext (
+ IN QNC_SMM_CONTEXT *HwContext,
+ IN QNC_SMM_CONTEXT *ChildContext
+ )
+{
+ DATABASE_RECORD *Record;
+
+ Record = DATABASE_RECORD_FROM_CONTEXT (ChildContext);
+
+ if (Record->CommBuffer.PeriodicTimer.ElapsedTime >= ChildContext->PeriodicTimer.Period) {
+ //
+ // This child should be dispatched
+ // The timer will be restarted on the "ClearSource" call.
+ //
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+VOID
+PeriodicTimerGetBuffer (
+ IN DATABASE_RECORD * Record
+ )
+{
+ //
+ // CommBuffer has been updated by PeriodicTimerGetContext, so return directly
+ //
+ return;
+}
+
+VOID
+QNCSmmPeriodicTimerProgramTimers (
+ VOID
+ )
+{
+ UINT32 GpePmcwValue;
+ SUPPORTED_TIMER Timer;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ TIMER_INTERVAL *TimerInterval;
+
+ //
+ // Find the minimum required interval for each timer
+ //
+ for (Timer = (SUPPORTED_TIMER)0; Timer < NUM_TIMERS; Timer++) {
+ mTimers[Timer].MinReqInterval = ~(UINT64)0x0;
+ mTimers[Timer].NumChildren = 0;
+ }
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ //
+ // This child is registerd with the PeriodicTimer protocol
+ //
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+
+ if(TimerInterval != NULL) {
+ Timer = (SUPPORTED_TIMER)((TIMER_INTERVAL *) (TimerInterval))->AssociatedTimer;
+
+ ASSERT (Timer >= 0 && Timer < NUM_TIMERS);
+
+ if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {
+ mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;
+ }
+ mTimers[Timer].NumChildren++;
+ }
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+
+ //
+ // Program the hardware
+ //
+ GpePmcwValue = 0;
+ if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
+ switch (mTimers[PERIODIC_TIMER].MinReqInterval) {
+
+ case TIME_64s:
+ GpePmcwValue = INDEX_TIME_64s;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
+ break;
+
+ case TIME_32s:
+ GpePmcwValue = INDEX_TIME_32s;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
+ break;
+
+ case TIME_16s:
+ GpePmcwValue = INDEX_TIME_16s;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
+ break;
+
+ case TIME_8s:
+ GpePmcwValue = INDEX_TIME_8s;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
+ break;
+
+ case TIME_64ms:
+ GpePmcwValue = INDEX_TIME_64ms;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64ms;
+ break;
+
+ case TIME_32ms:
+ GpePmcwValue = INDEX_TIME_32ms;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32ms;
+ break;
+
+ case TIME_16ms:
+ GpePmcwValue = INDEX_TIME_16ms;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16ms;
+ break;
+
+ case TIME_1_5ms:
+ GpePmcwValue = INDEX_TIME_1_5ms;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ };
+
+ GpePmcwValue |= B_QNC_GPE0BLK_PMCW_PSE;
+
+ IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_PMCW), GpePmcwValue);
+
+ //
+ // Restart the timer here, just need to clear the SMI
+ //
+ QNCSmmClearSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
+ } else {
+ QNCSmmDisableSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
+ }
+}
+
+EFI_STATUS
+QNCSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ )
+/*++
+
+Routine Description:
+
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+Arguments:
+
+ This - Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+ SmiTickInterval - Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+Returns:
+
+ EFI_SUCCESS - The service returned successfully.
+ EFI_INVALID_PARAMETER - The parameter SmiTickInterval is invalid.
+
+--*/
+{
+ TIMER_INTERVAL *IntervalPointer;
+
+ ASSERT (SmiTickInterval != NULL);
+
+ IntervalPointer = (TIMER_INTERVAL*)*SmiTickInterval;
+
+ if (IntervalPointer == NULL) {
+ //
+ // The first time child requesting an interval
+ //
+ IntervalPointer = &mSmmPeriodicTimerIntervals[0];
+ } else if (IntervalPointer == &mSmmPeriodicTimerIntervals[INDEX_TIME_MAX - 1]) {
+ //
+ // At end of the list
+ //
+ IntervalPointer = NULL;
+ } else {
+ if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&
+ (IntervalPointer < &mSmmPeriodicTimerIntervals[INDEX_TIME_MAX - 1])) {
+ //
+ // Get the next interval in the list
+ //
+ IntervalPointer++;
+ } else {
+ //
+ // Input is out of range
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (IntervalPointer != NULL) {
+ *SmiTickInterval = &IntervalPointer->Interval;
+ } else {
+ *SmiTickInterval = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+QNCSmmPeriodicTimerClearSource (
+ IN QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+Arguments:
+
+ SrcDesc - Pointer to the QNC_SMM_SOURCE_DESC instance.
+
+Returns:
+
+ None.
+
+--*/
+{
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ QNCSmmPeriodicTimerProgramTimers ();
+
+ //
+ // Reset Elapsed time
+ //
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ //
+ // This child is registerd with the PeriodicTimer protocol and Callback
+ // has been invoked, so reset the ElapsedTime to 0
+ //
+ if (RecordInDb->CommBuffer.PeriodicTimer.ElapsedTime >= RecordInDb->ChildContext.PeriodicTimer.Period) {
+ RecordInDb->CommBuffer.PeriodicTimer.ElapsedTime = 0;
+ }
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmQncn.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmQncn.c
new file mode 100644
index 0000000..715d64e
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmQncn.c
@@ -0,0 +1,238 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCSmmQncn.c
+
+Abstract:
+
+ File to contain all the hardware specific stuff for the Smm QNCn dispatch protocol.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmmHelpers.h"
+
+QNC_SMM_SOURCE_DESC QNCN_SOURCE_DESCS[NUM_ICHN_TYPES] = {
+
+ // QNCnMch (0)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnPme (1)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnRtcAlarm (2)
+ {
+ QNC_SMM_NO_FLAGS,
+ {
+ {{ACPI_ADDR_TYPE, R_QNC_PM1BLK_PM1E}, S_QNC_PM1BLK_PM1E, N_QNC_PM1BLK_PM1E_RTC},
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {{ACPI_ADDR_TYPE, R_QNC_PM1BLK_PM1S}, S_QNC_PM1BLK_PM1S, N_QNC_PM1BLK_PM1S_RTC}
+ }
+ },
+
+ // QNCnRingIndicate (3)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnAc97Wake (4)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnSerialIrq (5)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnY2KRollover (6)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnTcoTimeout (7)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnOsTco (8)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnNmi (9)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnIntruderDetect (10)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnBiosWp (11)
+ {
+ QNC_SMM_CLEAR_WITH_ZERO,
+ {
+ {
+ {
+ PCI_ADDR_TYPE,
+ (
+ (PCI_BUS_NUMBER_QNC << 24) |
+ (PCI_DEVICE_NUMBER_QNC_LPC << 16) |
+ (PCI_FUNCTION_NUMBER_QNC_LPC << 8) |
+ R_QNC_LPC_BIOS_CNTL
+ )
+ },
+ S_QNC_LPC_BIOS_CNTL,
+ N_QNC_LPC_BIOS_CNTL_BLE
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCI_ADDR_TYPE,
+ (
+ (PCI_BUS_NUMBER_QNC << 24) |
+ (PCI_DEVICE_NUMBER_QNC_LPC << 16) |
+ (PCI_FUNCTION_NUMBER_QNC_LPC << 8) |
+ R_QNC_LPC_BIOS_CNTL
+ )
+ },
+ S_QNC_LPC_BIOS_CNTL,
+ N_QNC_LPC_BIOS_CNTL_BIOSWE
+ }
+ }
+ },
+
+ // QNCnMcSmi (12)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnPmeB0 (13)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnThrmSts (14)
+ {
+ QNC_SMM_SCI_EN_DEPENDENT,
+ {
+ {{GPE_ADDR_TYPE, R_QNC_GPE0BLK_GPE0E}, S_QNC_GPE0BLK_GPE0E, N_QNC_GPE0BLK_GPE0E_THRM},
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {{GPE_ADDR_TYPE, R_QNC_GPE0BLK_GPE0S}, S_QNC_GPE0BLK_GPE0S, N_QNC_GPE0BLK_GPE0S_THRM}
+ }
+ },
+
+ // QNCnSmBus (15)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnIntelUsb2 (16)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnMonSmi7 (17)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnMonSmi6 (18)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnMonSmi5 (19)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnMonSmi4 (20)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap13 (21)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap12 (22)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap11 (23)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap10 (24)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap9 (25)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap8 (26)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap7 (27)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap6 (28)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap5 (29)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap3 (30)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap2 (31)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap1 (32)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnDevTrap0 (33)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnIoTrap3 (34)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnIoTrap2 (35)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnIoTrap1 (36)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnIoTrap0 (37)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnPciExpress (38)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnMonitor (39)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnSpi (40)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnQRT (41)
+ NULL_SOURCE_DESC_INITIALIZER,
+
+ // QNCnGpioUnlock (42)
+ NULL_SOURCE_DESC_INITIALIZER
+};
+
+VOID
+QNCSmmQNCnClearSource(
+ QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ QNCSmmClearSource (SrcDesc);
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSw.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSw.c
new file mode 100644
index 0000000..06c8427
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSw.c
@@ -0,0 +1,121 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCSmmSw.c
+
+Abstract:
+
+ File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmmHelpers.h"
+
+EFI_SMM_CPU_PROTOCOL *mSmmCpu = NULL;
+
+CONST QNC_SMM_SOURCE_DESC SW_SOURCE_DESC = {
+ QNC_SMM_NO_FLAGS,
+ {
+ {
+ {GPE_ADDR_TYPE, R_QNC_GPE0BLK_SMIE}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_APM
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {GPE_ADDR_TYPE, R_QNC_GPE0BLK_SMIS}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_APM
+ }
+ }
+};
+
+VOID
+SwGetContext(
+ IN DATABASE_RECORD *Record,
+ OUT QNC_SMM_CONTEXT *Context
+ )
+{
+ Context->Sw.SwSmiInputValue = IoRead8 (R_APM_CNT);
+}
+
+BOOLEAN
+SwCmpContext (
+ IN QNC_SMM_CONTEXT *Context1,
+ IN QNC_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN)( Context1->Sw.SwSmiInputValue == Context2->Sw.SwSmiInputValue );
+}
+
+VOID
+SwGetBuffer (
+ IN DATABASE_RECORD * Record
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN CpuIndex;
+ EFI_SMM_SAVE_STATE_IO_INFO IoState;
+
+ //
+ // Locate SMM CPU protocol to retrive the CPU save state
+ //
+ if (mSmmCpu == NULL) {
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Find the CPU which generated the software SMI
+ //
+ CpuIndex = 0;
+ for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
+ Status = mSmmCpu->ReadSaveState (
+ mSmmCpu,
+ sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
+ EFI_SMM_SAVE_STATE_REGISTER_IO,
+ Index,
+ &IoState
+ );
+ if (!EFI_ERROR (Status) && (IoState.IoPort == R_APM_CNT)) {
+ CpuIndex = Index;
+ break;
+ }
+ }
+
+ Record->CommBuffer.Sw.SwSmiCpuIndex = CpuIndex;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c
new file mode 100644
index 0000000..4f8821d
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c
@@ -0,0 +1,178 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCSmmSx.c
+
+Abstract:
+
+ File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmmHelpers.h"
+
+CONST QNC_SMM_SOURCE_DESC SX_SOURCE_DESC = {
+ QNC_SMM_NO_FLAGS,
+ {
+ {
+ {GPE_ADDR_TYPE, R_QNC_GPE0BLK_SMIE}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SLP
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {GPE_ADDR_TYPE, R_QNC_GPE0BLK_SMIS}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SLP
+ }
+ }
+};
+
+VOID
+SxGetContext(
+ IN DATABASE_RECORD *Record,
+ OUT QNC_SMM_CONTEXT *Context
+ )
+{
+ UINT32 Pm1Cnt;
+
+ Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
+
+ //
+ // By design, the context phase will always be ENTRY
+ //
+ Context->Sx.Phase = SxEntry;
+
+ //
+ // Map the PM1_CNT register's SLP_TYP bits to the context type
+ //
+ switch (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) {
+
+ case V_S0:
+ Context->Sx.Type = SxS0;
+ break;
+
+ case V_S3:
+ Context->Sx.Type = SxS3;
+ break;
+
+ case V_S4:
+ Context->Sx.Type = SxS4;
+ break;
+
+ case V_S5:
+ Context->Sx.Type = SxS5;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ };
+}
+
+BOOLEAN
+SxCmpContext (
+ IN QNC_SMM_CONTEXT *Context1,
+ IN QNC_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN)(Context1->Sx.Type == Context2->Sx.Type);
+}
+
+VOID
+QNCSmmSxGoToSleep(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+
+Returns:
+
+ None.
+
+--*/
+{
+ UINT32 Pm1Cnt;
+
+ //
+ // Flush cache into memory before we go to sleep. It is necessary for S3 sleep
+ // because we may update memory in SMM Sx sleep handlers -- the updates are in cache now
+ //
+ AsmWbinvd();
+
+ //
+ // Disable SMIs
+ //
+ QNCSmmClearSource (&SX_SOURCE_DESC );
+ QNCSmmDisableSource (&SX_SOURCE_DESC);
+
+ //
+ // Clear Sleep Type Enable
+ //
+ IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIE, (UINT16)(~B_QNC_GPE0BLK_SMIE_SLP));
+
+ // clear sleep SMI status
+ IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, (UINT16)(S_QNC_GPE0BLK_SMIS));
+
+ //
+ // Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep
+ //
+ Pm1Cnt = IoOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, B_QNC_PM1BLK_PM1C_SLPEN);
+
+ //
+ // The system just went to sleep. If the sleep state was S1, then code execution will resume
+ // here when the system wakes up.
+ //
+ Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
+ if ((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == 0) {
+ //
+ // An ACPI OS isn't present, clear the sleep information
+ //
+ Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SLPTP;
+ Pm1Cnt |= V_S0;
+
+ IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Pm1Cnt);
+ }
+
+ QNCSmmClearSource (&SX_SOURCE_DESC);
+ QNCSmmEnableSource (&SX_SOURCE_DESC);
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmm.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmm.h
new file mode 100644
index 0000000..e5228dd
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmm.h
@@ -0,0 +1,896 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ QNCSmm.h
+
+Abstract:
+
+ Prototypes and defines for the QNC SMM Dispatcher.
+
+--*/
+
+#ifndef QNC_SMM_H
+#define QNC_SMM_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmmRegisters.h"
+
+extern EFI_HANDLE mQNCSmmDispatcherImageHandle;
+
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// SUPPORTED PROTOCOLS
+//
+
+//
+// Define an enumeration for all the supported protocols
+//
+typedef enum {
+ // UsbType, DELETE:on QuarkNcSocId, there is no usb smi supported
+ SxType,
+ SwType,
+ GpiType,
+ QNCnType,
+ PowerButtonType,
+ PeriodicTimerType,
+ NUM_PROTOCOLS
+} QNC_SMM_PROTOCOL_TYPE;
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// SPECIFYING A REGISTER
+// We want a general way of referring to addresses. For this case, we'll only
+// need addresses in the ACPI table (and the TCO entries within the ACPI table).
+// However, it's interesting to consider what it would take to support other types
+// of addresses. To address Will's concern, I think it prudent to accommodate it
+// early on in the design.
+//
+// Addresses we need to consider:
+//
+// Type: Required:
+// I/O Yes
+// ACPI (special case of I/O) Only if we want to
+// TCO (special case of ACPI) Only if we want to
+// Memory (or Memory Mapped I/O) Only if we want to
+// PCI Yes, for BiosWp
+//
+typedef enum {
+ //
+ // IO_ADDR_TYPE, // unimplemented
+ //
+ ACPI_ADDR_TYPE,
+ GPE_ADDR_TYPE,
+ //
+ // MEMORY_ADDR_TYPE, // unimplemented
+ //
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCI_ADDR_TYPE,
+ NUM_ADDR_TYPES, // count of items in this enum
+ QNC_SMM_ADDR_TYPE_NULL = -1 // sentinel to indicate NULL or to signal end of arrays
+} ADDR_TYPE;
+
+//
+// Assumption: 32-bits -- enum's evaluate to integer
+// Assumption: This code will only run on IA-32. Justification: IA-64 doesn't have SMIs.
+// We don't have to worry about 64-bit addresses.
+// Typedef the size of addresses in case the numbers I'm using are wrong or in case
+// this changes. This is a good idea because PCI_ADDR will change, for example, when
+// we add support for PciExpress.
+//
+typedef UINT16 IO_ADDR;
+typedef IO_ADDR ACPI_ADDR; // can omit
+typedef IO_ADDR GPE_ADDR; // can omit
+typedef IO_ADDR TCO_ADDR; // can omit
+typedef VOID *MEM_ADDR;
+typedef MEM_ADDR MEMORY_MAPPED_IO_ADDRESS;
+typedef union {
+ UINT32 Raw;
+ struct {
+ UINT8 Reg;
+ UINT8 Fnc;
+ UINT8 Dev;
+ UINT8 Bus;
+ } Fields;
+} PCI_ADDR;
+
+typedef struct {
+ ADDR_TYPE Type;
+ union {
+ //
+ // used to initialize during declaration/definition
+ //
+ UINTN raw;
+
+ //
+ // used to access useful data
+ //
+ IO_ADDR io;
+ ACPI_ADDR acpi;
+ GPE_ADDR gpe;
+ TCO_ADDR tco;
+ MEM_ADDR mem;
+ MEMORY_MAPPED_IO_ADDRESS Mmio;
+ PCI_ADDR pci;
+
+ } Data;
+
+} QNC_SMM_ADDRESS;
+//
+// Assumption: total size is 64 bits (32 for type and 32 for data) or 8 bytes
+//
+#define EFI_PCI_ADDRESS_PORT 0xcf8
+#define EFI_PCI_DATA_PORT 0xcfc
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// SPECIFYING BITS WITHIN A REGISTER
+// Here's a struct that helps us specify a source or enable bit.
+//
+typedef struct {
+ QNC_SMM_ADDRESS Reg;
+ UINT8 SizeInBytes; // of the register
+ UINT8 Bit;
+} QNC_SMM_BIT_DESC;
+
+//
+// Sometimes, we'll have bit descriptions that are unused. It'd be great to have a
+// way to easily identify them:
+//
+#define IS_BIT_DESC_NULL(BitDesc) ((BitDesc).Reg.Type == QNC_SMM_ADDR_TYPE_NULL) // "returns" true when BitDesc is NULL
+#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = QNC_SMM_ADDR_TYPE_NULL) // will "return" an integer w/ value of 0
+#define NULL_BIT_DESC_INITIALIZER \
+ { \
+ { \
+ QNC_SMM_ADDR_TYPE_NULL, \
+ { \
+ 0 \
+ } \
+ }, \
+ 0, 0 \
+ }
+//
+// I'd like a type to specify the callback's Sts & En bits because they'll
+// be commonly used together:
+//
+#define NUM_EN_BITS 2
+#define NUM_STS_BITS 1
+
+//
+// Flags
+//
+typedef UINT8 QNC_SMM_SOURCE_FLAGS;
+
+//
+// Flags required today
+//
+#define QNC_SMM_NO_FLAGS 0
+#define QNC_SMM_SCI_EN_DEPENDENT (BIT0)
+#define QNC_SMM_CLEAR_WITH_ZERO (BIT6)
+
+//
+// Flags that might be required tomorrow
+// #define QNC_SMM_CLEAR_WITH_ONE 2 // may need to support bits that clear by writing 0
+// #define QNC_SMM_MULTIBIT_FIELD 3 // may need to support status/enable fields 2 bits wide
+//
+typedef struct {
+ QNC_SMM_SOURCE_FLAGS Flags;
+ QNC_SMM_BIT_DESC En[NUM_EN_BITS];
+ QNC_SMM_BIT_DESC Sts[NUM_STS_BITS];
+} QNC_SMM_SOURCE_DESC;
+//
+// 31 bytes, I think
+//
+#define NULL_SOURCE_DESC_INITIALIZER \
+ { \
+ QNC_SMM_NO_FLAGS, \
+ { \
+ NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \
+ }, \
+ { \
+ NULL_BIT_DESC_INITIALIZER \
+ } \
+ }
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// CHILD CONTEXTS
+// To keep consistent w/ the architecture, we'll need to provide the context
+// to the child when we call its callback function. After talking with Will,
+// we agreed that we'll need functions to "dig" the context out of the hardware
+// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those
+// contexts to prevent unnecessary dispatches. I'd like a general type for these
+// "GetContext" functions, so I'll need a union of all the protocol contexts for
+// our internal use:
+//
+typedef union {
+ //
+ // (in no particular order)
+ //
+ EFI_SMM_ICHN_REGISTER_CONTEXT QNCn;
+ EFI_SMM_SX_REGISTER_CONTEXT Sx;
+ EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT PeriodicTimer;
+ EFI_SMM_SW_REGISTER_CONTEXT Sw;
+ EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT PowerButton;
+ // EFI_SMM_USB_REGISTER_CONTEXT Usb; DELETE:on QuarkNcSocId, there is no usb smi supported
+ EFI_SMM_GPI_REGISTER_CONTEXT Gpi;
+} QNC_SMM_CONTEXT;
+
+typedef union {
+ //
+ // (in no particular order)
+ //
+ EFI_SMM_SW_CONTEXT Sw;
+ EFI_SMM_PERIODIC_TIMER_CONTEXT PeriodicTimer;
+} QNC_SMM_BUFFER;
+
+//
+// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes
+//
+typedef struct _DATABASE_RECORD DATABASE_RECORD;
+
+typedef
+VOID
+(EFIAPI *GET_CONTEXT) (
+ IN DATABASE_RECORD * Record,
+ OUT QNC_SMM_CONTEXT * Context
+ );
+//
+// Assumption: the GET_CONTEXT function will be as small and simple as possible.
+// Assumption: We don't need to pass in an enumeration for the protocol because each
+// GET_CONTEXT function is written for only one protocol.
+// We also need a function to compare contexts to see if the child should be dispatched
+//
+typedef
+BOOLEAN
+(EFIAPI *CMP_CONTEXT) (
+ IN QNC_SMM_CONTEXT * Context1,
+ IN QNC_SMM_CONTEXT * Context2
+ );
+
+/*
+ Returns: True when contexts are equivalent; False otherwise
+*/
+
+//
+// This function is used to get the content of CommBuffer that will be passed
+// to Callback function
+//
+typedef
+VOID
+(EFIAPI *GET_BUFFER) (
+ IN DATABASE_RECORD * Record
+ );
+
+//
+// Finally, every protocol will require a "Get Context", "Compare Context"
+// and "Get CommBuffer" call, so we may as well wrap that up in a table, too.
+//
+typedef struct {
+ GET_CONTEXT GetContext;
+ CMP_CONTEXT CmpContext;
+ GET_BUFFER GetBuffer;
+} CONTEXT_FUNCTIONS;
+
+extern CONTEXT_FUNCTIONS ContextFunctions[NUM_PROTOCOLS];
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// MAPPING CONTEXT TO BIT DESCRIPTIONS
+// I'd like to have a general approach to mapping contexts to bit descriptions.
+// Sometimes, we'll find that we can use table lookups or CONSTant assignments;
+// other times, we'll find that we'll need to use a function to perform the mapping.
+// If we define a macro to mask that process, we'll never have to change the code.
+// I don't know if this is desirable or not -- if it isn't, then we can get rid
+// of the macros and just use function calls or variable assignments. Doesn't matter
+// to me.
+// Mapping complex contexts requires a function
+//
+// DELETE:on QuarkNcSocId, there is no usb smi supported
+//EFI_STATUS
+//EFIAPI
+//MapUsbToSrcDesc (
+// IN QNC_SMM_CONTEXT *RegisterContext,
+// OUT QNC_SMM_SOURCE_DESC *SrcDesc
+// )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ RegisterContext - GC_TODO: add argument description
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+MapPeriodicTimerToSrcDesc (
+ IN QNC_SMM_CONTEXT *RegisterContext,
+ OUT QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ RegisterContext - GC_TODO: add argument description
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// Mapping simple contexts can be done by assignment or lookup table
+//
+extern CONST QNC_SMM_SOURCE_DESC SW_SOURCE_DESC;
+extern CONST QNC_SMM_SOURCE_DESC SX_SOURCE_DESC;
+
+//
+// With the changes we've made to the protocols, we can now use table
+// lookups for the following protocols:
+//
+extern CONST QNC_SMM_SOURCE_DESC GPI_SOURCE_DESC;
+
+extern QNC_SMM_SOURCE_DESC QNCN_SOURCE_DESCS[NUM_ICHN_TYPES];
+
+
+//
+// For QNCx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.
+//
+#define MAXIMUM_SWI_VALUE 0xFF
+
+
+//
+// Open: Need to make sure this kind of type cast will actually work.
+// May need an intermediate form w/ two VOID* arguments. I'll figure
+// that out when I start compiling.
+
+///////////////////////////////////////////////////////////////////////////////
+//
+typedef
+VOID
+(EFIAPI *QNC_SMM_CLEAR_SOURCE) (
+ QNC_SMM_SOURCE_DESC * SrcDesc
+ );
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// "DATABASE" RECORD
+// Linked list data structures
+//
+#define DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('D', 'B', 'R', 'C')
+
+struct _DATABASE_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ //
+ // Status and Enable bit description
+ //
+ QNC_SMM_SOURCE_DESC SrcDesc;
+
+ //
+ // Callback function
+ //
+ EFI_SMM_HANDLER_ENTRY_POINT2 Callback;
+ QNC_SMM_CONTEXT ChildContext;
+ QNC_SMM_BUFFER CommBuffer;
+ UINTN BufferSize;
+
+ //
+ // Special handling hooks -- init them to NULL if unused/unneeded
+ //
+ QNC_SMM_CLEAR_SOURCE ClearSource; // needed for SWSMI timer
+ // Functions required to make callback code general
+ //
+ CONTEXT_FUNCTIONS ContextFunctions;
+
+ //
+ // The protocol that this record dispatches
+ //
+ QNC_SMM_PROTOCOL_TYPE ProtocolType;
+
+};
+
+#define DATABASE_RECORD_FROM_LINK(_record) CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)
+#define DATABASE_RECORD_FROM_CONTEXT(_record) CR (_record, DATABASE_RECORD, ChildContext, DATABASE_RECORD_SIGNATURE)
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// HOOKING INTO THE ARCHITECTURE
+//
+typedef
+EFI_STATUS
+(EFIAPI *QNC_SMM_GENERIC_REGISTER) (
+ IN VOID **This,
+ IN VOID *DispatchFunction,
+ IN VOID *RegisterContext,
+ OUT EFI_HANDLE * DispatchHandle
+ );
+typedef
+EFI_STATUS
+(EFIAPI *QNC_SMM_GENERIC_UNREGISTER) (
+ IN VOID **This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+//
+// Define a memory "stamp" equivalent in size and function to most of the protocols
+//
+typedef struct {
+ QNC_SMM_GENERIC_REGISTER Register;
+ QNC_SMM_GENERIC_UNREGISTER Unregister;
+ UINTN Extra1;
+ UINTN Extra2; // may not need this one
+} QNC_SMM_GENERIC_PROTOCOL;
+
+EFI_STATUS
+QNCSmmCoreRegister (
+ IN QNC_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN QNC_SMM_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ DispatchFunction - GC_TODO: add argument description
+ RegisterContext - GC_TODO: add argument description
+ DispatchHandle - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+EFI_STATUS
+QNCSmmCoreUnRegister (
+ IN QNC_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ DispatchHandle - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+typedef union {
+ QNC_SMM_GENERIC_PROTOCOL Generic;
+
+ // EFI_SMM_USB_DISPATCH2_PROTOCOL Usb; DELETE:on QuarkNcSocId, there is no usb smi supported
+ EFI_SMM_SX_DISPATCH2_PROTOCOL Sx;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL Sw;
+ EFI_SMM_GPI_DISPATCH2_PROTOCOL Gpi;
+ EFI_SMM_ICHN_DISPATCH2_PROTOCOL QNCn;
+ EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL PowerButton;
+ EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL PeriodicTimer;
+} QNC_SMM_PROTOCOL;
+
+//
+// Define a structure to help us identify the generic protocol
+//
+#define PROTOCOL_SIGNATURE SIGNATURE_32 ('P', 'R', 'O', 'T')
+
+typedef struct {
+ UINTN Signature;
+
+ QNC_SMM_PROTOCOL_TYPE Type;
+ EFI_GUID *Guid;
+ QNC_SMM_PROTOCOL Protocols;
+} QNC_SMM_QUALIFIED_PROTOCOL;
+
+#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \
+ CR (_generic, \
+ QNC_SMM_QUALIFIED_PROTOCOL, \
+ Protocols, \
+ PROTOCOL_SIGNATURE \
+ )
+
+//
+// Create private data for the protocols that we'll publish
+//
+typedef struct {
+ LIST_ENTRY CallbackDataBase;
+ EFI_HANDLE SmiHandle;
+ EFI_HANDLE InstallMultProtHandle;
+ QNC_SMM_QUALIFIED_PROTOCOL Protocols[NUM_PROTOCOLS];
+} PRIVATE_DATA;
+
+extern PRIVATE_DATA mPrivateData;
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+//
+VOID
+EFIAPI
+SwGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT QNC_SMM_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Record - GC_TODO: add argument description
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+EFIAPI
+SwCmpContext (
+ IN QNC_SMM_CONTEXT *Context1,
+ IN QNC_SMM_CONTEXT *Context2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context1 - GC_TODO: add argument description
+ Context2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+SwGetBuffer (
+ IN DATABASE_RECORD * Record
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Record - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT QNC_SMM_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Record - GC_TODO: add argument description
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN QNC_SMM_CONTEXT *Context1,
+ IN QNC_SMM_CONTEXT *Context2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context1 - GC_TODO: add argument description
+ Context2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT QNC_SMM_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Record - GC_TODO: add argument description
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN QNC_SMM_CONTEXT *Context1,
+ IN QNC_SMM_CONTEXT *Context2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context1 - GC_TODO: add argument description
+ Context2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+PeriodicTimerGetBuffer (
+ IN DATABASE_RECORD * Record
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Record - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT QNC_SMM_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Record - GC_TODO: add argument description
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN QNC_SMM_CONTEXT *Context1,
+ IN QNC_SMM_CONTEXT *Context2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context1 - GC_TODO: add argument description
+ Context2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+//
+VOID
+EFIAPI
+QNCSmmPeriodicTimerClearSource (
+ QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+QNCSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ SmiTickInterval - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+QNCSmmSxGoToSleep (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+EFIAPI
+QNCSmmQNCnClearSource (
+ QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmCore.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmCore.c
new file mode 100644
index 0000000..41794b6
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmCore.c
@@ -0,0 +1,806 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCSmmCore.c
+
+Abstract:
+
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the QNC SMI sources.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmm.h"
+#include "QNCSmmHelpers.h"
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// MODULE / GLOBAL DATA
+//
+// Module variables used by the both the main dispatcher and the source dispatchers
+// Declared in QNCSmmSources.h
+//
+UINT32 mPciData;
+UINT32 mPciAddress;
+
+PRIVATE_DATA mPrivateData = { // for the structure
+ {
+ NULL
+ }, // CallbackDataBase linked list head
+ NULL, // Handler returned whan calling SmiHandlerRegister
+ NULL, // EFI handle returned when calling InstallMultipleProtocolInterfaces
+ { // protocol arrays
+ // elements within the array
+ //
+ {
+ PROTOCOL_SIGNATURE,
+ SxType,
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ {
+ (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,
+ (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SwType,
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ {
+ (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,
+ (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister,
+ (UINTN) MAXIMUM_SWI_VALUE
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ GpiType,
+ &gEfiSmmGpiDispatch2ProtocolGuid,
+ {
+ (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,
+ (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister,
+ (UINTN) 1
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ QNCnType,
+ &gEfiSmmIchnDispatch2ProtocolGuid,
+ {
+ (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,
+ (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PowerButtonType,
+ &gEfiSmmPowerButtonDispatch2ProtocolGuid,
+ {
+ (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,
+ (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister
+ }
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PeriodicTimerType,
+ &gEfiSmmPeriodicTimerDispatch2ProtocolGuid,
+ {
+ (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,
+ (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister,
+ (UINTN) QNCSmmPeriodicTimerDispatchGetNextShorterInterval
+ }
+ },
+ }
+};
+
+CONTEXT_FUNCTIONS mContextFunctions[NUM_PROTOCOLS] = {
+ {
+ SxGetContext,
+ SxCmpContext,
+ NULL
+ },
+ {
+ SwGetContext,
+ SwCmpContext,
+ SwGetBuffer
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ PeriodicTimerGetContext,
+ PeriodicTimerCmpContext,
+ PeriodicTimerGetBuffer,
+ },
+};
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// PROTOTYPES
+//
+// Functions use only in this file
+//
+EFI_STATUS
+QNCSmmCoreDispatcher (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context, OPTIONAL
+ IN OUT VOID *CommBuffer, OPTIONAL
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ );
+
+
+UINTN
+DevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// FUNCTIONS
+//
+// Driver entry point
+//
+EFI_STATUS
+EFIAPI
+InitializeQNCSmmDispatcher (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initializes the QNC SMM Dispatcher
+
+Arguments:
+
+ ImageHandle - Pointer to the loaded image protocol for this driver
+ SystemTable - Pointer to the EFI System Table
+
+Returns:
+ Status - EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ QNCSmmPublishDispatchProtocols ();
+
+ //
+ // Register a callback function to handle subsequent SMIs. This callback
+ // will be called by SmmCoreDispatcher.
+ //
+ Status = gSmst->SmiHandlerRegister (QNCSmmCoreDispatcher, NULL, &mPrivateData.SmiHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Callback DataBase
+ //
+ InitializeListHead (&mPrivateData.CallbackDataBase);
+
+ //
+ // Enable SMIs on the QNC now that we have a callback
+ //
+ QNCSmmInitHardware ();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SaveState (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Save Index registers to avoid corrupting the foreground environment
+
+Arguments:
+ None
+
+Returns:
+ Status - EFI_SUCCESS
+
+--*/
+{
+ mPciAddress = IoRead32 (EFI_PCI_ADDRESS_PORT);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RestoreState (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Restore Index registers to avoid corrupting the foreground environment
+
+Arguments:
+ None
+
+Returns:
+ Status - EFI_SUCCESS
+
+--*/
+{
+ IoWrite32 (EFI_PCI_ADDRESS_PORT, mPciAddress);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SmiInputValueDuplicateCheck (
+ UINTN FedSwSmiInputValue
+ )
+/*++
+
+Routine Description:
+
+ Check the Fed SwSmiInputValue to see if there is a duplicated one in the database
+
+Arguments:
+ None
+
+Returns:
+ Status - EFI_SUCCESS, EFI_INVALID_PARAMETER
+
+--*/
+// GC_TODO: FedSwSmiInputValue - add argument and description to function comment
+{
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ if (RecordInDb->ProtocolType == SwType) {
+ if (RecordInDb->ChildContext.Sw.SwSmiInputValue == FedSwSmiInputValue) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+QNCSmmCoreRegister (
+ IN QNC_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN QNC_SMM_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: DispatchFunction - add argument and description to function comment
+// GC_TODO: RegisterContext - add argument and description to function comment
+// GC_TODO: DispatchHandle - add argument and description to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+ QNC_SMM_QUALIFIED_PROTOCOL *Qualified;
+ INTN Index;
+
+ //
+ // Check for invalid parameter
+ //
+ if (This == NULL || RegisterContext == NULL || DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Create database record and add to database
+ //
+ Record = (DATABASE_RECORD *) AllocateZeroPool (sizeof (DATABASE_RECORD));
+ if (Record == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Gather information about the registration request
+ //
+ Record->Callback = DispatchFunction;
+ Record->ChildContext = *RegisterContext;
+
+ Qualified = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+
+ Record->ProtocolType = Qualified->Type;
+
+ CopyMem (&Record->ContextFunctions, &mContextFunctions[Qualified->Type], sizeof (Record->ContextFunctions));
+ //
+ // Perform linked list housekeeping
+ //
+ Record->Signature = DATABASE_RECORD_SIGNATURE;
+
+ switch (Qualified->Type) {
+ //
+ // By the end of this switch statement, we'll know the
+ // source description the child is registering for
+ //
+ case SxType:
+ //
+ // Check the validity of Context Type and Phase
+ //
+ if ((Record->ChildContext.Sx.Type < SxS0) ||
+ (Record->ChildContext.Sx.Type >= EfiMaximumSleepType) ||
+ (Record->ChildContext.Sx.Phase < SxEntry) ||
+ (Record->ChildContext.Sx.Phase >= EfiMaximumPhase)
+ ) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ CopyMem (&Record->SrcDesc, &SX_SOURCE_DESC, sizeof (Record->SrcDesc));
+ //
+ // use default clear source function
+ //
+ break;
+
+ case SwType:
+ if (RegisterContext->Sw.SwSmiInputValue == (UINTN)-1) {
+ //
+ // If SwSmiInputValue is set to (UINTN) -1 then a unique value will be assigned and returned in the structure.
+ //
+ Status = EFI_NOT_FOUND;
+ for (Index = 1; Index < MAXIMUM_SWI_VALUE; Index++) {
+ Status = SmiInputValueDuplicateCheck (Index);
+ if (!EFI_ERROR (Status)) {
+ RegisterContext->Sw.SwSmiInputValue = Index;
+ break;
+ }
+ }
+ if (RegisterContext->Sw.SwSmiInputValue == (UINTN)-1) {
+ Status = gSmst->SmmFreePool (Record);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Update ChildContext again as SwSmiInputValue has been changed
+ //
+ Record->ChildContext = *RegisterContext;
+ }
+
+ //
+ // Check the validity of Context Value
+ //
+ if (Record->ChildContext.Sw.SwSmiInputValue > MAXIMUM_SWI_VALUE) {
+ goto Error;
+ }
+
+ if (EFI_ERROR (SmiInputValueDuplicateCheck (Record->ChildContext.Sw.SwSmiInputValue))) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ CopyMem (&Record->SrcDesc, &SW_SOURCE_DESC, sizeof (Record->SrcDesc));
+ Record->BufferSize = sizeof (EFI_SMM_SW_REGISTER_CONTEXT);
+ //
+ // use default clear source function
+ //
+ break;
+
+ case GpiType:
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ CopyMem (&Record->SrcDesc, &GPI_SOURCE_DESC, sizeof (Record->SrcDesc));
+ //
+ // use default clear source function
+ //
+ break;
+
+ case QNCnType:
+ //
+ // Check the validity of Context Type
+ //
+ if ((Record->ChildContext.QNCn.Type < IchnMch) || (Record->ChildContext.QNCn.Type >= NUM_ICHN_TYPES)) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ CopyMem (&Record->SrcDesc, &QNCN_SOURCE_DESCS[Record->ChildContext.QNCn.Type], sizeof (Record->SrcDesc));
+ Record->ClearSource = QNCSmmQNCnClearSource;
+ break;
+
+ case PeriodicTimerType:
+
+ Status = MapPeriodicTimerToSrcDesc (RegisterContext, &(Record->SrcDesc));
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+ Record->BufferSize = sizeof (EFI_SMM_PERIODIC_TIMER_CONTEXT);
+ Record->ClearSource = QNCSmmPeriodicTimerClearSource;
+ break;
+
+ default:
+ goto Error;
+ break;
+ };
+
+ if (Record->ClearSource == NULL) {
+ //
+ // Clear the SMI associated w/ the source using the default function
+ //
+ QNCSmmClearSource (&Record->SrcDesc);
+ } else {
+ //
+ // This source requires special handling to clear
+ //
+ Record->ClearSource (&Record->SrcDesc);
+ }
+
+ QNCSmmEnableSource (&Record->SrcDesc);
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+
+Error:
+ FreePool (Record);
+ //
+ // DEBUG((EFI_D_ERROR,"Free pool status %d\n", Status ));
+ //
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+QNCSmmCoreUnRegister (
+ IN QNC_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: DispatchHandle - add argument and description to function comment
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ BOOLEAN SafeToDisable;
+ DATABASE_RECORD *RecordToDelete;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BASE_CR (DispatchHandle, DATABASE_RECORD, Link)->Signature != DATABASE_RECORD_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+ RemoveEntryList (&RecordToDelete->Link);
+ RecordToDelete->Signature = 0;
+
+ //
+ // See if we can disable the source, reserved for future use since this might
+ // not be the only criteria to disable
+ //
+ SafeToDisable = TRUE;
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while(!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (CompareEnables (&RecordToDelete->SrcDesc, &RecordInDb->SrcDesc)) {
+ SafeToDisable = FALSE;
+ break;
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+ if (SafeToDisable) {
+ QNCSmmDisableSource( &RecordToDelete->SrcDesc );
+}
+
+ FreePool (RecordToDelete);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is the main entry point for an SMM handler dispatch
+ or communicate-based callback.
+
+ @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param RegisterContext Points to an optional handler context which was specified when the handler was registered.
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @return Status Code
+
+**/
+EFI_STATUS
+QNCSmmCoreDispatcher (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *RegisterContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ //
+ // Used to prevent infinite loops
+ //
+ UINTN EscapeCount;
+
+ BOOLEAN ContextsMatch;
+ BOOLEAN ResetListSearch;
+ BOOLEAN EosSet;
+ BOOLEAN SxChildWasDispatched;
+ BOOLEAN ChildWasDispatched;
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ DATABASE_RECORD *RecordToExhaust;
+ LIST_ENTRY *LinkToExhaust;
+
+ QNC_SMM_CONTEXT Context;
+ VOID *CommunicationBuffer;
+ UINTN BufferSize;
+
+ EFI_STATUS Status;
+
+ QNC_SMM_SOURCE_DESC ActiveSource = NULL_SOURCE_DESC_INITIALIZER;
+
+ EscapeCount = 100;
+ ContextsMatch = FALSE;
+ ResetListSearch = FALSE;
+ EosSet = FALSE;
+ SxChildWasDispatched = FALSE;
+ Status = EFI_WARN_INTERRUPT_SOURCE_PENDING;
+ ChildWasDispatched = FALSE;
+
+ //
+ // Preserve Index registers
+ //
+ SaveState ();
+
+ if (!IsListEmpty (&mPrivateData.CallbackDataBase)) {
+ //
+ // We have children registered w/ us -- continue
+ //
+ while ((!EosSet) && (EscapeCount > 0)) {
+ EscapeCount--;
+
+ //
+ // Reset this flag in order to be able to process multiple SMI Sources in one loop.
+ //
+ ResetListSearch = FALSE;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+
+ while ((!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) && (ResetListSearch == FALSE)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ //
+ // look for the first active source
+ //
+ if (!SourceIsActive (&RecordInDb->SrcDesc)) {
+ //
+ // Didn't find the source yet, keep looking
+ //
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+
+ } else {
+ //
+ // We found a source. If this is a sleep type, we have to go to
+ // appropriate sleep state anyway.No matter there is sleep child or not
+ //
+ if (RecordInDb->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ //
+ // "cache" the source description and don't query I/O anymore
+ //
+ CopyMem (&ActiveSource, &RecordInDb->SrcDesc, sizeof (ActiveSource));
+ LinkToExhaust = LinkInDb;
+
+ //
+ // exhaust the rest of the queue looking for the same source
+ //
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {
+ RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);
+
+ if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {
+ //
+ // These source descriptions are equal, so this callback should be
+ // dispatched.
+ //
+ if (RecordToExhaust->ContextFunctions.GetContext != NULL) {
+ //
+ // This child requires that we get a calling context from
+ // hardware and compare that context to the one supplied
+ // by the child.
+ //
+ ASSERT (RecordToExhaust->ContextFunctions.CmpContext != NULL);
+
+ //
+ // Make sure contexts match before dispatching event to child
+ //
+ RecordToExhaust->ContextFunctions.GetContext (RecordToExhaust, &Context);
+ ContextsMatch = RecordToExhaust->ContextFunctions.CmpContext (&Context, &RecordToExhaust->ChildContext);
+
+ } else {
+ //
+ // This child doesn't require any more calling context beyond what
+ // it supplied in registration. Simply pass back what it gave us.
+ //
+ ASSERT (RecordToExhaust->Callback != NULL);
+ Context = RecordToExhaust->ChildContext;
+ ContextsMatch = TRUE;
+ }
+
+ if (ContextsMatch) {
+
+ if (RecordToExhaust->BufferSize != 0) {
+ ASSERT (RecordToExhaust->ContextFunctions.GetBuffer != NULL);
+
+ RecordToExhaust->ContextFunctions.GetBuffer (RecordToExhaust);
+
+ CommunicationBuffer = &RecordToExhaust->CommBuffer;
+ BufferSize = RecordToExhaust->BufferSize;
+ } else {
+ CommunicationBuffer = NULL;
+ BufferSize = 0;
+ }
+
+ ASSERT (RecordToExhaust->Callback != NULL);
+
+ RecordToExhaust->Callback (
+ (EFI_HANDLE) & RecordToExhaust->Link,
+ &Context,
+ CommunicationBuffer,
+ &BufferSize
+ );
+
+ ChildWasDispatched = TRUE;
+ if (RecordToExhaust->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ }
+ }
+ //
+ // Get next record in DB
+ //
+ LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);
+ }
+
+ if (RecordInDb->ClearSource == NULL) {
+ //
+ // Clear the SMI associated w/ the source using the default function
+ //
+ QNCSmmClearSource (&ActiveSource);
+ } else {
+ //
+ // This source requires special handling to clear
+ //
+ RecordInDb->ClearSource (&ActiveSource);
+ }
+
+ if (ChildWasDispatched) {
+ //
+ // The interrupt was handled and quiesced
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // The interrupt was not handled but quiesced
+ //
+ Status = EFI_WARN_INTERRUPT_SOURCE_QUIESCED;
+ }
+
+ //
+ // Queue is empty, reset the search
+ //
+ ResetListSearch = TRUE;
+
+ }
+ }
+ EosSet = QNCSmmSetAndCheckEos ();
+ }
+ }
+ //
+ // If you arrive here, there are two possible reasons:
+ // (1) you've got problems with clearing the SMI status bits in the
+ // ACPI table. If you don't properly clear the SMI bits, then you won't be able to set the
+ // EOS bit. If this happens too many times, the loop exits.
+ // (2) there was a SMM communicate for callback messages that was received prior
+ // to this driver.
+ // If there is an asynchronous SMI that occurs while processing the Callback, let
+ // all of the drivers (including this one) have an opportunity to scan for the SMI
+ // and handle it.
+ // If not, we don't want to exit and have the foreground app. clear EOS without letting
+ // these other sources get serviced.
+ //
+ ASSERT (EscapeCount > 0);
+
+ //
+ // Restore Index registers
+ //
+ RestoreState ();
+
+ if (SxChildWasDispatched) {
+ //
+ // A child of the SmmSxDispatch protocol was dispatched during this call;
+ // put the system to sleep.
+ //
+ QNCSmmSxGoToSleep ();
+ }
+
+ return Status;
+
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf
new file mode 100644
index 0000000..ff8aa34
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf
@@ -0,0 +1,108 @@
+## @file
+# Component description file for QuarkNcSocId SmmDispatcher module.
+#
+# This driver is responsible for the registration of child drivers
+# and the abstraction of the ICH SMI sources.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QNCSmmDispatcher
+ FILE_GUID = 2480271C-09C6-4f36-AD75-5E1390BD9929
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = InitializeQNCSmmDispatcher
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ QNC/QNCSmmPeriodicTimer.c
+ QNC/QNCSmmQncn.c
+ QNC/QNCSmmSx.c
+ QNC/QNCSmmSw.c
+ QNC/QNCSmmGpi.c
+ QNC/QNCSmmHelpers.c
+ QNCSmmHelpers.c
+ QNCSmmCore.c
+ QNCSmmHelpers.h
+ QNCxSmmHelpers.h
+ QNCSmmRegisters.h
+ QNCSmm.h
+ CommonHeader.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ SmmServicesTableLib
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ PciLib
+ PcdLib
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ IoLib
+ DevicePathLib
+ S3IoLib
+ QNCAccessLib
+
+[Protocols]
+ gEfiSmmCpuProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSmmPeriodicTimerDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmPowerButtonDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmIchnDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmGpiDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmSwDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmSxDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmUsbDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmIoTrapDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiSmmIchnDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+
+[Depex]
+ gEfiSmmCpuProtocolGuid AND gEfiPciRootBridgeIoProtocolGuid
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.c
new file mode 100644
index 0000000..cb88bf8
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.c
@@ -0,0 +1,397 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ QNCSmmHelpers.c
+
+Abstract:
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmm.h"
+#include "QNCSmmHelpers.h"
+
+//
+// #define BIT_ZERO 0x00000001
+//
+CONST UINT32 BIT_ZERO = 0x00000001;
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// SUPPORT / HELPER FUNCTIONS (QNC version-independent)
+//
+BOOLEAN
+CompareEnables (
+ CONST IN QNC_SMM_SOURCE_DESC *Src1,
+ CONST IN QNC_SMM_SOURCE_DESC *Src2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Src1 - GC_TODO: add argument description
+ Src2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ BOOLEAN IsEqual;
+ UINTN loopvar;
+
+ IsEqual = TRUE;
+ for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
+ //
+ // It's okay to compare a NULL bit description to a non-NULL bit description.
+ // They are unequal and these tests will generate the correct result.
+ //
+ if (Src1->En[loopvar].Bit != Src2->En[loopvar].Bit ||
+ Src1->En[loopvar].Reg.Type != Src2->En[loopvar].Reg.Type ||
+ Src1->En[loopvar].Reg.Data.raw != Src2->En[loopvar].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ //
+ // out of for loop
+ //
+ }
+ }
+
+ return IsEqual;
+}
+
+BOOLEAN
+CompareStatuses (
+ CONST IN QNC_SMM_SOURCE_DESC *Src1,
+ CONST IN QNC_SMM_SOURCE_DESC *Src2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Src1 - GC_TODO: add argument description
+ Src2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ BOOLEAN IsEqual;
+ UINTN loopvar;
+
+ IsEqual = TRUE;
+
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+ //
+ // It's okay to compare a NULL bit description to a non-NULL bit description.
+ // They are unequal and these tests will generate the correct result.
+ //
+ if (Src1->Sts[loopvar].Bit != Src2->Sts[loopvar].Bit ||
+ Src1->Sts[loopvar].Reg.Type != Src2->Sts[loopvar].Reg.Type ||
+ Src1->Sts[loopvar].Reg.Data.raw != Src2->Sts[loopvar].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ //
+ // out of for loop
+ //
+ }
+ }
+
+ return IsEqual;
+}
+
+BOOLEAN
+CompareSources (
+ CONST IN QNC_SMM_SOURCE_DESC *Src1,
+ CONST IN QNC_SMM_SOURCE_DESC *Src2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Src1 - GC_TODO: add argument description
+ Src2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));
+}
+
+BOOLEAN
+SourceIsActive (
+ CONST IN QNC_SMM_SOURCE_DESC *Src
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Src - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ BOOLEAN IsActive;
+ UINTN loopvar;
+
+ BOOLEAN SciEn;
+
+ IsActive = TRUE;
+
+ SciEn = QNCSmmGetSciEn ();
+
+ if ((Src->Flags & QNC_SMM_SCI_EN_DEPENDENT) && (SciEn)) {
+ //
+ // This source is dependent on SciEn, and SciEn == 1. An ACPI OS is present,
+ // so we shouldn't do anything w/ this source until SciEn == 0.
+ //
+ IsActive = FALSE;
+
+ } else {
+ //
+ // Read each bit desc from hardware and make sure it's a one
+ //
+ for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
+
+ if (!IS_BIT_DESC_NULL (Src->En[loopvar])) {
+
+ if (ReadBitDesc (&Src->En[loopvar]) == 0) {
+ IsActive = FALSE;
+ break;
+ //
+ // out of for loop
+ //
+ }
+
+ }
+ }
+
+ if (IsActive) {
+ //
+ // Read each bit desc from hardware and make sure it's a one
+ //
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+
+ if (!IS_BIT_DESC_NULL (Src->Sts[loopvar])) {
+
+ if (ReadBitDesc (&Src->Sts[loopvar]) == 0) {
+ IsActive = FALSE;
+ break;
+ //
+ // out of for loop
+ //
+ }
+
+ }
+ }
+ }
+ }
+
+ return IsActive;
+}
+
+VOID
+QNCSmmEnableSource (
+ CONST QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINTN loopvar;
+
+ //
+ // Set enables to 1 by writing a 1
+ //
+ for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) {
+ WriteBitDesc (&SrcDesc->En[loopvar], 1);
+ }
+ }
+
+ QNCSmmClearSource (SrcDesc);
+
+}
+
+VOID
+QNCSmmDisableSource (
+ CONST QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINTN loopvar;
+
+ for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) {
+ WriteBitDesc (&SrcDesc->En[loopvar], 0);
+ }
+ }
+}
+
+VOID
+QNCSmmClearSource (
+ CONST QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINTN loopvar;
+ BOOLEAN ValueToWrite;
+
+ ValueToWrite =
+ ((SrcDesc->Flags & QNC_SMM_CLEAR_WITH_ZERO) == 0) ? TRUE : FALSE;
+
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {
+ WriteBitDesc (&SrcDesc->Sts[loopvar], ValueToWrite);
+ }
+ }
+}
+
+VOID
+QNCSmmClearSourceAndBlock (
+ CONST QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+// GC_TODO: function comment should start with '/*++'
+/*
+ Sets the source to a 1 or 0 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+*/
+// GC_TODO: function comment should end with '--*/'
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: SrcDesc - add argument and description to function comment
+{
+ UINTN loopvar;
+ BOOLEAN IsSet;
+ BOOLEAN ValueToWrite;
+
+ ValueToWrite =
+ ((SrcDesc->Flags & QNC_SMM_CLEAR_WITH_ZERO) == 0) ? TRUE : FALSE;
+
+ for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
+
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {
+ //
+ // Write the bit
+ //
+ WriteBitDesc (&SrcDesc->Sts[loopvar], ValueToWrite);
+
+ //
+ // Don't return until the bit actually clears.
+ //
+ IsSet = TRUE;
+ while (IsSet) {
+ IsSet = ReadBitDesc (&SrcDesc->Sts[loopvar]);
+ //
+ // IsSet will eventually clear -- or else we'll have
+ // an infinite loop.
+ //
+ }
+ }
+ }
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.h
new file mode 100644
index 0000000..00064e8
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.h
@@ -0,0 +1,249 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ QNCSmmHelpers.h
+
+Abstract:
+
+--*/
+
+#ifndef QNC_SMM_HELPERS_H
+#define QNC_SMM_HELPERS_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmm.h"
+#include "QNCxSmmHelpers.h"
+
+//
+// /////////////////////////////////////////////////////////////////////////////
+// SUPPORT / HELPER FUNCTIONS (QNC version-independent)
+//
+VOID
+QNCSmmPublishDispatchProtocols (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+CompareEnables (
+ CONST IN QNC_SMM_SOURCE_DESC *Src1,
+ CONST IN QNC_SMM_SOURCE_DESC *Src2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Src1 - GC_TODO: add argument description
+ Src2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+CompareStatuses (
+ CONST IN QNC_SMM_SOURCE_DESC *Src1,
+ CONST IN QNC_SMM_SOURCE_DESC *Src2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Src1 - GC_TODO: add argument description
+ Src2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+CompareSources (
+ CONST IN QNC_SMM_SOURCE_DESC *Src1,
+ CONST IN QNC_SMM_SOURCE_DESC *Src2
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Src1 - GC_TODO: add argument description
+ Src2 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+SourceIsActive (
+ CONST IN QNC_SMM_SOURCE_DESC *Src
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Src - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+QNCSmmEnableSource (
+ CONST QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+QNCSmmDisableSource (
+ CONST QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+QNCSmmClearSource (
+ CONST QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+QNCSmmClearSourceAndBlock (
+ CONST QNC_SMM_SOURCE_DESC *SrcDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SrcDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmRegisters.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmRegisters.h
new file mode 100644
index 0000000..ec8fd48
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmRegisters.h
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ QNCSmmRegisters.h
+
+Abstract:
+
+--*/
+
+#ifndef QNC_SMM_REGISTERS_H
+#define QNC_SMM_REGISTERS_H
+#include "CommonHeader.h"
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCxSmmHelpers.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCxSmmHelpers.h
new file mode 100755
index 0000000..5f4af68
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCxSmmHelpers.h
@@ -0,0 +1,208 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ QNCxSmmHelpers.h
+
+Abstract:
+
+--*/
+
+#ifndef QNCX_SMM_HELPERS_H
+#define QNCX_SMM_HELPERS_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "QNCSmm.h"
+
+EFI_STATUS
+QNCSmmInitHardware (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+QNCSmmEnableGlobalSmiBit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enables the QNC to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS.
+ Asserts, otherwise.
+
+--*/
+;
+
+EFI_STATUS
+QNCSmmClearSmi (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+QNCSmmSetAndCheckEos (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+QNCSmmGetSciEn (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// ///////////////////////////////////////////////////////////////////////////
+//
+// These may or may not need to change w/ the QNC version;
+// they're here because they're highly IA-32 dependent.
+//
+BOOLEAN
+ReadBitDesc (
+ CONST QNC_SMM_BIT_DESC *BitDesc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ BitDesc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+WriteBitDesc (
+ CONST QNC_SMM_BIT_DESC *BitDesc,
+ CONST BOOLEAN ValueToWrite
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ BitDesc - GC_TODO: add argument description
+ ValueToWrite - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.c
new file mode 100755
index 0000000..59494a0
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.c
@@ -0,0 +1,406 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ SmmAccessPei.c
+
+Abstract:
+
+ This is the driver that publishes the SMM Access Ppi
+ instance for the Quark SOC.
+
+Revision History:
+
+--*/
+#include <PiPei.h>
+#include <Ppi/SmmAccess.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/IntelQNCLib.h>
+#include <QNCAccess.h>
+
+#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \
+ CR ( \
+ a, \
+ SMM_ACCESS_PRIVATE_DATA, \
+ SmmAccess, \
+ SMM_ACCESS_PRIVATE_DATA_SIGNATURE \
+ )
+
+#define MAX_CPU_SOCKET 1
+#define MAX_SMRAM_RANGES 4
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ PEI_SMM_ACCESS_PPI SmmAccess;
+ UINTN NumberRegions;
+ EFI_SMRAM_DESCRIPTOR SmramDesc[MAX_SMRAM_RANGES];
+ UINT8 TsegSize;
+ UINT8 MaxBusNumber;
+ UINT8 SocketPopulated[MAX_CPU_SOCKET];
+ UINT8 SocketBusNum[MAX_CPU_SOCKET];
+} SMM_ACCESS_PRIVATE_DATA;
+
+#define SMM_ACCESS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', 's', 'm', 'a')
+
+
+EFI_STATUS
+EFIAPI
+Open (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *This,
+ IN UINTN DescriptorIndex
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "open" a region of SMRAM. The
+ region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
+ The use of "open" means that the memory is visible from all PEIM
+ and SMM agents.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Open.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully opened.
+ EFI_DEVICE_ERROR - The region could not be opened because locked by
+ chipset.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+{
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ if (DescriptorIndex >= SmmAccess->NumberRegions) {
+ return EFI_INVALID_PARAMETER;
+ } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Open TSEG
+ //
+ if (!QNCOpenSmramRegion ()) {
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
+ return EFI_DEVICE_ERROR;
+ }
+
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_OPEN;
+ SmmAccess->SmmAccess.OpenState = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+Close (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *This,
+ IN UINTN DescriptorIndex
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "close" a region of SMRAM. This is valid for
+ compatible SMRAM region.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Close.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully closed.
+ EFI_DEVICE_ERROR - The region could not be closed because locked by
+ chipset.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+{
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+ BOOLEAN OpenState;
+ UINTN Index;
+
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ if (DescriptorIndex >= SmmAccess->NumberRegions) {
+ return EFI_INVALID_PARAMETER;
+ } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_CLOSED) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Close TSEG
+ //
+ if (!QNCCloseSmramRegion ()) {
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
+ return EFI_DEVICE_ERROR;
+ }
+
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~EFI_SMRAM_OPEN;
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+
+ //
+ // Find out if any regions are still open
+ //
+ OpenState = FALSE;
+ for (Index = 0; Index < SmmAccess->NumberRegions; Index++) {
+ if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {
+ OpenState = TRUE;
+ }
+ }
+
+ SmmAccess->SmmAccess.OpenState = OpenState;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+Lock (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *This,
+ IN UINTN DescriptorIndex
+ )
+/*++
+
+Routine Description:
+
+ This routine accepts a request to "lock" SMRAM. The
+ region could be legacy AB or TSEG near top of physical memory.
+ The use of "lock" means that the memory can no longer be opened
+ to PEIM.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ This - Pointer to the SMM Access Interface.
+ DescriptorIndex - Region of SMRAM to Lock.
+
+Returns:
+
+ EFI_SUCCESS - The region was successfully locked.
+ EFI_DEVICE_ERROR - The region could not be locked because at least
+ one range is still open.
+ EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+
+--*/
+{
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ if (DescriptorIndex >= SmmAccess->NumberRegions) {
+ return EFI_INVALID_PARAMETER;
+ } else if (SmmAccess->SmmAccess.OpenState) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
+ SmmAccess->SmmAccess.LockState = TRUE;
+
+ //
+ // Lock TSEG
+ //
+ QNCLockSmramRegion ();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetCapabilities (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *This,
+ IN OUT UINTN *SmramMapSize,
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
+ )
+/*++
+
+Routine Description:
+
+ This routine services a user request to discover the SMRAM
+ capabilities of this platform. This will report the possible
+ ranges that are possible for SMRAM access, based upon the
+ memory controller capabilities.
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ This - Pointer to the SMRAM Access Interface.
+ SmramMapSize - Pointer to the variable containing size of the
+ buffer to contain the description information.
+ SmramMap - Buffer containing the data describing the Smram
+ region descriptors.
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
+ EFI_SUCCESS - The user provided a sufficiently-sized buffer.
+
+--*/
+{
+ EFI_STATUS Status;
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+ UINTN BufferSize;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+ BufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);
+
+ if (*SmramMapSize < BufferSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ } else {
+ CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);
+ Status = EFI_SUCCESS;
+ }
+
+ *SmramMapSize = BufferSize;
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+SmmAccessPeiEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+
+Routine Description:
+
+ This is the constructor for the SMM Access Ppi
+
+Arguments:
+
+ FfsHeader - FfsHeader.
+ PeiServices - General purpose services available to every PEIM.
+
+Returns:
+
+ EFI_SUCCESS - Protocol successfully started and installed.
+ EFI_UNSUPPORTED - Protocol can't be started.
+--*/
+{
+
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+ SMM_ACCESS_PRIVATE_DATA *SmmAccessPrivate;
+ EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ //
+ // Initialize private data
+ //
+ SmmAccessPrivate = AllocatePool (sizeof(*SmmAccessPrivate));
+ ASSERT(SmmAccessPrivate);
+
+ PpiList = AllocatePool (sizeof(*PpiList));
+ ASSERT (PpiList);
+
+ //
+ // Build SMM related information
+ //
+ SmmAccessPrivate->Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;
+
+ //
+ // Get Hob list
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (DescriptorBlock);
+
+ // Get CPU Max bus number
+
+ SmmAccessPrivate->MaxBusNumber = PCI_BUS_NUMBER_QNC;
+ for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {
+ SmmAccessPrivate->SocketPopulated[Index] = TRUE;
+ SmmAccessPrivate->SocketBusNum[Index] = PCI_BUS_NUMBER_QNC;
+ }
+
+ //
+ // Use the hob to publish SMRAM capabilities
+ //
+ ASSERT (DescriptorBlock->NumberOfSmmReservedRegions <= MAX_SMRAM_RANGES);
+ for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {
+ SmmAccessPrivate->SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;
+ SmmAccessPrivate->SmramDesc[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart;
+ SmmAccessPrivate->SmramDesc[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize;
+ SmmAccessPrivate->SmramDesc[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState;
+ }
+
+ SmmAccessPrivate->NumberRegions = Index;
+ SmmAccessPrivate->SmmAccess.Open = Open;
+ SmmAccessPrivate->SmmAccess.Close = Close;
+ SmmAccessPrivate->SmmAccess.Lock = Lock;
+ SmmAccessPrivate->SmmAccess.GetCapabilities = GetCapabilities;
+ SmmAccessPrivate->SmmAccess.LockState = FALSE;
+ SmmAccessPrivate->SmmAccess.OpenState = FALSE;
+
+ PpiList->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ PpiList->Guid = &gPeiSmmAccessPpiGuid;
+ PpiList->Ppi = &SmmAccessPrivate->SmmAccess;
+
+ Status = (**PeiServices).InstallPpi (PeiServices, PpiList);
+ ASSERT_EFI_ERROR(Status);
+
+ DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", (UINT32)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalStart)));
+ DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", (UINT32)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize)));
+
+ SmmAccessPrivate->TsegSize = (UINT8)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
new file mode 100644
index 0000000..e485141
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
@@ -0,0 +1,77 @@
+#/*++
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Module Name:
+#
+# SmmAccessPei.inf
+#
+# Abstract:
+#
+# Component description file for SmmAccessPei module
+#
+#--*/
+
+[Defines]
+INF_VERSION = 0x00010005
+BASE_NAME = SmmAccessPei
+FILE_GUID = B4E0CDFC-30CD-4b29-A445-B0AA95A532E4
+MODULE_TYPE = PEIM
+VERSION_STRING = 1.0
+ENTRY_POINT = SmmAccessPeiEntryPoint
+
+[Sources]
+ SmmAccessPei.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ BaseMemoryLib
+ MemoryAllocationLib
+ DebugLib
+ HobLib
+ PeiServicesLib
+ PciLib
+ IntelQNCLib
+
+[Guids]
+ gEfiSmmPeiSmramMemoryReserveGuid # ALWAYS_CONSUMED
+
+[Ppis]
+ gPeiSmmAccessPpiGuid # ALWAYS_PRODUCED
+ gEfiPeiMemoryDiscoveredPpiGuid # ALWAYS_CONSUMED
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.c
new file mode 100755
index 0000000..85e8267
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.c
@@ -0,0 +1,300 @@
+/** @file
+ This module provides an implementation of the SMM Control PPI for use with
+ the QNC.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SmmControl.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+
+#include <IntelQNCPeim.h>
+#include <Library/QNCAccessLib.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Generates an SMI using the parameters passed in.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param This A pointer to an instance of
+ EFI_SMM_CONTROL_PPI
+ @param ArgumentBuffer The argument buffer
+ @param ArgumentBufferSize The size of the argument buffer
+ @param Periodic TRUE to indicate a periodical SMI
+ @param ActivationInterval Interval of the periodical SMI
+
+ @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
+ @retval EFI_SUCCESS SMI generated
+
+**/
+EFI_STATUS
+EFIAPI
+PeiActivate (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_CONTROL_PPI *This,
+ IN OUT INT8 *ArgumentBuffer OPTIONAL,
+ IN OUT UINTN *ArgumentBufferSize OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ );
+
+/**
+ Clears an SMI.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param This Pointer to an instance of EFI_SMM_CONTROL_PPI
+ @param Periodic TRUE to indicate a periodical SMI
+
+ @return Return value from SmmClear()
+
+**/
+EFI_STATUS
+EFIAPI
+PeiDeactivate (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_CONTROL_PPI *This,
+ IN BOOLEAN Periodic OPTIONAL
+ );
+
+PEI_SMM_CONTROL_PPI mSmmControlPpi = {
+ PeiActivate,
+ PeiDeactivate
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiSmmControlPpiGuid,
+ &mSmmControlPpi
+};
+
+/**
+ Clear SMI related chipset status and re-enable SMI by setting the EOS bit.
+
+ @retval EFI_SUCCESS The requested operation has been carried out successfully
+ @retval EFI_DEVICE_ERROR The EOS bit could not be set.
+
+**/
+EFI_STATUS
+SmmClear (
+ VOID
+ )
+{
+ UINT16 PM1BLK_Base;
+ UINT16 GPE0BLK_Base;
+
+ //
+ // Get PM1BLK_Base & GPE0BLK_Base
+ //
+ PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);
+ GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
+
+ //
+ // Clear the Power Button Override Status Bit, it gates EOS from being set.
+ // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.
+ //
+
+ //
+ // Clear the APM SMI Status Bit
+ //
+ IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);
+
+ //
+ // Set the EOS Bit
+ //
+ IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+ IN UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ Trigger the software SMI
+
+Arguments:
+
+ Data The value to be set on the software SMI data port
+
+Returns:
+
+ EFI_SUCCESS Function completes successfully
+
+--*/
+{
+ UINT16 GPE0BLK_Base;
+ UINT32 NewValue;
+
+ //
+ // Get GPE0BLK_Base
+ //
+ GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
+
+ //
+ // Enable the APMC SMI
+ //
+ IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM);
+
+ //
+ // Enable SMI globally
+ //
+ NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ NewValue |= SMI_EN;
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
+
+
+ //
+ // Generate the APMC SMI
+ //
+ IoWrite8 (PcdGet16 (PcdSmmActivationPort), Data);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates an SMI using the parameters passed in.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param This A pointer to an instance of
+ EFI_SMM_CONTROL_PPI
+ @param ArgumentBuffer The argument buffer
+ @param ArgumentBufferSize The size of the argument buffer
+ @param Periodic TRUE to indicate a periodical SMI
+ @param ActivationInterval Interval of the periodical SMI
+
+ @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
+ @retval EFI_SUCCESS SMI generated
+
+**/
+EFI_STATUS
+EFIAPI
+PeiActivate (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_CONTROL_PPI *This,
+ IN OUT INT8 *ArgumentBuffer OPTIONAL,
+ IN OUT UINTN *ArgumentBufferSize OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ )
+{
+ INT8 Data;
+ EFI_STATUS Status;
+ //
+ // Periodic SMI not supported.
+ //
+ if (Periodic) {
+ DEBUG ((DEBUG_WARN, "Invalid parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ArgumentBuffer == NULL) {
+ Data = 0xFF;
+ } else {
+ if (ArgumentBufferSize == NULL || *ArgumentBufferSize != 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data = *ArgumentBuffer;
+ }
+ //
+ // Clear any pending the APM SMI
+ //
+ Status = SmmClear ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return SmmTrigger (Data);
+}
+
+/**
+ Clears an SMI.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param This Pointer to an instance of EFI_SMM_CONTROL_PPI
+ @param Periodic TRUE to indicate a periodical SMI
+
+ @return Return value from SmmClear()
+
+**/
+EFI_STATUS
+EFIAPI
+PeiDeactivate (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_CONTROL_PPI *This,
+ IN BOOLEAN Periodic OPTIONAL
+ )
+{
+ if (Periodic) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return SmmClear ();
+}
+
+/**
+ This is the constructor for the SMM Control Ppi.
+
+ This function installs EFI_SMM_CONTROL_PPI.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
+ @return The status returned from InstallProtocolInterface().
+
+--*/
+EFI_STATUS
+EFIAPI
+SmmControlPeiEntry (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = (**PeiServices).InstallPpi (PeiServices, &mPpiList);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf
new file mode 100644
index 0000000..8dbf669
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf
@@ -0,0 +1,75 @@
+## @file
+# Component description file for SmmControlPei module.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmControlPei
+ FILE_GUID = 60EC7720-512B-4490-9FD1-A336769AE01F
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SmmControlPeiEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SmmControlPei.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ PeiServicesLib
+ PcdLib
+ IoLib
+ PciLib
+ QNCAccessLib
+
+[Ppis]
+ gPeiSmmControlPpiGuid # ALWAYS_PRODUCED
+
+[FixedPcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort
+
+[Depex]
+ TRUE
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.c b/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.c
new file mode 100755
index 0000000..2b69b28
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.c
@@ -0,0 +1,975 @@
+/** @file
+ PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "PchSpi.h"
+
+STATIC
+VOID
+FillOutPublicInfoStruct (
+ SPI_INSTANCE *SpiInstance
+ )
+/*++
+
+Routine Description:
+
+ Fillout SpiInstance->InitInfo;
+
+Arguments:
+
+ SpiInstance - Pointer to SpiInstance to initialize
+
+Returns:
+
+ NONE
+
+--*/
+{
+ UINT8 Index;
+
+ SpiInstance->InitInfo.InitTable = &SpiInstance->SpiInitTable;
+
+ //
+ // Give invalid index in case operation not supported.
+ //
+ SpiInstance->InitInfo.JedecIdOpcodeIndex = 0xff;
+ SpiInstance->InitInfo.OtherOpcodeIndex = 0xff;
+ SpiInstance->InitInfo.WriteStatusOpcodeIndex = 0xff;
+ SpiInstance->InitInfo.ProgramOpcodeIndex = 0xff;
+ SpiInstance->InitInfo.ReadOpcodeIndex = 0xff;
+ SpiInstance->InitInfo.EraseOpcodeIndex = 0xff;
+ SpiInstance->InitInfo.ReadStatusOpcodeIndex = 0xff;
+ SpiInstance->InitInfo.FullChipEraseOpcodeIndex = 0xff;
+ for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
+ SpiInstance->InitInfo.JedecIdOpcodeIndex = Index;
+ }
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationOther) {
+ SpiInstance->InitInfo.OtherOpcodeIndex = Index;
+ }
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
+ SpiInstance->InitInfo.WriteStatusOpcodeIndex = Index;
+ }
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationProgramData_1_Byte ||
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationProgramData_64_Byte) {
+ SpiInstance->InitInfo.ProgramOpcodeIndex = Index;
+ }
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {
+ SpiInstance->InitInfo.ReadOpcodeIndex = Index;
+ }
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_256_Byte ||
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_4K_Byte ||
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_8K_Byte ||
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_64K_Byte) {
+ SpiInstance->InitInfo.EraseOpcodeIndex = Index;
+ }
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadStatus) {
+ SpiInstance->InitInfo.ReadStatusOpcodeIndex = Index;
+ }
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFullChipErase) {
+ SpiInstance->InitInfo.FullChipEraseOpcodeIndex = Index;
+ }
+ }
+}
+
+EFI_STATUS
+SpiProtocolConstructor (
+ SPI_INSTANCE *SpiInstance
+ )
+/*++
+
+Routine Description:
+
+ Initialize an SPI protocol instance.
+ The function will assert in debug if PCH RCBA has not been initialized
+
+Arguments:
+
+ SpiInstance - Pointer to SpiInstance to initialize
+
+Returns:
+
+ EFI_SUCCESS The protocol instance was properly initialized
+ EFI_UNSUPPORTED The PCH is not supported by this module
+
+--*/
+{
+ SpiInstance->InitDone = FALSE; // Indicate NOT READY.
+
+ //
+ // Check if the current PCH is known and supported by this code
+ //
+ if (!IsQncSupported ()) {
+ DEBUG ((DEBUG_ERROR, "PCH SPI Protocol not supported due to no proper QNC LPC found!\n"));
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Initialize the SPI protocol instance
+ //
+ SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE;
+ SpiInstance->Handle = NULL;
+ SpiInstance->SpiProtocol.Init = SpiProtocolInit;
+ SpiInstance->SpiProtocol.Lock = SpiProtocolLock;
+ SpiInstance->SpiProtocol.Execute = SpiProtocolExecute;
+ SpiInstance->SpiProtocol.Info = SpiProtocolInfo;
+
+ //
+ // Sanity check to ensure PCH RCBA initialization has occurred previously.
+ //
+ SpiInstance->PchRootComplexBar = MmioRead32 (
+ PciDeviceMmBase (PCI_BUS_NUMBER_QNC,
+ PCI_DEVICE_NUMBER_QNC_LPC,
+ PCI_FUNCTION_NUMBER_QNC_LPC) + R_QNC_LPC_RCBA
+ ) & B_QNC_LPC_RCBA_MASK;
+ ASSERT (SpiInstance->PchRootComplexBar != 0);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UnlockFlashComponents (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 UnlockCmdOpcodeIndex
+ )
+/*++
+
+Routine Description:
+
+ Issue unlock command to disable block protection, this only needs to be done once per SPI power on
+
+Arguments:
+
+ This A pointer to "EFI_SPI_PROTOCOL" for issuing commands
+ UnlockCmdOpcodeIndex The index of the Unlock command
+
+Returns:
+
+ EFI_SUCCESS UnLock operation succeed.
+ EFI_DEVICE_ERROR Device error, operation failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ SPI_INSTANCE *SpiInstance;
+ UINT8 SpiStatus;
+ UINTN PchRootComplexBar;
+
+ if (UnlockCmdOpcodeIndex >= SPI_NUM_OPCODE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ //
+ // Issue unlock command to disable block protection, this only needs to be done once per SPI power on
+ //
+ SpiStatus = 0;
+ //
+ // Issue unlock command to the flash component 1 at first
+ //
+ Status = SpiProtocolExecute (
+ This,
+ UnlockCmdOpcodeIndex,
+ SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_ENABLE ? 0 : 1,
+ TRUE,
+ TRUE,
+ TRUE,
+ (UINTN) 0,
+ sizeof (SpiStatus),
+ &SpiStatus,
+ EnumSpiRegionAll
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Unlock flash component 1 fail!\n"));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SpiProtocolInit (
+ IN EFI_SPI_PROTOCOL *This,
+ IN SPI_INIT_TABLE *InitTable
+ )
+/*++
+
+Routine Description:
+
+ Initialize the host controller to execute SPI command.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ InitTable Initialization data to be programmed into the SPI host controller.
+
+Returns:
+
+ EFI_SUCCESS Initialization completed.
+ EFI_ACCESS_DENIED The SPI static configuration interface has been locked-down.
+ EFI_INVALID_PARAMETER Bad input parameters.
+ EFI_UNSUPPORTED Can't get Descriptor mode VSCC values
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT16 OpcodeType;
+ SPI_INSTANCE *SpiInstance;
+ BOOLEAN MultiPartitionIsSupported;
+ UINTN PchRootComplexBar;
+ UINT8 SFDPCmdOpcodeIndex;
+ UINT8 UnlockCmdOpcodeIndex;
+ UINT8 ReadDataCmdOpcodeIndex;
+ UINT8 FlashPartId[3];
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ if (InitTable != NULL) {
+ //
+ // Copy table into SPI driver Private data structure
+ //
+ CopyMem (
+ &SpiInstance->SpiInitTable,
+ InitTable,
+ sizeof (SPI_INIT_TABLE)
+ );
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check if the SPI interface has been locked-down.
+ //
+ if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
+ ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Clear all the status bits for status regs.
+ //
+ MmioOr16 (
+ (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
+ (UINT16) ((B_QNC_RCRB_SPIS_CDS | B_QNC_RCRB_SPIS_BAS))
+ );
+ MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);
+
+ //
+ // Set the Prefix Opcode registers.
+ //
+ MmioWrite16 (
+ PchRootComplexBar + R_QNC_RCRB_SPIPREOP,
+ (SpiInstance->SpiInitTable.PrefixOpcode[1] << 8) | InitTable->PrefixOpcode[0]
+ );
+ MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIPREOP);
+
+ //
+ // Set Opcode Type Configuration registers.
+ //
+ for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) {
+ switch (SpiInstance->SpiInitTable.OpcodeMenu[Index].Type) {
+ case EnumSpiOpcodeRead:
+ OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_READ << (Index * 2));
+ break;
+ case EnumSpiOpcodeWrite:
+ OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_WRITE << (Index * 2));
+ break;
+ case EnumSpiOpcodeWriteNoAddr:
+ OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE << (Index * 2));
+ break;
+ default:
+ OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_READ << (Index * 2));
+ break;
+ }
+ }
+ MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE, OpcodeType);
+ MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE);
+
+ //
+ // Setup the Opcode Menu registers.
+ //
+ ReadDataCmdOpcodeIndex = SPI_NUM_OPCODE;
+ SFDPCmdOpcodeIndex = SPI_NUM_OPCODE;
+ UnlockCmdOpcodeIndex = SPI_NUM_OPCODE;
+ for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
+ MmioWrite8 (
+ PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index,
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Code
+ );
+ MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index);
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
+ Status = SpiProtocolExecute (
+ This,
+ Index,
+ 0,
+ TRUE,
+ TRUE,
+ FALSE,
+ (UINTN) 0,
+ 3,
+ FlashPartId,
+ EnumSpiRegionDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (FlashPartId[0] != SpiInstance->SpiInitTable.VendorId ||
+ FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0 ||
+ FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||
+ SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {
+ ReadDataCmdOpcodeIndex = Index;
+ }
+
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDiscoveryParameters) {
+ SFDPCmdOpcodeIndex = Index;
+ }
+
+ if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
+ UnlockCmdOpcodeIndex = Index;
+ }
+ }
+
+ MultiPartitionIsSupported = FALSE;
+
+ Status = UnlockFlashComponents (
+ This,
+ UnlockCmdOpcodeIndex
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Unlock flash components fail!\n"));
+ }
+
+ SpiPhaseInit ();
+ FillOutPublicInfoStruct (SpiInstance);
+ SpiInstance->InitDone = TRUE;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SpiProtocolLock (
+ IN EFI_SPI_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Lock the SPI Static Configuration Interface.
+ Once locked, the interface can not be changed and can only be clear by system reset.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+
+Returns:
+
+ EFI_SUCCESS Lock operation succeed.
+ EFI_DEVICE_ERROR Device error, operation failed.
+ EFI_ACCESS_DENIED The interface has already been locked.
+
+--*/
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchRootComplexBar;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ //
+ // Check if the SPI interface has been locked-down.
+ //
+ if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Lock-down the configuration interface.
+ //
+ MmioOr16 ((UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS), (UINT16) (B_QNC_RCRB_SPIS_SCL));
+
+ //
+ // Verify if it's really locked.
+ //
+ if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) == 0) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ //
+ // Save updated register in S3 Boot script.
+ //
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
+ 1,
+ (VOID *) (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SpiProtocolExecute (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ )
+/*++
+
+Routine Description:
+
+ Execute SPI commands from the host controller.
+ This function would be called by runtime driver, please do not use any MMIO marco here
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ OpcodeIndex Index of the command in the OpCode Menu.
+ PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ DataCycle TRUE if the SPI cycle contains data
+ Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
+ data transfer into multiple operations. This function ensures each operation does
+ not cross 256 byte flash address boundary.
+ *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+ (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+ function to cut the data transfer at proper address boundaries, and it's the
+ caller's reponsibility to pass in a properly cut DataByteCount parameter.
+ Buffer Pointer to caller-allocated buffer containing the dada received or sent during the
+ SPI cycle.
+ SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+Returns:
+
+ EFI_SUCCESS Command succeed.
+ EFI_INVALID_PARAMETER The parameters specified are not valid.
+ EFI_UNSUPPORTED Command not supported.
+ EFI_DEVICE_ERROR Device error, command aborts abnormally.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 BiosCtlSave;
+ UINT32 SmiEnSave;
+
+ BiosCtlSave = 0;
+ SmiEnSave = 0;
+
+ //
+ // Check if the parameters are valid.
+ //
+ if ((OpcodeIndex >= SPI_NUM_OPCODE) || (PrefixOpcodeIndex >= SPI_NUM_PREFIX_OPCODE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure it's safe to program the command.
+ //
+ if (!WaitForSpiCycleComplete (This, FALSE)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Acquire access to the SPI interface is not required any more.
+ //
+ //
+ // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
+ // whose SMI handler accesses flash (e.g. for error logging)
+ //
+ SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));
+
+ //
+ // Save BIOS Ctrl register
+ //
+ BiosCtlSave = PciRead16 (
+ PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
+ PCI_DEVICE_NUMBER_QNC_LPC,
+ PCI_FUNCTION_NUMBER_QNC_LPC,
+ R_QNC_LPC_BIOS_CNTL)
+ ) & (B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE | B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP);
+
+ //
+ // Enable flash writing
+ //
+ PciOr16 (
+ PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
+ PCI_DEVICE_NUMBER_QNC_LPC,
+ PCI_FUNCTION_NUMBER_QNC_LPC,
+ R_QNC_LPC_BIOS_CNTL),
+ (UINT16) (B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP)
+ );
+
+ //
+ // If shifts the data out, disable Prefetching and Caching.
+ //
+ if (ShiftOut) {
+ PciAndThenOr16 (
+ PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
+ PCI_DEVICE_NUMBER_QNC_LPC,
+ PCI_FUNCTION_NUMBER_QNC_LPC,
+ R_QNC_LPC_BIOS_CNTL),
+ (UINT16) (~(B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE)),
+ (UINT16) ((B_QNC_LPC_BIOS_CNTL_BCD))
+ );
+ }
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ OpcodeIndex,
+ PrefixOpcodeIndex,
+ DataCycle,
+ Atomic,
+ ShiftOut,
+ Address,
+ DataByteCount,
+ Buffer,
+ SpiRegionType
+ );
+
+ //
+ // Restore BIOS Ctrl register
+ //
+ PciAndThenOr16 (
+ PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
+ PCI_DEVICE_NUMBER_QNC_LPC,
+ PCI_FUNCTION_NUMBER_QNC_LPC,
+ R_QNC_LPC_BIOS_CNTL),
+ (UINT16) (~(B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE | B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP)),
+ (UINT16) (BiosCtlSave)
+ );
+ //
+ // Restore SMIs.
+ //
+ QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, SmiEnSave);
+
+ return Status;
+}
+
+VOID
+SpiOffset2Physical (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINTN SpiRegionOffset,
+ IN SPI_REGION_TYPE SpiRegionType,
+ OUT UINTN *HardwareSpiAddress,
+ OUT UINTN *BaseAddress,
+ OUT UINTN *LimitAddress
+ )
+/*++
+
+Routine Description:
+
+ Convert SPI offset to Physical address of SPI hardware
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ SpiRegionOffset In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ BaseAddress Base Address of the region.
+ SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+ HardwareSpiAddress Return absolution SPI address (i.e., Flash Linear Address)
+ BaseAddress Return base address of the region type
+ LimitAddress Return limit address of the region type
+
+Returns:
+
+ EFI_SUCCESS Command succeed.
+
+--*/
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchRootComplexBar;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ if (SpiRegionType == EnumSpiRegionAll) {
+ //
+ // EnumSpiRegionAll indicates address is relative to flash device (i.e., address is Flash
+ // Linear Address)
+ //
+ *HardwareSpiAddress = SpiRegionOffset;
+ } else {
+ //
+ // Otherwise address is relative to BIOS image
+ //
+ *HardwareSpiAddress = SpiRegionOffset + SpiInstance->SpiInitTable.BiosStartOffset;
+ }
+}
+
+EFI_STATUS
+SendSpiCmd (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ )
+/*++
+
+Routine Description:
+
+ This function sends the programmed SPI command to the slave device.
+
+Arguments:
+
+ OpcodeIndex Index of the command in the OpCode Menu.
+ PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ DataCycle TRUE if the SPI cycle contains data
+ Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
+ data transfer into multiple operations. This function ensures each operation does
+ not cross 256 byte flash address boundary.
+ *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+ (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+ function to cut the data transfer at proper address boundaries, and it's the
+ caller's reponsibility to pass in a properly cut DataByteCount parameter.
+ Buffer Data received or sent during the SPI cycle.
+ SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+Returns:
+
+ EFI_SUCCESS SPI command completes successfully.
+ EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ EFI_INVALID_PARAMETER The parameters specified are not valid.
+
+--*/
+{
+ UINT32 Index;
+ SPI_INSTANCE *SpiInstance;
+ UINTN HardwareSpiAddr;
+ UINTN SpiBiosSize;
+ UINTN BaseAddress;
+ UINTN LimitAddress;
+ UINT32 SpiDataCount;
+ UINT8 OpCode;
+ SPI_OPERATION Operation;
+ UINTN PchRootComplexBar;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+ SpiBiosSize = SpiInstance->SpiInitTable.BiosSize;
+ Operation = SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Operation;
+ OpCode = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + OpcodeIndex);
+
+ //
+ // Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0
+ //
+ if (OpCode == 0 || SpiBiosSize == 0) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SpiOffset2Physical (This, Address, SpiRegionType, &HardwareSpiAddr, &BaseAddress, &LimitAddress);
+ //
+ // Have direct access to BIOS region in Descriptor mode,
+ //
+ if (SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Type == EnumSpiOpcodeRead &&
+ SpiRegionType == EnumSpiRegionBios) {
+ CopyMem (
+ Buffer,
+ (UINT8 *) ((HardwareSpiAddr - BaseAddress) + (UINT32) (~(SpiBiosSize - 1))),
+ DataByteCount
+ );
+ return EFI_SUCCESS;
+ }
+ //
+ // DEBUG((EFI_D_ERROR, "SPIADDR %x, %x, %x, %x\n", Address, HardwareSpiAddr, BaseAddress,
+ // LimitAddress));
+ //
+ if ((DataCycle == FALSE) && (DataByteCount > 0)) {
+ DataByteCount = 0;
+ }
+
+ do {
+ //
+ // Trim at 256 byte boundary per operation,
+ // - PCH SPI controller requires trimming at 4KB boundary
+ // - Some SPI chips require trimming at 256 byte boundary for write operation
+ // - Trimming has limited performance impact as we can read / write atmost 64 byte
+ // per operation
+ //
+ if (HardwareSpiAddr + DataByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
+ SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
+ } else {
+ SpiDataCount = DataByteCount;
+ }
+ //
+ // Calculate the number of bytes to shift in/out during the SPI data cycle.
+ // Valid settings for the number of bytes duing each data portion of the
+ // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ if (SpiDataCount >= 64) {
+ SpiDataCount = 64;
+ } else if ((SpiDataCount &~0x07) != 0) {
+ SpiDataCount = SpiDataCount &~0x07;
+ }
+ //
+ // If shifts data out, load data into the SPI data buffer.
+ //
+ if (ShiftOut) {
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ MmioWrite8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index, Buffer[Index]);
+ MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
+ }
+ }
+
+ MmioWrite32 (
+ (PchRootComplexBar + R_QNC_RCRB_SPIA),
+ (UINT32) (HardwareSpiAddr & B_QNC_RCRB_SPIA_MASK)
+ );
+ MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIA);
+
+ //
+ // Execute the command on the SPI compatible mode
+ //
+
+ //
+ // Clear error flags
+ //
+ MmioOr16 ((PchRootComplexBar + R_QNC_RCRB_SPIS), B_QNC_RCRB_SPIS_BAS);
+
+ //
+ // Initialte the SPI cycle
+ //
+ if (DataCycle) {
+ MmioWrite16 (
+ (PchRootComplexBar + R_QNC_RCRB_SPIC),
+ ( (UINT16) (B_QNC_RCRB_SPIC_DC) | (UINT16) (((SpiDataCount - 1) << 8) & B_QNC_RCRB_SPIC_DBC) |
+ (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
+ (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
+ (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
+ (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
+ } else {
+ MmioWrite16 (
+ (PchRootComplexBar + R_QNC_RCRB_SPIC),
+ ( (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
+ (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
+ (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
+ (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
+ }
+
+ MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIC);
+
+ //
+ // end of command execution
+ //
+ // Wait the SPI cycle to complete.
+ //
+ if (!WaitForSpiCycleComplete (This, TRUE)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // If shifts data in, get data from the SPI data buffer.
+ //
+ if (!ShiftOut) {
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ Buffer[Index] = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
+ }
+ }
+
+ HardwareSpiAddr += SpiDataCount;
+ Buffer += SpiDataCount;
+ DataByteCount -= SpiDataCount;
+ } while (DataByteCount > 0);
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN EFI_SPI_PROTOCOL *This,
+ IN BOOLEAN ErrorCheck
+ )
+/*++
+
+Routine Description:
+
+ Wait execution cycle to complete on the SPI interface. Check both Hardware
+ and Software Sequencing status registers
+
+Arguments:
+
+ This - The SPI protocol instance
+ UseSoftwareSequence - TRUE if this is a Hardware Sequencing operation
+ ErrorCheck - TRUE if the SpiCycle needs to do the error check
+
+Returns:
+
+ TRUE SPI cycle completed on the interface.
+ FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+
+--*/
+{
+ UINT64 WaitTicks;
+ UINT64 WaitCount;
+ UINT16 Data16;
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchRootComplexBar;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ PchRootComplexBar = SpiInstance->PchRootComplexBar;
+
+ //
+ // Convert the wait period allowed into to tick count
+ //
+ WaitCount = WAIT_TIME / WAIT_PERIOD;
+
+ //
+ // Wait for the SPI cycle to complete.
+ //
+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+ Data16 = MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);
+ if ((Data16 & B_QNC_RCRB_SPIS_SCIP) == 0) {
+ MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIS, (B_QNC_RCRB_SPIS_BAS | B_QNC_RCRB_SPIS_CDS));
+ if ((Data16 & B_QNC_RCRB_SPIS_BAS) && (ErrorCheck == TRUE)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+
+ MicroSecondDelay (WAIT_PERIOD);
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+EFIAPI
+SpiProtocolInfo (
+ IN EFI_SPI_PROTOCOL *This,
+ OUT SPI_INIT_INFO **InitInfoPtr
+ )
+/*++
+
+Routine Description:
+
+ Return info about SPI host controller, to help callers usage of Execute
+ service.
+
+ If 0xff is returned as an opcode index in init info struct
+ then device does not support the operation.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ InitInfoPtr Pointer to init info written to this memory location.
+
+Returns:
+
+ EFI_SUCCESS Information returned.
+ EFI_INVALID_PARAMETER Invalid parameter.
+ EFI_NOT_READY Required resources not setup.
+ Others Unexpected error happened.
+
+--*/
+{
+ SPI_INSTANCE *SpiInstance;
+
+ if (This == NULL || InitInfoPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ if (SpiInstance->Signature != PCH_SPI_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!SpiInstance->InitDone) {
+ *InitInfoPtr = NULL;
+ return EFI_NOT_READY;
+ }
+ *InitInfoPtr = &SpiInstance->InitInfo;
+ return EFI_SUCCESS;
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.h b/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.h
new file mode 100755
index 0000000..5205d77
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.h
@@ -0,0 +1,341 @@
+/** @file
+ Header file for the PCH SPI Common Driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef _SPI_COMMON_H_
+#define _SPI_COMMON_H_
+
+#include "Protocol/Spi.h"
+#include <Library/PciLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Uefi/UefiBaseType.h>
+
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+// Wait Time = 6 seconds = 6000000 microseconds
+// Wait Period = 10 microseconds
+//
+#define WAIT_TIME 6000000
+#define WAIT_PERIOD 10
+//
+// PCH Required SPI Commands -------- COMMAND SET I ------------
+// SPI flash device must support in order to be compatible with PCH
+//
+#define PCH_SPI_COMMAND_PROGRAM_BYTE 0x02
+#define PCH_SPI_COMMAND_READ_DATA 0x03
+#define PCH_SPI_COMMAND_WRITE_DISABLE 0x04
+#define PCH_SPI_COMMAND_READ_STATUS 0x05
+#define PCH_SPI_COMMAND_WRITE_ENABLE 0x06
+#define PCH_SPI_COMMAND_FAST_READ 0x0B
+#define PCH_SPI_COMMAND_READ_ID 0x9F
+#define PCH_SPI_COMMAND_DUAL_FAST_READ 0x3B // Dual Output Fast Read
+
+//
+// Need to support at least one of the following two kinds of size of sector for erasing
+//
+#define PCH_SPI_COMMAND_4KB_ERASE 0x20
+#define PCH_SPI_COMMAND_64KB_ERASE 0xD8
+//
+// Recommended SPI Commands -------- COMMAND SET II ------------
+// SPI flash device best to support
+//
+#define PCH_SPI_COMMAND_WRITE_STATUS 0x01
+#define PCH_SPI_COMMAND_FULL_CHIP_ERASE 0xC7
+
+//
+// Private data structure definitions for the driver
+//
+#define PCH_SPI_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'S', 'P', 'I')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SPI_PROTOCOL SpiProtocol;
+ SPI_INIT_TABLE SpiInitTable;
+ UINTN PchRootComplexBar;
+ BOOLEAN InitDone; // Set to TRUE on SpiProtocolInit SUCCESS.
+ SPI_INIT_INFO InitInfo;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+//
+// Function prototypes used by the SPI protocol.
+//
+EFI_STATUS
+SpiProtocolConstructor (
+ SPI_INSTANCE *SpiInstance
+ )
+/*++
+
+Routine Description:
+
+ Initialize an SPI protocol instance.
+ The function will assert in debug if PCH RCBA has not been initialized
+
+Arguments:
+
+ SpiInstance - Pointer to SpiInstance to initialize
+
+Returns:
+
+ EFI_SUCCESS The protocol instance was properly initialized
+ EFI_UNSUPPORTED The PCH is not supported by this module
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SpiProtocolInit (
+ IN EFI_SPI_PROTOCOL *This,
+ IN SPI_INIT_TABLE *InitTable
+ )
+/*++
+
+Routine Description:
+
+ Initialize the host controller to execute SPI command.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ InitTable Initialization data to be programmed into the SPI host controller.
+
+Returns:
+
+ EFI_SUCCESS Initialization completed.
+ EFI_ACCESS_DENIED The SPI static configuration interface has been locked-down.
+ EFI_INVALID_PARAMETER Bad input parameters.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SpiProtocolLock (
+ IN EFI_SPI_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Lock the SPI Static Configuration Interface.
+ Once locked, the interface can not be changed and can only be clear by system reset.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+
+Returns:
+
+ EFI_SUCCESS Lock operation succeed.
+ EFI_DEVICE_ERROR Device error, operation failed.
+ EFI_ACCESS_DENIED The interface has already been locked.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SpiProtocolExecute (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ )
+/*++
+
+Routine Description:
+
+ Execute SPI commands from the host controller.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ OpcodeIndex Index of the command in the OpCode Menu.
+ PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ DataCycle TRUE if the SPI cycle contains data
+ Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ DataByteCount Number of bytes in the data portion of the SPI cycle.
+ Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+ SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+Returns:
+
+ EFI_SUCCESS Command succeed.
+ EFI_INVALID_PARAMETER The parameters specified are not valid.
+ EFI_UNSUPPORTED Command not supported.
+ EFI_DEVICE_ERROR Device error, command aborts abnormally.
+
+--*/
+;
+
+EFI_STATUS
+SendSpiCmd (
+ IN EFI_SPI_PROTOCOL *This,
+ IN UINT8 OpcodeIndex,
+ IN UINT8 PrefixOpcodeIndex,
+ IN BOOLEAN DataCycle,
+ IN BOOLEAN Atomic,
+ IN BOOLEAN ShiftOut,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer,
+ IN SPI_REGION_TYPE SpiRegionType
+ )
+/*++
+
+Routine Description:
+
+ This function sends the programmed SPI command to the slave device.
+
+Arguments:
+
+ OpcodeIndex Index of the command in the OpCode Menu.
+ PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+ DataCycle TRUE if the SPI cycle contains data
+ Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+ ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+ Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+ Region, this value specifies the offset from the Region Base; for BIOS Region,
+ this value specifies the offset from the start of the BIOS Image. In Non
+ Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+ Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+ Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+ supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+ the flash (in Non Descriptor Mode)
+ DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the
+ data transfer into multiple operations. This function ensures each operation does
+ not cross 256 byte flash address boundary.
+ *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+ (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+ function to cut the data transfer at proper address boundaries, and it's the
+ caller's reponsibility to pass in a properly cut DataByteCount parameter.
+ Buffer Data received or sent during the SPI cycle.
+ SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+ EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+ Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+ and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+ to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+Returns:
+
+ EFI_SUCCESS SPI command completes successfully.
+ EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ EFI_INVALID_PARAMETER The parameters specified are not valid.
+
+--*/
+;
+
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN EFI_SPI_PROTOCOL *This,
+ IN BOOLEAN ErrorCheck
+ )
+/*++
+
+Routine Description:
+
+ Wait execution cycle to complete on the SPI interface. Check both Hardware
+ and Software Sequencing status registers
+
+Arguments:
+
+ This - The SPI protocol instance
+ UseSoftwareSequence - TRUE if this is a Hardware Sequencing operation
+ ErrorCheck - TRUE if the SpiCycle needs to do the error check
+
+Returns:
+
+ TRUE SPI cycle completed on the interface.
+ FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SpiProtocolInfo (
+ IN EFI_SPI_PROTOCOL *This,
+ OUT SPI_INIT_INFO **InitInfoPtr
+ )
+/*++
+
+Routine Description:
+
+ Return info about SPI host controller, to help callers usage of Execute
+ service.
+
+ If 0xff is returned as an opcode index in init info struct
+ then device does not support the operation.
+
+Arguments:
+
+ This Pointer to the EFI_SPI_PROTOCOL instance.
+ InitInfoPtr Pointer to init info written to this memory location.
+
+Returns:
+
+ EFI_SUCCESS Information returned.
+ EFI_INVALID_PARAMETER Invalid parameter.
+ EFI_NOT_READY Required resources not setup.
+ Others Unexpected error happened.
+
+--*/
+;
+
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.c b/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.c
new file mode 100644
index 0000000..f49a112
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.c
@@ -0,0 +1,236 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ PchSpi.c
+
+Abstract:
+
+ PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.
+
+--*/
+#include "PchSpi.h"
+
+extern EFI_GUID gEfiEventVirtualAddressChangeGuid;
+
+//
+// Global variables
+//
+SPI_INSTANCE *mSpiInstance;
+static CONST UINT32 mSpiRegister[] = {
+ R_QNC_RCRB_SPIS,
+ R_QNC_RCRB_SPIPREOP,
+ R_QNC_RCRB_SPIOPMENU,
+ R_QNC_RCRB_SPIOPMENU + 4
+ };
+
+//
+// Function implementations
+//
+VOID
+PchSpiVirtualddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+Arguments:
+
+ Event The event registered.
+ Context Event context. Not used in this event handler.
+
+Returns:
+
+ None.
+
+--*/
+{
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->PchRootComplexBar));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Init));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Lock));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Execute));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance));
+}
+
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Entry point for the SPI host controller driver.
+
+Arguments:
+
+ ImageHandle Image handle of this driver.
+ SystemTable Global system service table.
+
+Returns:
+
+ EFI_SUCCESS Initialization complete.
+ EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ EFI_DEVICE_ERROR Device error, driver exits abnormally.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 BaseAddress;
+ UINT64 Length;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdMemorySpaceDescriptor;
+ UINT64 Attributes;
+ EFI_EVENT Event;
+
+ DEBUG ((DEBUG_INFO, "InstallPchSpi() Start\n"));
+
+ //
+ // Allocate Runtime memory for the SPI protocol instance.
+ //
+ mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE));
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Initialize the SPI protocol instance
+ //
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Install the EFI_SPI_PROTOCOL interface
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &(mSpiInstance->Handle),
+ &gEfiSpiProtocolGuid,
+ &(mSpiInstance->SpiProtocol),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set RCBA space in GCD to be RUNTIME so that the range will be supported in
+ // virtual address mode in EFI aware OS runtime.
+ // It will assert if RCBA Memory Space is not allocated
+ // The caller is responsible for the existence and allocation of the RCBA Memory Spaces
+ //
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) (mSpiInstance->PchRootComplexBar);
+ Length = FixedPcdGet64 (PcdRcbaMmioSize);
+
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BaseAddress,
+ Length,
+ EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ PchSpiVirtualddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "InstallPchSpi() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ )
+/*++
+Routine Description:
+
+ This function is a a hook for Spi Dxe phase specific initialization
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+
+ //
+ // Disable SMM BIOS write protect if it's not a SMM protocol
+ //
+ MmioAnd8 (
+ PciDeviceMmBase (PCI_BUS_NUMBER_QNC,
+ PCI_DEVICE_NUMBER_QNC_LPC,
+ PCI_FUNCTION_NUMBER_QNC_LPC) + R_QNC_LPC_BIOS_CNTL,
+ (UINT8) (~B_QNC_LPC_BIOS_CNTL_SMM_BWP)
+ );
+
+ //
+ // Save SPI Registers for S3 resume usage
+ //
+ for (Index = 0; Index < sizeof (mSpiRegister) / sizeof (UINT32); Index++) {
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index]),
+ 1,
+ (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index])
+ );
+ }
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.h b/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.h
new file mode 100644
index 0000000..ff1f77d
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.h
@@ -0,0 +1,104 @@
+/** @file
+ Header file for the PCH SPI Runtime Driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _PCH_SPI_H_
+#define _PCH_SPI_H_
+
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/Spi.h>
+#include "SpiCommon.h"
+#include <Library/PciExpressLib.h>
+#include <Protocol/BootScriptSave.h>
+#include <IntelQNCRegs.h>
+#include <IntelQNCLib.h>
+#include <QNCAccessLib.h>
+#include <Library/TimerLib.h>
+
+#define EFI_INTERNAL_POINTER 0x00000004
+
+
+//
+// Function prototypes used by the SPI protocol.
+//
+VOID
+PchSpiVirtualddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+Arguments:
+
+ Event The event registered.
+ Context Event context. Not used in this event handler.
+
+Returns:
+
+ None.
+
+--*/
+;
+
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ )
+/*++
+Routine Description:
+
+ This function is a hook for Spi Dxe phase specific initialization
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpiRuntime.inf b/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpiRuntime.inf
new file mode 100644
index 0000000..5ffd800
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpiRuntime.inf
@@ -0,0 +1,112 @@
+## @file
+# Component description file for the SPI Runtime driver.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+#
+#
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PchSpiRuntime
+ FILE_GUID = C194C6EA-B68C-4981-B64B-9BD271474B20
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InstallPchSpi
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+[Sources]
+ PchSpi.h
+ PchSpi.c
+ ../Common/SpiCommon.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ UefiRuntimeLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ IntelQNCLib
+ QNCAccessLib
+ TimerLib
+ DxeServicesTableLib
+ UefiLib
+ DebugLib
+ MemoryAllocationLib
+ S3BootScriptLib
+ PciExpressLib
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+[Guids]
+
+[Protocols]
+ gEfiSpiProtocolGuid
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioSize
+
+[Depex]
+ TRUE
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.c b/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.c
new file mode 100644
index 0000000..f4d2174
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.c
@@ -0,0 +1,146 @@
+/** @file
+
+ PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+**/
+#include "PchSpi.h"
+
+SPI_INSTANCE *mSpiInstance;
+
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Entry point for the SPI host controller driver.
+
+Arguments:
+
+ ImageHandle Image handle of this driver.
+ SystemTable Global system service table.
+
+Returns:
+
+ EFI_SUCCESS Initialization complete.
+ EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ EFI_DEVICE_ERROR Device error, driver exits abnormally.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Allocate pool for SPI protocol instance
+ //
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData, // MemoryType don't care
+ sizeof (SPI_INSTANCE),
+ &mSpiInstance
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
+ //
+ // Initialize the SPI protocol instance
+ //
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install the SMM EFI_SPI_PROTOCOL interface
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &(mSpiInstance->Handle),
+ &gEfiSmmSpiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(mSpiInstance->SpiProtocol)
+ );
+ if (EFI_ERROR (Status)) {
+ gSmst->SmmFreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ )
+/*++
+Routine Description:
+
+ This function is a a hook for Spi Smm phase specific initialization
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+ static CONST UINT32 SpiRegister[] = {
+ R_QNC_RCRB_SPIS,
+ R_QNC_RCRB_SPIPREOP,
+ R_QNC_RCRB_SPIOPMENU,
+ R_QNC_RCRB_SPIOPMENU + 4
+ };
+
+ //
+ // Save SPI Registers for S3 resume usage
+ //
+ for (Index = 0; Index < sizeof (SpiRegister) / sizeof (UINT32); Index++) {
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (mSpiInstance->PchRootComplexBar + SpiRegister[Index]),
+ 1,
+ (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + SpiRegister[Index])
+ );
+ }
+}
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.h b/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.h
new file mode 100644
index 0000000..260cbad
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.h
@@ -0,0 +1,73 @@
+/** @file
+ Header file for the PCH SPI SMM Driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _PCH_SPI_H_
+#define _PCH_SPI_H_
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Framework/BootScript.h>
+#include <Protocol/Spi.h>
+#include "SpiCommon.h"
+#include <Protocol/BootScriptSave.h>
+#include <Library/SmmServicesTableLib.h>
+#include <IntelQNCRegs.h>
+#include <IntelQNCLib.h>
+#include <QNCAccessLib.h>
+#include <Library/TimerLib.h>
+
+VOID
+EFIAPI
+SpiPhaseInit (
+ VOID
+ )
+/*++
+Routine Description:
+
+ This function is a hook for Spi Smm phase specific initialization
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+#endif
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpiSmm.inf b/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpiSmm.inf
new file mode 100644
index 0000000..5773c4b
--- /dev/null
+++ b/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpiSmm.inf
@@ -0,0 +1,75 @@
+## @file
+# Spi smm driver
+#
+# Component description file for the SPI SMM driver.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PchSpiSmm
+ FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = InstallPchSpi
+
+[Sources]
+ PchSpi.h
+ PchSpi.c
+ ../Common/SpiCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ IntelQNCLib
+ QNCAccessLib
+ TimerLib
+ S3BootScriptLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ BaseLib
+ SmmServicesTableLib
+
+
+[Protocols]
+ gEfiSmmSpiProtocolGuid # PRODUCES
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[Depex]
+ gEfiSmmBase2ProtocolGuid
diff --git a/QuarkSocPkg/QuarkSocPkg.dec b/QuarkSocPkg/QuarkSocPkg.dec
new file mode 100755
index 0000000..dcb469f
--- /dev/null
+++ b/QuarkSocPkg/QuarkSocPkg.dec
@@ -0,0 +1,261 @@
+## @file
+# INTEL Quark SoC Module Package Reference Implementations
+#
+# This Module provides FRAMEWORK reference implementation for INTEL Quark SoC.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = QuarkSocPkg
+ PACKAGE_GUID = 28DECF17-6C75-448f-87DC-BDE4BD579919
+ PACKAGE_VERSION = 0.1
+
+
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+# Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+# SEC PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER BASE
+#
+################################################################################
+[Includes]
+ #
+ # North Cluster
+ #
+ QuarkNorthCluster/Include
+ QuarkNorthCluster/Include/Library
+ QuarkNorthCluster/MemoryInit/Pei
+
+ #
+ # South Cluster
+ #
+ QuarkSouthCluster/Include
+
+################################################################################
+#
+# Library Class Header section - list of Library Class header files that are
+# provided by this package.
+#
+################################################################################
+[LibraryClasses]
+ #
+ # North Cluster
+ #
+ QNCAccessLib|QuarkNorthCluster/Include/Library/QNCAccessLib.h
+ IntelQNCLib|QuarkNorthCluster/Include/Library/IntelQNCLib.h
+
+################################################################################
+#
+# Global Guid Definition section - list of Global Guid C Name Data Structures
+# that are provided by this package.
+#
+################################################################################
+[Guids]
+ #
+ # North Cluster
+ #
+ gEfiQuarkNcSocIdTokenSpaceGuid = { 0xca452c6a, 0xdf0c, 0x4dc9, { 0x82, 0xfb, 0xea, 0xe2, 0xab, 0x31, 0x29, 0x46 }}
+ gEfiPciGInfoHobGuid = { 0xACB72A8B, 0xF584, 0x47CC, { 0xB3, 0xA5, 0xD4, 0xB8, 0x6D, 0x4C, 0x04, 0x04 }}
+ gEfiQncTokenSpaceGuid = { 0x758e73aa, 0x2587, 0x4ef1, { 0x86, 0xa9, 0x83, 0xa7, 0xfb, 0x87, 0x2a, 0x52 }}
+ gQncS3CodeInLockBoxGuid = { 0x1f18c5b3, 0x29ed, 0x4d9e, {0xa5, 0x4, 0x6d, 0x97, 0x8e, 0x7e, 0xd5, 0x69}}
+ gQncS3ContextInLockBoxGuid = { 0xe5769ea9, 0xe706, 0x454b, {0x95, 0x7f, 0xaf, 0xc6, 0xdb, 0x4b, 0x8a, 0xd}}
+ gRedirectServicesHobGuid = { 0x91f9a3af, 0x3df7, 0x4744, { 0x86, 0x13, 0x32, 0x79, 0x27, 0x7c, 0x35, 0x4a }}
+
+ #
+ # South Cluster
+ #
+ gEfiQuarkSCSocIdTokenSpaceGuid = { 0xef251b71, 0xceed, 0x484e, { 0x82, 0xe3, 0x3a, 0x1f, 0x34, 0xf5, 0x12, 0xe2 }}
+
+################################################################################
+#
+# Global Ppi Definition section - list of Global Ppi C Name Data Structures
+# that are provided by this package.
+#
+################################################################################
+[Ppis]
+ #
+ # North Cluster
+ #
+ gCltMemoryInitPpiGuid = { 0x21ff1fee, 0xd33a, 0x4fce, { 0xa6, 0x5e, 0x95, 0x5e, 0xa3, 0xc4, 0x1f, 0x40}}
+ gQNCMemoryInitPpiGuid = {0xa55d6970, 0x1306, 0x440c, {0x8c, 0x72, 0x8f, 0x51, 0xfa, 0xfb, 0x29, 0x26}}
+
+################################################################################
+#
+# Global Protocols Definition section - list of Global Protocols C Name Data
+# Structures that are provided by this package.
+#
+################################################################################
+[Protocols]
+ #
+ # North Cluster
+ #
+ gEfiPlatformPolicyProtocolGuid = { 0x2977064F, 0xAB96, 0x4FA9, { 0x85, 0x45, 0xF9, 0xC4, 0x02, 0x51, 0xE0, 0x7F }}
+ gEfiSmmIchnDispatch2ProtocolGuid = { 0xadf3a128, 0x416d, 0x4060, { 0x8d, 0xdf, 0x30, 0xa1, 0xd7, 0xaa, 0xb6, 0x99 }}
+ gEfiSpiProtocolGuid = { 0x1156efc6, 0xea32, 0x4396, { 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 }}
+ gEfiSmmSpiProtocolGuid = { 0xD9072C35, 0xEB8F, 0x43ad, { 0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 }}
+ gEfiQncS3SupportProtocolGuid = { 0xe287d20b, 0xd897, 0x4e1e, { 0xa5, 0xd9, 0x97, 0x77, 0x63, 0x93, 0x6a, 0x4 }}
+ gDxeQncPlatformPolicyProtocolGuid = { 0x4b0165a9, 0x61d6, 0x4e23, { 0xa0, 0xb5, 0x3e, 0xc7, 0x9c, 0x2e, 0x30, 0xd5 }}
+ gEfiSmmRuntimeProtocolGuid = { 0xa56897a1, 0xa77f, 0x4600, { 0x84, 0xdb, 0x22, 0xb0, 0xa8, 0x1, 0xfa, 0x9a } }
+
+ #
+ # South Cluster
+ #
+ gEfiSDHostIoProtocolGuid = {0xb63f8ec7, 0xa9c9, 0x4472, {0xa4, 0xc0, 0x4d, 0x8b, 0xf3, 0x65, 0xcc, 0x51}}
+ gEfiI2CHcProtocolGuid = {0x855b7d58, 0x874b, 0x47eb, { 0xa5, 0xcf, 0x98, 0xed, 0xac, 0x80, 0x67, 0x96 }}
+
+################################################################################
+#
+# PCD Declarations section - list of all PCDs Declared by this Package
+# Only this package should be providing the
+# declaration, other packages should not.
+#
+################################################################################
+
+[PcdsFeatureFlag]
+ #
+ # North Cluster
+ #
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddressFixed|TRUE|BOOLEAN|0x10000001
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdUseAcpiTimerInSmartTimer|TRUE|BOOLEAN|0x10000002
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciexpressHotplugEnabled|TRUE|BOOLEAN|0x10000003
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRmuDmaLock|FALSE|BOOLEAN|0x10000004
+
+ #
+ # South Cluster
+ #
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartEnable|TRUE|BOOLEAN|0x10000001
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartUseMmio|TRUE|BOOLEAN|0x10000002
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdEhciRecoveryEnabled|FALSE|BOOLEAN|0x10000003
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdI2CFastModeEnabled|FALSE|BOOLEAN|0x10000005
+
+ #
+ # Feature Flag equivalent to linux SDHCI_QUIRK_NO_HISPD_BIT to stop
+ # setting of SD HCI hi_spd_en bit in HOST_CTL register.
+ #
+ # Quark SIGHTING #4930600, Alway TRUE ie high speed enable bit must never
+ # be set so we stay within SD interface Setup/Hold time.
+ #
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdSdHciQuirkNoHiSpd|TRUE|BOOLEAN|0x10000004
+
+[PcdsFixedAtBuild]
+ #
+ # North Cluster
+ #
+
+ # Values of Io Port Base Address, MMIO base address and space size.
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress|0x1000|UINT16|0x10000200
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress|0x1010|UINT16|0x10000201
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoLVL2|0x1014|UINT16|0x10000202
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress|0x1080|UINT16|0x10000205
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress|0x1100|UINT16|0x10000206
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress|0x1040|UINT16|0x10000207
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSpiDmaIoBaseAddress|0x1020|UINT16|0x10000208
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdWdtbaIoBaseAddress|0x1140|UINT16|0x10000209
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress|0xFED1C000|UINT64|0x1000020B
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicBaseAddress|0xFEC00000|UINT64|0x1000020C
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicSize|0x1000|UINT64|0x1000020D
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioSize|0x4000|UINT64|0x1000020E
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciExpressSize|0x02000000|UINT64|0x1000020F
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetBaseAddress|0xFED00000|UINT64|0x10000210
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetSize|0x400|UINT64|0x10000211
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdTSegSize|0x200000|UINT32|0x10000212
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeIoBase|0x2000|UINT16|0x10000214
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeIoSize|0xE000|UINT16|0x10000215
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory32Base|0x90000000|UINT32|0x1000021B
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory32Size|0x20000000|UINT32|0x1000021C
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory64Base|0xB0000000|UINT64|0x1000021D
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory64Size|0x30000000|UINT64|0x1000021E
+
+ # Values for programming Interrupt Route Configuration Registers:
+ # Indicates which interrupt routing is connected to the INTA/B/C/D pins reported in the
+ # "DxIP" register fields. This will be the internal routing, the device interrupt is connected
+ # to the interrupt controller.
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent0IR|0x0000|UINT16|0x10000223
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent1IR|0x7654|UINT16|0x10000224
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent2IR|0x0000|UINT16|0x10000225
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent3IR|0x3210|UINT16|0x10000226
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort|0xb2|UINT16|0x10000232
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmDataPort|0xb3|UINT16|0x10000233
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationData|0x55|UINT8|0x10000234
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPlatformSmbusAddrNum|0x0|UINT32|0x10000235
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPlatformSmbusAddrTable|0x0|UINT64|0x10000236
+
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdESramMemorySize|0x00080000|UINT32|0x10000240
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables|0x03|UINT32|0x10000237
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPcieRootPortConfiguration|{0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00}|VOID*|0x10000239
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkMicrocodeFile |{ 0x8B, 0xEA, 0x5E, 0xD7, 0xD2, 0x23, 0xD4, 0x4E, 0xBC, 0x4F, 0x57, 0x51, 0xD4, 0xA1, 0x8D, 0xCF }|VOID*|0x1000023A
+
+ #
+ # South Cluster
+ #
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartMmioBase|0xA0019000|UINT64|0x20000002
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartIoBase|0x5098|UINT16|0x20000003
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartLineControl|0x03|UINT8|0x20000004
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohI2cMmioBase|0xA001F000|UINT64|0x20000005
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiP2PMemoryBaseAddress|0xA0000000|UINT32|0x20000006
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiQNCUsbControllerMemoryBaseAddress|0xA0010000|UINT32|0x20000007
+
+ # IOH Uart Clock Frequency 44.2368Mhz.
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartClkFreq|44236800|UINT32|0x20000012
+
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartBusNumber|0x00|UINT8|0x20000013
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartDevNumber|0x14|UINT8|0x20000014
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartFunctionNumber|0x5|UINT8|0x20000001
+
+[PcdsDynamic]
+ #
+ # North Cluster
+ #
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQncS3CodeInLockBoxAddress|0|UINT64|0x30000026
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdQncS3CodeInLockBoxSize|0|UINT64|0x30000027
+
+[PcdsDynamic, PcdsDynamicEx]
+ #
+ # North Cluster
+ #
+
+[PcdsPatchableInModule]
diff --git a/QuarkSocPkg/QuarkSocPkg.dsc b/QuarkSocPkg/QuarkSocPkg.dsc
new file mode 100755
index 0000000..77b38fa
--- /dev/null
+++ b/QuarkSocPkg/QuarkSocPkg.dsc
@@ -0,0 +1,264 @@
+## @file
+# INTEL Quark SoC Module Package Reference Implementations
+#
+# This DSC file is used for Package Level build.
+#
+# This Module provides FRAMEWORK reference implementation for INTEL Quark SoC.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = QuarkSocPkg
+ PLATFORM_GUID = 5F9864F4-EAFB-4ded-A41A-CA501EE50502
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/QuarkSocPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this
+# Platform.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+[LibraryClasses]
+ #
+ # Entry point
+ #
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ #
+ # Basic
+ #
+ BaseLib|QuarkSocPkg/Override/MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+!if $(CFG_SOURCE_DEBUG) == 1
+ PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+!else
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+!endif
+ #
+ # UEFI & PI
+ #
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+ #
+ # Framework
+ #
+ S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+ S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf
+ S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf
+ #
+ # Generic Modules
+ #
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ RecoveryOemHookLib|QuarkSocPkg/Override/MdePkg/Library/BaseRecoveryOemHookLibNull/BaseRecoveryOemHookLibNull.inf
+
+ #
+ # CPU
+ #
+ MtrrLib|QuarkSocPkg/Override/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ #
+ # Quark North Cluster
+ #
+ SmmLib|QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf
+ SmbusLib|QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf
+ TimerLib|QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCAcpiTimerLib/IntelQNCAcpiTimerLib.inf
+ ResetSystemLib|QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf
+ IntelQNCLib|QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf
+ QNCAccessLib|QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf
+ #
+ # Quark South Cluster
+ #
+ IohLib|QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf
+ SerialPortLib|QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.inf
+ #
+ # Misc
+ #
+ DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
+!else
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+!endif
+
+[LibraryClasses.IA32.PEIM,LibraryClasses.IA32.PEI_CORE]
+ #
+ # SEC and PEI phase common
+ #
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+ PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+
+[LibraryClasses.IA32.SEC]
+ #
+ # SEC specific phase
+ #
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+
+[LibraryClasses.IA32]
+ #
+ # DXE phase common
+ #
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+!if $(CFG_SOURCE_DEBUG) == 1
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+
+[LibraryClasses.IA32.DXE_SMM_DRIVER]
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+!if $(CFG_SOURCE_DEBUG) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
+!endif
+
+[LibraryClasses.IA32.SMM_CORE]
+ ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
+
+[LibraryClasses.IA32.DXE_RUNTIME_DRIVER]
+ ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+
+[LibraryClasses.IA32.UEFI_DRIVER,LibraryClasses.IA32.UEFI_APPLICATION]
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsFixedAtBuild]
+
+[PcdsFeatureFlag]
+
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault.common.DEFAULT]
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+# into firmware volume images. This section is just a list of modules to compile from
+# source into UEFI-compliant binaries.
+# It is the FDF file that contains information on combining binary files into firmware
+# volume images, whose concept is beyond UEFI and is described in PI specification.
+# Binary modules do not need to be listed in this section, as they should be
+# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
+# Logo (Logo.bmp), and etc.
+# There may also be modules listed in this section that are not required in the FDF file,
+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+# generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
+
+[Components]
+ QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf
+ QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf
+ QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpiRuntime.inf {
+ <LibraryClasses>
+ PciExpressLib|MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf
+ }
+ QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpiSmm.inf
+ QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmRuntime/SmmRuntime.inf
+ QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf
+
+ QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf
+ QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf
+ QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/SerialDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf
+ QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2CDxe.inf
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/CommonHeader.h b/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/CommonHeader.h
new file mode 100644
index 0000000..2c5901d
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/CommonHeader.h
@@ -0,0 +1,70 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+//
+// The package level header files this module uses
+//
+#include <Base.h>
+
+//
+// The protocols, PPI and GUID definitions for this module
+//
+#include <Protocol/PciIo.h>
+#include <Protocol/I2CHc.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+#include <Library/IohLib.h>
+#include <IndustryStandard/Pci.h>
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2C.c b/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2C.c
new file mode 100644
index 0000000..c8d13f7
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2C.c
@@ -0,0 +1,962 @@
+/** @file
+ I2C DXE Driver for Quark I2C Controller.
+ Follows I2C Controller setup instructions as detailed in
+ Quark DataSheet (doc id: 329676) Section 19.1/19.1.3.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "CommonHeader.h"
+
+#include "I2C.h"
+
+//
+// Interface definition of I2C Host Controller Protocol.
+//
+EFI_I2C_HC_PROTOCOL mI2CbusHc = {
+ I2CWriteByte,
+ I2CReadByte,
+ I2CWriteMultipleByte,
+ I2CReadMultipleByte
+};
+
+//
+// Handle to install I2C Controller protocol.
+//
+
+STATIC EFI_HANDLE mHandle = NULL;
+STATIC UINT16 mSaveCmdReg;
+STATIC UINT32 mSaveBar0Reg;
+
+/**
+ The Called on Protocol Service Entry.
+
+ @return None.
+
+**/
+STATIC
+VOID
+ServiceEntry (
+ VOID
+ )
+{
+ mSaveBar0Reg = IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0);
+ if ((mSaveBar0Reg & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) {
+
+ IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) =
+ FixedPcdGet32 (PcdIohI2cMmioBase) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK;
+
+ //
+ // also Save Cmd Register, Setup by InitializeInternal later during xfers.
+ //
+ mSaveCmdReg = IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD);
+ }
+}
+
+/**
+ The Called on Protocol Service Entry.
+
+ @return None.
+
+**/
+STATIC
+VOID
+ServiceExit (
+ VOID
+ )
+{
+ if ((mSaveBar0Reg & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) {
+ IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD) = mSaveCmdReg;
+ IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) = mSaveBar0Reg;
+ }
+}
+
+
+/**
+ The GetI2CIoPortBaseAddress() function gets IO port base address of I2C Controller.
+
+ Always reads PCI configuration space to get MMIO base address of I2C Controller.
+
+ @return The IO port base address of I2C controller.
+
+**/
+UINTN
+GetI2CIoPortBaseAddress (
+ VOID
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+
+ //
+ // Get I2C Memory Mapped registers base address.
+ //
+ I2CIoPortBaseAddress = IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0);
+
+ //
+ // Make sure that the IO port base address has been properly set.
+ //
+ ASSERT (I2CIoPortBaseAddress != 0);
+ ASSERT (I2CIoPortBaseAddress != 0xFF);
+
+ return I2CIoPortBaseAddress;
+}
+
+
+/**
+ The EnableI2CMmioSpace() function enables access to I2C MMIO space.
+
+**/
+VOID
+EnableI2CMmioSpace (
+ VOID
+ )
+{
+ UINT8 PciCmd;
+
+ //
+ // Read PCICMD. Bus=0, Dev=0, Func=0, Reg=0x4
+ //
+ PciCmd = IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD);
+
+ //
+ // Enable Bus Master(Bit2), MMIO Space(Bit1) & I/O Space(Bit0)
+ //
+ PciCmd |= 0x7;
+ IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD) = PciCmd;
+
+}
+
+
+/**
+ The DisableI2CController() functions disables I2C Controller.
+
+ @retval EFI_SUCCESS I2C Controller disabled successfully.
+
+ @retval EFI_DEVICE_ERROR I2C Controller could not be disabled.
+
+**/
+EFI_STATUS
+DisableI2CController (
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+ UINT32 Addr;
+ UINT32 Data;
+ UINT8 PollCount;
+
+ PollCount = 0;
+
+ //
+ // Get I2C Memory Mapped registers base address.
+ //
+ I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
+
+ //
+ // Disable the I2C Controller by setting IC_ENABLE.ENABLE to zero
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= ~B_I2C_REG_ENABLE;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Read the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled
+ //
+ Data = 0xFF;
+ Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE_STATUS;
+ Data = *((volatile UINT32 *) (UINTN)(Addr)) & I2C_REG_ENABLE_STATUS;
+
+ if (Data == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Poll the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled, until timeout (TI2C_POLL*MAX_T_POLL_COUNT).
+ //
+PollIcEn:
+ PollCount++;
+ if (PollCount >= MAX_T_POLL_COUNT) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ gBS->Stall(TI2C_POLL);
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= I2C_REG_ENABLE_STATUS;
+ if (Data == 0) {
+ return EFI_SUCCESS;
+ } else {
+ goto PollIcEn;
+ }
+ }
+
+}
+
+/**
+ The EnableI2CController() function enables the I2C Controller.
+
+**/
+VOID
+EnableI2CController (
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+ UINT32 Addr;
+ UINT32 Data;
+
+ //
+ // Get I2C Memory Mapped registers base address.
+ //
+ I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
+
+ //
+ // Enable the I2C Controller by setting IC_ENABLE.ENABLE to 1
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data |= B_I2C_REG_ENABLE;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+}
+
+/**
+ The WaitForStopDet() function waits until I2C STOP Condition occurs,
+ indicating transfer completion.
+
+**/
+VOID
+WaitForStopDet (
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+ UINT32 Addr;
+ UINT32 Data;
+
+ //
+ // Get I2C Memory Mapped registers base address.
+ //
+ I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
+
+ //
+ // Wait for STOP Detect.
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
+
+PollStopDet:
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= I2C_REG_RAW_INTR_STAT_STOP_DET;
+ if (Data == 0) {
+ gBS->Stall(TI2C_POLL);
+ goto PollStopDet;
+ }
+
+}
+
+/**
+
+ The InitializeInternal() function initialises internal I2C Controller
+ register values that are commonly required for I2C Write and Read transfers.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+InitializeInternal (
+ IN EFI_I2C_ADDR_MODE AddrMode
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+ UINTN Addr;
+ UINT32 Data;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Enable access to I2C Controller MMIO space.
+ //
+ EnableI2CMmioSpace ();
+
+ //
+ // Disable I2C Controller initially
+ //
+ Status = DisableI2CController ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get I2C Memory Mapped registers base address.
+ //
+ I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
+
+ //
+ // Clear START_DET
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_CLR_START_DET;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= ~B_I2C_REG_CLR_START_DET;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Clear STOP_DET
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_CLR_STOP_DET;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= ~B_I2C_REG_CLR_STOP_DET;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Set addressing mode to user defined (7 or 10 bit) and
+ // speed mode to that defined by PCD (standard mode default).
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_CON;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ // Set Addressing Mode
+ if (AddrMode == EfiI2CSevenBitAddrMode) {
+ Data &= ~B_I2C_REG_CON_10BITADD_MASTER;
+ } else {
+ Data |= B_I2C_REG_CON_10BITADD_MASTER;
+ }
+ // Set Speed Mode
+ Data &= ~B_I2C_REG_CON_SPEED;
+ if (FeaturePcdGet (PcdI2CFastModeEnabled)) {
+ Data |= BIT2;
+ } else {
+ Data |= BIT1;
+ }
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+
+ return Status;
+
+}
+
+/**
+
+ The WriteByte() function provides a standard way to execute a
+ standard single byte write to an IC2 device (without accessing
+ sub-addresses), as defined in the I2C Specification.
+
+ @param I2CAddress I2C Slave device address
+ @param Value The 8-bit value to write.
+ @param Status Return status for the executed command (EFI_SUCCESS or EFI_DEVICE_ERROR).
+ This is an optional parameter and may be NULL.
+
+ @return Data written to I2C Slave device, as read from I2C Data CMD register.
+
+**/
+UINT8
+EFIAPI
+WriteByte (
+ IN UINTN I2CAddress,
+ IN UINT8 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+ UINTN Addr;
+ UINT32 Data;
+ UINT8 ReturnData;
+
+ //
+ // Get I2C Memory Mapped registers base address
+ //
+ I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
+
+ //
+ // Write to the IC_TAR register the address of the slave device to be addressed
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= ~B_I2C_REG_TAR;
+ Data |= I2CAddress;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Enable the I2C Controller
+ //
+ EnableI2CController ();
+
+ //
+ // Write the data and transfer direction to the IC_DATA_CMD register.
+ // Also specify that transfer should be terminated by STOP condition.
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= 0xFFFFFF00;
+ Data |= (UINT8)Value;
+ Data &= ~B_I2C_REG_DATA_CMD_RW;
+ Data |= B_I2C_REG_DATA_CMD_STOP;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Wait for transfer completion.
+ //
+ WaitForStopDet ();
+
+ //
+ // Return write data byte from TX/RX buffer (IC_DATA_CMD[7:0]).
+ //
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= 0x000000FF;
+ ReturnData = (UINT8)Data;
+
+ return ReturnData;
+
+}
+
+/**
+
+ The ReadByte() function provides a standard way to execute a
+ standard single byte read to an IC2 device (without accessing
+ sub-addresses), as defined in the I2C Specification.
+
+ @param I2CAddress I2C Slave device address
+ @param Status Return status for the executed command (EFI_SUCCESS or EFI_DEVICE_ERROR).
+ This is an optional parameter and may be NULL.
+
+ @return Data read from the I2C Slave device.
+
+**/
+UINT8
+EFIAPI
+ReadByte (
+ IN UINTN I2CAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+ UINTN Addr;
+ UINT32 Data;
+ UINT8 ReturnData;
+
+ //
+ // Get I2C Memory Mapped registers base address.
+ //
+ I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
+
+ //
+ // Write to the IC_TAR register the address of the slave device to be addressed
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= ~B_I2C_REG_TAR;
+ Data |= I2CAddress;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Enable the I2C Controller
+ //
+ EnableI2CController ();
+
+ //
+ // Write transfer direction to the IC_DATA_CMD register and
+ // specify that transfer should be terminated by STOP condition.
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= 0xFFFFFF00;
+ Data |= B_I2C_REG_DATA_CMD_RW;
+ Data |= B_I2C_REG_DATA_CMD_STOP;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Wait for transfer completion
+ //
+ WaitForStopDet ();
+
+ //
+ // Obtain and return read data byte from RX buffer (IC_DATA_CMD[7:0]).
+ //
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= 0x000000FF;
+ ReturnData = (UINT8)Data;
+
+ return ReturnData;
+
+}
+
+/**
+
+ The WriteMultipleByte() function provides a standard way to execute
+ multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
+ when writing block of data), as defined in the I2C Specification.
+
+ @param I2CAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param Buffer Contains the value of byte to be written to the
+ I2C slave device.
+
+ @param Length No. of bytes to be written.
+
+ @param Status Return status for the executed command (EFI_SUCCESS or EFI_DEVICE_ERROR).
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+WriteMultipleByte (
+ IN UINTN I2CAddress,
+ IN UINT8 *WriteBuffer,
+ IN UINTN Length,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+ UINTN Index;
+ UINTN Addr;
+ UINT32 Data;
+
+ I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
+
+ //
+ // Write to the IC_TAR register the address of the slave device to be addressed
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= ~B_I2C_REG_TAR;
+ Data |= I2CAddress;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Enable the I2C Controller
+ //
+ EnableI2CController ();
+
+ //
+ // Write the data and transfer direction to the IC_DATA_CMD register.
+ // Also specify that transfer should be terminated by STOP condition.
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
+ for (Index = 0; Index < Length; Index++) {
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= 0xFFFFFF00;
+ Data |= (UINT8)WriteBuffer[Index];
+ Data &= ~B_I2C_REG_DATA_CMD_RW;
+ if (Index == (Length-1)) {
+ Data |= B_I2C_REG_DATA_CMD_STOP;
+ }
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+ }
+
+ //
+ // Wait for transfer completion
+ //
+ WaitForStopDet ();
+
+}
+
+/**
+
+ The ReadMultipleByte() function provides a standard way to execute
+ multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
+ when reading block of data), as defined in the I2C Specification (I2C combined
+ write/read protocol).
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param Buffer Contains the value of byte data written or read from the
+ I2C slave device.
+
+ @param WriteLength No. of bytes to be written. In this case data
+ written typically contains sub-address or sub-addresses
+ in Hi-Lo format, that need to be read (I2C combined
+ write/read protocol).
+
+ @param ReadLength No. of bytes to be read. I
+
+ @param ReadLength No. of bytes to be read from I2C slave device.
+ need to be read.
+
+ @param Buffer Contains the value of byte data read from the
+ I2C slave device.
+
+ @param Status Return status for the executed command (EFI_SUCCESS or EFI_DEVICE_ERROR).
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+ReadMultipleByte (
+ IN UINTN I2CAddress,
+ IN OUT UINT8 *Buffer,
+ IN UINTN WriteLength,
+ IN UINTN ReadLength,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ UINTN I2CIoPortBaseAddress;
+ UINTN Index;
+ UINTN Addr;
+ UINT32 Data;
+ UINT8 PollCount;
+
+ I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
+
+ //
+ // Write to the IC_TAR register the address of the slave device to be addressed
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= ~B_I2C_REG_TAR;
+ Data |= I2CAddress;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+
+ //
+ // Enable the I2C Controller
+ //
+ EnableI2CController ();
+
+ //
+ // Write the data (sub-addresses) to the IC_DATA_CMD register.
+ //
+ Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
+ for (Index = 0; Index < WriteLength; Index++) {
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= 0xFFFFFF00;
+ Data |= (UINT8)Buffer[Index];
+ Data &= ~B_I2C_REG_DATA_CMD_RW;
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+ }
+
+ //
+ // Issue Read Transfers for each byte (Restart issued when write/read bit changed).
+ //
+ for (Index = 0; Index < ReadLength; Index++) {
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data |= B_I2C_REG_DATA_CMD_RW;
+ // Issue a STOP for last read transfer.
+ if (Index == (ReadLength-1)) {
+ Data |= B_I2C_REG_DATA_CMD_STOP;
+ }
+ *((volatile UINT32 *) (UINTN)(Addr)) = Data;
+ }
+
+ //
+ // Wait for STOP condition.
+ //
+ WaitForStopDet ();
+
+ //
+ // Poll Receive FIFO Buffer Level register until valid (upto MAX_T_POLL_COUNT times).
+ //
+ Data = 0;
+ PollCount = 0;
+ Addr = I2CIoPortBaseAddress + I2C_REG_RXFLR;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ while ((Data != ReadLength) && (PollCount < MAX_T_POLL_COUNT)) {
+ gBS->Stall(TI2C_POLL);
+ PollCount++;
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ }
+
+ //
+ // If receive buffer valid output data, otherwise return device error.
+ //
+ if (PollCount == MAX_T_POLL_COUNT) {
+ *Status = EFI_DEVICE_ERROR;
+ } else {
+ *Status = EFI_SUCCESS;
+ Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
+ for (Index = 0; Index < ReadLength; Index++) {
+ Data = *((volatile UINT32 *) (UINTN)(Addr));
+ Data &= 0x000000FF;
+ *(Buffer+Index) = (UINT8)Data;
+ }
+ }
+
+}
+
+
+/**
+
+ The I2CWriteByte() function is a wrapper function for the WriteByte function.
+ Provides a standard way to execute a standard single byte write to an IC2 device
+ (without accessing sub-addresses), as defined in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be written.
+
+ @param Buffer Contains the value of byte data to execute to the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+EFIAPI
+I2CWriteByte (
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN I2CAddress;
+
+ ServiceEntry ();
+
+ Status = EFI_SUCCESS;
+
+ I2CAddress = SlaveAddress.I2CDeviceAddress;
+
+ Status = InitializeInternal (AddrMode);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ WriteByte (I2CAddress, *(UINT8 *) Buffer, &Status);
+
+ ServiceExit ();
+ return Status;
+}
+
+/**
+
+ The I2CReadByte() function is a wrapper function for the ReadByte function.
+ Provides a standard way to execute a standard single byte read to an IC2 device
+ (without accessing sub-addresses), as defined in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be read.
+
+ @param Buffer Contains the value of byte data read from the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+EFIAPI
+I2CReadByte (
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN I2CAddress;
+
+ ServiceEntry ();
+
+ Status = EFI_SUCCESS;
+
+ I2CAddress = SlaveAddress.I2CDeviceAddress;
+
+ Status = InitializeInternal (AddrMode);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ *(UINT8 *) Buffer = ReadByte (I2CAddress, &Status);
+
+ ServiceExit ();
+ return Status;
+}
+
+/**
+
+ The I2CWriteMultipleByte() function is a wrapper function for the WriteMultipleByte() function.
+ Provides a standard way to execute multiple byte writes to an IC2 device
+ (e.g. when accessing sub-addresses or writing block of data), as defined
+ in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be written.
+
+ @param Buffer Contains the value of byte to be written to the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+EFIAPI
+I2CWriteMultipleByte (
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN I2CAddress;
+
+ ServiceEntry ();
+ Status = EFI_SUCCESS;
+
+ I2CAddress = SlaveAddress.I2CDeviceAddress;
+
+ Status = InitializeInternal (AddrMode);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ WriteMultipleByte (I2CAddress, Buffer, (*Length), &Status);
+
+ ServiceExit ();
+ return Status;
+}
+
+/**
+
+ The I2CReadMultipleByte() function is a wrapper function for the ReadMultipleByte() function.
+ Provides a standard way to execute multiple byte writes to an IC2 device
+ (e.g. when accessing sub-addresses or when reading block of data), as defined
+ in the I2C Specification (I2C combined write/read protocol).
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param WriteLength No. of bytes to be written. In this case data
+ written typically contains sub-address or sub-addresses
+ in Hi-Lo format, that need to be read (I2C combined
+ write/read protocol).
+
+ @param ReadLength No. of bytes to be read from I2C slave device.
+ need to be read.
+
+ @param Buffer Contains the value of byte data read from the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+EFIAPI
+I2CReadMultipleByte (
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *WriteLength,
+ IN UINTN *ReadLength,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN I2CAddress;
+
+ ServiceEntry ();
+
+ Status = EFI_SUCCESS;
+
+ I2CAddress = SlaveAddress.I2CDeviceAddress;
+
+ Status = InitializeInternal (AddrMode);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ ReadMultipleByte(I2CAddress, Buffer, (*WriteLength), (*ReadLength), &Status);
+
+ ServiceExit ();
+ return Status;
+}
+
+/**
+ Entry point to the DXE Driver that produces the I2C Controller Protocol.
+
+ @param ImageHandle ImageHandle of the loaded driver.
+ @param SystemTable Pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point of I2C DXE driver is executed successfully.
+ @retval !EFI_SUCESS Some error occurs in the entry point of I2C DXE driver.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeI2C (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ Status = EFI_SUCCESS;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiI2CHcProtocolGuid,
+ &mI2CbusHc,
+ NULL
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2C.h b/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2C.h
new file mode 100644
index 0000000..a8ddda3
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2C.h
@@ -0,0 +1,405 @@
+/** @file
+ Provides definition of entry point to the DXE Driver that produces the
+ I2C Controller Protocol and definition of protocol functions.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#ifndef _I2C_H_
+#define _I2C_H_
+
+#include <IohAccess.h>
+#include <IohCommonDefinitions.h>
+#include "CommonHeader.h"
+#include "I2CRegs.h"
+
+//
+// Constants that define I2C Controller timeout and max. polling time.
+//
+#define MAX_T_POLL_COUNT 100
+#define TI2C_POLL 25 // microseconds
+
+/**
+ The GetI2CIoPortBaseAddress() function gets IO port base address of I2C Controller.
+
+ Always reads PCI configuration space to get MMIO base address of I2C Controller.
+
+ @return The IO port base address of I2C controller.
+
+**/
+UINTN
+GetI2CIoPortBaseAddress (
+ VOID
+ );
+
+
+/**
+ The EnableI2CMmioSpace() function enables access to I2C MMIO space.
+
+**/
+VOID
+EnableI2CMmioSpace (
+ VOID
+ );
+
+
+/**
+ The DisableI2CController() functions disables I2C Controller.
+
+ @retval EFI_SUCCESS I2C Controller disabled successfully.
+
+ @retval EFI_DEVICE_ERROR I2C Controller could not be disabled.
+
+**/
+EFI_STATUS
+DisableI2CController (
+ VOID
+ );
+
+
+/**
+ The EnableI2CController() function enables the I2C Controller.
+
+**/
+VOID
+EnableI2CController (
+ VOID
+ );
+
+
+/**
+ The WaitForStopDet() function waits until I2C STOP Condition occurs,
+ indicating transfer completion.
+
+**/
+VOID
+WaitForStopDet (
+ );
+
+
+/**
+
+ The InitializeInternal() function initialises internal I2C Controller
+ register values that are commonly required for I2C Write and Read transfers.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+InitializeInternal (
+ IN EFI_I2C_ADDR_MODE AddrMode
+ );
+
+
+/**
+
+ The WriteByte() function provides a standard way to execute a
+ standard single byte write to an IC2 device (without accessing
+ sub-addresses), as defined in the I2C Specification.
+
+ @param I2CAddress I2C Slave device address
+ @param Value The 8-bit value to write.
+ @param Status Return status for the executed command (EFI_SUCCESS or EFI_DEVICE_ERROR).
+ This is an optional parameter and may be NULL.
+
+ @return Data written to I2C Slave device, as read from I2C Data CMD register.
+
+**/
+UINT8
+EFIAPI
+WriteByte (
+ IN UINTN I2CAddress,
+ IN UINT8 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ );
+
+
+/**
+
+ The ReadByte() function provides a standard way to execute a
+ standard single byte read to an IC2 device (without accessing
+ sub-addresses), as defined in the I2C Specification.
+
+ @param I2CAddress I2C Slave device address
+ @param Status Return status for the executed command (EFI_SUCCESS or EFI_DEVICE_ERROR).
+ This is an optional parameter and may be NULL.
+
+ @return Data read from the I2C Slave device.
+
+**/
+UINT8
+EFIAPI
+ReadByte (
+ IN UINTN I2CAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ );
+
+
+/**
+
+ The WriteMultipleByte() function provides a standard way to execute
+ multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
+ when writing block of data), as defined in the I2C Specification.
+
+ @param I2CAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param Buffer Contains the value of byte to be written to the
+ I2C slave device.
+
+ @param Length No. of bytes to be written.
+
+ @param Status Return status for the executed command (EFI_SUCCESS or EFI_DEVICE_ERROR).
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+WriteMultipleByte (
+ IN UINTN I2CAddress,
+ IN UINT8 *WriteBuffer,
+ IN UINTN Length,
+ OUT RETURN_STATUS *Status OPTIONAL
+ );
+
+
+/**
+
+ The ReadMultipleByte() function provides a standard way to execute
+ multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
+ when reading block of data), as defined in the I2C Specification (I2C combined
+ write/read protocol).
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param Buffer Contains the value of byte data written or read from the
+ I2C slave device.
+
+ @param WriteLength No. of bytes to be written. In this case data
+ written typically contains sub-address or sub-addresses
+ in Hi-Lo format, that need to be read (I2C combined
+ write/read protocol).
+
+ @param ReadLength No. of bytes to be read.
+
+ @param ReadLength No. of bytes to be read from I2C slave device.
+ need to be read.
+
+ @param Buffer Contains the value of byte data read from the
+ I2C slave device.
+
+ @param Status Return status for the executed command (EFI_SUCCESS or EFI_DEVICE_ERROR).
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+ReadMultipleByte (
+ IN UINTN I2CAddress,
+ IN OUT UINT8 *Buffer,
+ IN UINTN WriteLength,
+ IN UINTN ReadLength,
+ OUT RETURN_STATUS *Status OPTIONAL
+ );
+
+
+/**
+
+ The I2CWriteByte() function is a wrapper function for the WriteByte() function.
+ Provides a standard way to execute a standard single byte write to an IC2 device
+ (without accessing sub-addresses), as defined in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be written.
+
+ @param Buffer Contains the value of byte data to execute to the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+I2CWriteByte (
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+ );
+
+
+/**
+
+ The I2CReadByte() function is a wrapper function for the ReadByte() function.
+ Provides a standard way to execute a standard single byte read to an IC2 device
+ (without accessing sub-addresses), as defined in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be read.
+
+ @param Buffer Contains the value of byte data read from the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+I2CReadByte (
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+ );
+
+
+/**
+
+ The I2CWriteMultipleByte() function is a wrapper function for the WriteMultipleByte() function.
+ Provides a standard way to execute multiple byte writes to an IC2 device (e.g. when accessing
+ sub-addresses or writing block of data), as defined in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be written.
+
+ @param Buffer Contains the value of byte to be written to the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+I2CWriteMultipleByte (
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+ );
+
+
+/**
+
+ The I2CReadMultipleByte() function is a wrapper function for the ReadMultipleByte function.
+ Provides a standard way to execute multiple byte writes to an IC2 device
+ (e.g. when accessing sub-addresses or when reading block of data), as defined
+ in the I2C Specification (I2C combined write/read protocol).
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param WriteLength No. of bytes to be written. In this case data
+ written typically contains sub-address or sub-addresses
+ in Hi-Lo format, that need to be read (I2C combined
+ write/read protocol).
+
+ @param ReadLength No. of bytes to be read from I2C slave device.
+ need to be read.
+
+ @param Buffer Contains the value of byte data read from the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+EFI_STATUS
+I2CReadMultipleByte (
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *WriteLength,
+ IN UINTN *ReadLength,
+ IN OUT VOID *Buffer
+ );
+
+
+/**
+ Entry point to the DXE Driver that produces the I2C Controller Protocol.
+
+ @param ImageHandle ImageHandle of the loaded driver.
+ @param SystemTable Pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point of I2C DXE driver is executed successfully.
+ @retval !EFI_SUCESS Some error occurs in the entry point of I2C DXE driver.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeI2C (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2CDxe.inf b/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2CDxe.inf
new file mode 100644
index 0000000..e910091
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/I2C/Dxe/I2CDxe.inf
@@ -0,0 +1,97 @@
+## @file
+# Component description file for Quark South Cluster I2C DXE driver.
+#
+# I2C DXE driver implement QuarkSCSocId related drivers, includes:
+# PciHostBridge, PciExpress, SmmAccess driver and LegacyRegion driver.
+#
+# This driver contains I2C bus access routines:
+# 1. I2C Read (byte, multi-byte)
+# 2. I2C Write (byte, multi-byte)
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = I2CDxe
+ FILE_GUID = 462d127a-c143-469e-8449-b6e36beb04a8
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeI2C
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CommonHeader.h
+ I2C.h
+ I2C.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ PciLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiLib
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+ UefiDriverEntryPoint
+ BaseLib
+ TimerLib
+ IoLib
+ IohLib
+
+[Guids]
+
+[Protocols]
+ gEfiI2CHcProtocolGuid
+
+[FeaturePcd]
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdI2CFastModeEnabled
+
+[FixedPcd]
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohI2cMmioBase
+
+[Pcd]
+
+[Depex]
+ TRUE
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/CEATA.h b/QuarkSocPkg/QuarkSouthCluster/Include/CEATA.h
new file mode 100644
index 0000000..86d3b02
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/CEATA.h
@@ -0,0 +1,138 @@
+/** @file
+
+ Header file for chipset CE-AT spec.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _CE_ATA_H
+#define _CE_ATA_H
+
+#pragma pack(1)
+
+
+#define DATA_UNIT_SIZE 512
+
+
+#define CMD60 60
+#define CMD61 61
+
+
+#define RW_MULTIPLE_REGISTER CMD60
+#define RW_MULTIPLE_BLOCK CMD61
+
+
+#define CE_ATA_SIG_CE 0xCE
+#define CE_ATA_SIG_AA 0xAA
+
+
+#define Reg_Features_Exp 01
+#define Reg_SectorCount_Exp 02
+#define Reg_LBALow_Exp 03
+#define Reg_LBAMid_Exp 04
+#define Reg_LBAHigh_Exp 05
+#define Reg_Control 06
+#define Reg_Features_Error 09
+#define Reg_SectorCount 10
+#define Reg_LBALow 11
+#define Reg_LBAMid 12
+#define Reg_LBAHigh 13
+#define Reg_Device_Head 14
+#define Reg_Command_Status 15
+
+#define Reg_scrTempC 0x80
+#define Reg_scrTempMaxP 0x84
+#define Reg_scrTempMinP 0x88
+#define Reg_scrStatus 0x8C
+#define Reg_scrReallocsA 0x90
+#define Reg_scrERetractsA 0x94
+#define Reg_scrCapabilities 0x98
+#define Reg_scrControl 0xC0
+
+
+
+typedef struct {
+ UINT8 Reserved0;
+ UINT8 Features_Exp;
+ UINT8 SectorCount_Exp;
+ UINT8 LBALow_Exp;
+ UINT8 LBAMid_Exp;
+ UINT8 LBAHigh_Exp;
+ UINT8 Control;
+ UINT8 Reserved1[2];
+ UINT8 Features_Error;
+ UINT8 SectorCount;
+ UINT8 LBALow;
+ UINT8 LBAMid;
+ UINT8 LBAHigh;
+ UINT8 Device_Head;
+ UINT8 Command_Status;
+}TASK_FILE;
+
+
+//
+//Reduced ATA command set
+//
+#define IDENTIFY_DEVICE 0xEC
+#define READ_DMA_EXT 0x25
+#define WRITE_DMA_EXT 0x35
+#define STANDBY_IMMEDIATE 0xE0
+#define FLUSH_CACHE_EXT 0xEA
+
+
+
+typedef struct {
+ UINT16 Reserved0[10];
+ UINT16 SerialNumber[10];
+ UINT16 Reserved1[3];
+ UINT16 FirmwareRevision[4];
+ UINT16 ModelNumber[20];
+ UINT16 Reserved2[33];
+ UINT16 MajorVersion;
+ UINT16 Reserved3[19];
+ UINT16 MaximumLBA[4];
+ UINT16 Reserved4[2];
+ UINT16 Sectorsize;
+ UINT16 Reserved5;
+ UINT16 DeviceGUID[4];
+ UINT16 Reserved6[94];
+ UINT16 Features;
+ UINT16 MaxWritesPerAddress;
+ UINT16 Reserved7[47];
+ UINT16 IntegrityWord;
+}IDENTIFY_DEVICE_DATA;
+
+
+
+
+
+#pragma pack()
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/I2CRegs.h b/QuarkSocPkg/QuarkSouthCluster/Include/I2CRegs.h
new file mode 100644
index 0000000..8429586
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/I2CRegs.h
@@ -0,0 +1,90 @@
+/** @file
+ Include file for I2C DXE Driver register definitions (PCIe config. space and memory space).
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _I2C_REGS_H_
+#define _I2C_REGS_H_
+
+//----------------------------------------------------------------------------
+// I2C Controller B:D:F
+//----------------------------------------------------------------------------
+#define I2C_Bus 0x00
+#define I2C_Device 0x15
+#define I2C_Func 0x02
+
+//----------------------------------------------------------------------------
+// Memory Mapped Registers
+//----------------------------------------------------------------------------
+#define I2C_REG_CON 0x00 // Control Register
+#define B_I2C_REG_CON_SPEED (BIT2+BIT1) // standard mode (01) or fast mode (10)
+#define B_I2C_REG_CON_10BITADD_MASTER (BIT4) // 7-bit addressing (0) or 10-bit addressing (1)
+#define I2C_REG_TAR 0x04 // Master Target Address Register
+#define B_I2C_REG_TAR (BIT9+BIT8+BIT7+BIT6+BIT5+BIT4+BIT3+BIT2+BIT1+BIT0) // Master Target Address bits
+#define I2C_REG_DATA_CMD 0x10 // Data Buffer and Command Register
+#define B_I2C_REG_DATA_CMD_RW (BIT8) // Data Buffer and Command Register Read/Write bit
+#define B_I2C_REG_DATA_CMD_STOP (BIT9) // Data Buffer and Command Register STOP bit
+#define B_I2C_REG_DATA_CMD_RESTART (BIT10) // Data Buffer and Command Register RESTART bit
+#define I2C_REG_SS_SCL_HCNT 0x14 // Standard Speed Clock SCL High Count Register
+#define I2C_REG_SS_SCL_LCNT 0x18 // Standard Speed Clock SCL Low Count Register
+#define I2C_REG_FS_SCL_HCNT 0x1C // Fast Speed Clock SCL High Count Register
+#define I2C_REG_FS_SCL_LCNT 0x20 // Fast Speed Clock SCL Low Count Register
+#define I2C_REG_INTR_STAT 0x2C // Interrupt Status Register
+#define B_I2C_REG_INTR_STAT_STOP_DET (BIT9) // Interrupt Status Register STOP_DET signal status
+#define I2C_REG_INTR_MASK 0x30 // Interrupt Status Mask Register
+#define I2C_REG_RAW_INTR_STAT 0x34 // Raw Interrupt Status Register
+#define I2C_REG_RAW_INTR_STAT_STOP_DET (BIT9) // Raw Interrupt Status Register STOP_DET signal status
+#define I2C_REG_RX_TL 0x38 // Receive FIFO Threshold Level Register
+#define I2C_REG_TX_TL 0x3C // Transmit FIFO Threshold Level Register
+#define I2C_REG_CLR_INT 0x40 // Clear Combined and Individual Interrupt Register
+#define I2C_REG_CLR_RX_UNDER 0x44 // Clear RX Under Interrupt Register
+#define I2C_REG_CLR_RX_OVER 0x48 // Clear RX Over Interrupt Register
+#define I2C_REG_CLR_TX_OVER 0x4C // Clear TX Over Interrupt Register
+#define I2C_REG_CLR_RD_REQ 0x50 // Clear RD REQ Interrupt Register
+#define I2C_REG_CLR_TX_ABRT 0x54 // Clear TX ABRT Interrupt Register
+#define I2C_REG_CLR_ACTIVITY 0x5C // Clear Activity Interrupt Register
+#define I2C_REG_CLR_STOP_DET 0x60 // Clear STOP DET Interrupt Register
+#define B_I2C_REG_CLR_STOP_DET (BIT0) // Clear STOP DET Interrupt Register
+#define I2C_REG_CLR_START_DET 0x64 // Clear START DET Interrupt Register
+#define B_I2C_REG_CLR_START_DET (BIT0) // Clear START DET Interrupt Register
+#define I2C_REG_ENABLE 0x6C // Enable Register
+#define B_I2C_REG_ENABLE (BIT0) // Enable (1) or disable (0) I2C Controller
+#define I2C_REG_STATUS 0x70 // Status Register
+#define I2C_REG_TXFLR 0x74 // Transmit FIFO Level Register
+#define B_I2C_REG_TXFLR (BIT3+BIT2+BIT1+BIT0) // Transmit FIFO Level Register bits
+#define I2C_REG_RXFLR 0x78 // Receive FIFO Level Register
+#define B_I2C_REG_RXFLR (BIT3+BIT2+BIT1+BIT0) // Receive FIFO Level Register bits
+#define I2C_REG_SDA_HOLD 0x7C // SDA HOLD Register
+#define I2C_REG_TX_ABRT_SOURCE 0x80 // Transmit Abort Source Register
+#define I2C_REG_ENABLE_STATUS 0x9C // Enable Status Register
+#define I2C_REG_FS_SPKLEN 0xA0 // SS and FS Spike Suppression Limit Register
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/Ioh.h b/QuarkSocPkg/QuarkSouthCluster/Include/Ioh.h
new file mode 100644
index 0000000..d1f8b88
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/Ioh.h
@@ -0,0 +1,277 @@
+/*++
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ Ioh.h
+
+Abstract:
+
+ Header file for QuarkSCSocId Ioh.
+
+Revision History:
+
+--*/
+#ifndef _IOH_H_
+#define _IOH_H_
+
+#ifndef BIT0
+#define BIT0 0x01
+#define BIT1 0x02
+#define BIT2 0x04
+#define BIT3 0x08
+#define BIT4 0x10
+#define BIT5 0x20
+#define BIT6 0x40
+#define BIT7 0x80
+#define BIT8 0x100
+#define BIT9 0x200
+#define BIT00 0x00000001
+#define BIT01 0x00000002
+#define BIT02 0x00000004
+#define BIT03 0x00000008
+#define BIT04 0x00000010
+#define BIT05 0x00000020
+#define BIT06 0x00000040
+#define BIT07 0x00000080
+#define BIT08 0x00000100
+#define BIT09 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#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
+#endif
+
+#define IOH_PCI_CFG_ADDRESS(bus,dev,func,reg) \
+ ((UINT32) ( (((UINTN)bus) << 24) + (((UINTN)dev) << 16) + \
+ (((UINTN)func) << 8) + ((UINTN)reg) ))& 0x00000000ffffffff
+
+//----------------------------------------------------------------------------
+
+#define INTEL_VENDOR_ID 0x8086 // Intel Vendor ID
+
+//----------------------------------------------------------------------------
+// Pci Configuration Map Register Offsets
+//----------------------------------------------------------------------------
+#define PCI_REG_VID 0x00 // Vendor ID Register
+#define PCI_REG_DID 0x02 // Device ID Register
+#define PCI_REG_PCICMD 0x04 // PCI Command Register
+#define PCI_REG_PCISTS 0x06 // PCI Status Register
+#define PCI_REG_RID 0x08 // PCI Revision ID Register
+#define PCI_REG_PI 0x09 // Programming Interface
+#define PCI_REG_SCC 0x0a // Sub Class Code Register
+#define PCI_REG_BCC 0x0b // Base Class Code Register
+#define PCI_REG_PMLT 0x0d // Primary Master Latnecy Timer
+#define PCI_REG_HDR 0x0e // Header Type Register
+#define PCI_REG_PBUS 0x18 // Primary Bus Number Register
+#define PCI_REG_SBUS 0x19 // Secondary Bus Number Register
+#define PCI_REG_SUBUS 0x1a // Subordinate Bus Number Register
+#define PCI_REG_SMLT 0x1b // Secondary Master Latnecy Timer
+#define PCI_REG_IOBASE 0x1c // I/O base Register
+#define PCI_REG_IOLIMIT 0x1d // I/O Limit Register
+#define PCI_REG_SECSTATUS 0x1e // Secondary Status Register
+#define PCI_REG_MEMBASE 0x20 // Memory Base Register
+#define PCI_REG_MEMLIMIT 0x22 // Memory Limit Register
+#define PCI_REG_PRE_MEMBASE 0x24 // Prefretchable memory Base register
+#define PCI_REG_PRE_MEMLIMIT 0x26 // Prefretchable memory Limit register
+#define PCI_REG_SVID0 0x2c // Subsystem Vendor ID low byte
+#define PCI_REG_SVID1 0x2d // Subsystem Vendor ID high byte
+#define PCI_REG_SID0 0x2e // Subsystem ID low byte
+#define PCI_REG_SID1 0x2f // Subsystem ID high byte
+#define PCI_REG_IOBASE_U 0x30 // I/O base Upper Register
+#define PCI_REG_IOLIMIT_U 0x32 // I/O Limit Upper Register
+#define PCI_REG_INTLINE 0x3c // Interrupt Line Register
+#define PCI_REG_BRIDGE_CNTL 0x3e // Bridge Control Register
+
+
+
+//---------------------------------------------------------------------------
+// QuarkSCSocId Packet Hub definitions
+//---------------------------------------------------------------------------
+
+#define PCIE_BRIDGE_VID_DID 0x88008086
+
+//---------------------------------------------------------------------------
+// Quark South Cluster USB definitions.
+//---------------------------------------------------------------------------
+
+#define IOH_USB_BUS_NUMBER 0x00
+#define IOH_USB_CONTROLLER_MMIO_RANGE 0x1000
+#define IOH_MAX_OHCI_USB_CONTROLLERS 1
+#define IOH_MAX_EHCI_USB_CONTROLLERS 1
+#define IOH_MAX_USBDEVICE_USB_CONTROLLERS 1
+
+#define R_IOH_USB_VENDOR_ID 0x00
+#define V_IOH_USB_VENDOR_ID INTEL_VENDOR_ID
+#define R_IOH_USB_DEVICE_ID 0x02
+#define R_IOH_USB_COMMAND 0x04
+#define B_IOH_USB_COMMAND_BME BIT2
+#define B_IOH_USB_COMMAND_MSE BIT1
+#define B_IOH_USB_COMMAND_ISE BIT0
+#define R_IOH_USB_MEMBAR 0x10
+#define B_IOH_USB_MEMBAR_ADDRESS_MASK 0xFFFFF000 // [31:12].
+#define R_IOH_USB_OHCI_HCCABAR 0x18
+
+//---------------------------------------------------------------------------
+// Quark South Cluster OHCI definitions
+//---------------------------------------------------------------------------
+#define IOH_USB_OHCI_DEVICE_NUMBER 0x14
+#define IOH_OHCI_FUNCTION_NUMBER 0x04
+
+//---------------------------------------------------------------------------
+// Quark South Cluster EHCI definitions
+//---------------------------------------------------------------------------
+#define IOH_USB_EHCI_DEVICE_NUMBER 0x14
+#define IOH_EHCI_FUNCTION_NUMBER 0x03
+
+//
+// EHCI memory mapped registers offset from memory BAR0.
+//
+#define R_IOH_EHCI_CAPLENGTH 0x00
+#define R_IOH_EHCI_INSNREG01 0x94
+#define B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP (16)
+#define B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_MASK (0xff << B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP)
+#define B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP (0)
+#define B_IOH_EHCI_INSNREG01_IN_THRESHOLD_MASK (0xff << B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP)
+
+//
+// EHCI memory mapped registers offset from memory BAR0 + Cap length value.
+//
+#define R_IOH_EHCI_CONFIGFLAGS 0x40
+
+//---------------------------------------------------------------------------
+// Quark South Cluster USB Device definitions
+//---------------------------------------------------------------------------
+#define IOH_USBDEVICE_DEVICE_NUMBER 0x14
+#define IOH_USBDEVICE_FUNCTION_NUMBER 0x02
+
+//
+// USB Device memory mapped registers offset from memory BAR0.
+//
+#define R_IOH_USBDEVICE_D_INTR_UDC_REG 0x40c
+#define R_IOH_USBDEVICE_D_INTR_MSK_UDC_REG 0x410
+#define B_IOH_USBDEVICE_D_INTR_MSK_UDC_REG_MASK1_MASK 0xff
+#define R_IOH_USBDEVICE_EP_INTR_UDC_REG 0x414
+#define R_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG 0x418
+#define B_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG_OUT_EP_MASK 0x000f0000
+#define B_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG_IN_EP_MASK 0x0000000f
+
+//---------------------------------------------------------------------------
+// Quark South Cluster 10/100 Mbps Ethernet Device definitions.
+//---------------------------------------------------------------------------
+#define IOH_MAC0_BUS_NUMBER 0x00
+#define IOH_MAC0_DEVICE_NUMBER 0x14
+#define IOH_MAC0_FUNCTION_NUMBER 0x06
+#define IOH_MAC1_BUS_NUMBER 0x00
+#define IOH_MAC1_DEVICE_NUMBER 0x14
+#define IOH_MAC1_FUNCTION_NUMBER 0x07
+
+//
+// MAC Device PCI config registers.
+//
+#define R_IOH_MAC_DEVICE_ID 0x02
+#define V_IOH_MAC_VENDOR_ID INTEL_VENDOR_ID
+#define R_IOH_MAC_DEVICE_ID 0x02
+#define V_IOH_MAC_DEVICE_ID 0x0937
+#define R_IOH_MAC_COMMAND 0x04
+#define B_IOH_MAC_COMMAND_BME BIT2
+#define B_IOH_MAC_COMMAND_MSE BIT1
+#define B_IOH_MAC_COMMAND_ISE BIT0
+#define R_IOH_MAC_MEMBAR 0x10
+#define B_IOH_MAC_MEMBAR_ADDRESS_MASK 0xFFFFF000
+
+//
+// LAN Device memory mapped registers offset from memory BAR0.
+//
+#define R_IOH_MAC_GMAC_REG_8 0x20
+#define B_IOH_MAC_USERVER_MASK 0x0000FF00
+#define B_IOH_MAC_SNPSVER_MASK 0x000000FF
+#define R_IOH_MAC_GMAC_REG_16 0x40
+#define B_IOH_MAC_ADDRHI_MASK 0x0000FFFF
+#define B_IOH_MAC_AE BIT31
+#define R_IOH_MAC_GMAC_REG_17 0x44
+#define B_IOH_MAC_ADDRLO_MASK 0xFFFFFFFF
+
+//---------------------------------------------------------------------------
+// Quark I2C / GPIO definitions
+//---------------------------------------------------------------------------
+#define IOH_I2C_GPIO_BUS_NUMBER 0x00
+#define IOH_I2C_GPIO_DEVICE_NUMBER 0x15
+#define IOH_I2C_GPIO_FUNCTION_NUMBER 0x02
+
+#define V_IOH_I2C_GPIO_VENDOR_ID INTEL_VENDOR_ID
+#define V_IOH_I2C_GPIO_DEVICE_ID 0x0934
+
+#define R_IOH_I2C_MEMBAR 0x10
+#define R_IOH_GPIO_MEMBAR 0x14
+#define B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK 0xFFFFF000 // [31:12].
+
+#define GPIO_SWPORTA_DR 0x00
+#define GPIO_SWPORTA_DDR 0x04
+#define GPIO_INTEN 0x30
+#define GPIO_INTMASK 0x34
+#define GPIO_INTTYPE_LEVEL 0x38
+#define GPIO_INT_POLARITY 0x3C
+#define GPIO_INTSTATUS 0x40
+#define GPIO_RAW_INTSTATUS 0x44
+#define GPIO_DEBOUNCE 0x48
+#define GPIO_PORTA_EOI 0x4C
+#define GPIO_EXT_PORTA 0x50
+#define GPIO_EXT_PORTB 0x54
+#define GPIO_LS_SYNC 0x60
+#define GPIO_CONFIG_REG2 0x70
+#define GPIO_CONFIG_REG1 0x74
+
+//---------------------------------------------------------------------------
+// Quark South Cluster UART definitions.
+//---------------------------------------------------------------------------
+
+#define R_IOH_UART_MEMBAR 0x10
+#define B_IOH_UART_MEMBAR_ADDRESS_MASK 0xFFFFF000 // [31:12].
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/IohAccess.h b/QuarkSocPkg/QuarkSouthCluster/Include/IohAccess.h
new file mode 100644
index 0000000..2e42ccb
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/IohAccess.h
@@ -0,0 +1,49 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ IohAccess.h
+
+Abstract:
+
+ Macros to simplify and abstract the interface to PCI configuration.
+
+--*/
+
+#ifndef _IOH_ACCESS_H_
+#define _IOH_ACCESS_H_
+
+#include "Ioh.h"
+#include "IohCommonDefinitions.h"
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/IohCommonDefinitions.h b/QuarkSocPkg/QuarkSouthCluster/Include/IohCommonDefinitions.h
new file mode 100644
index 0000000..dea7889
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/IohCommonDefinitions.h
@@ -0,0 +1,374 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Module Name:
+
+ IohCommonDefinitions.h
+
+Abstract:
+
+ This header file provides common definitions just for MCH using to avoid including extra module's file.
+
+--*/
+
+#ifndef _IOH_COMMON_DEFINITIONS_H_
+#define _IOH_COMMON_DEFINITIONS_H_
+
+//
+// PCI CONFIGURATION MAP REGISTER OFFSETS
+//
+#ifndef PCI_VID
+#define PCI_VID 0x0000 // Vendor ID Register
+#define PCI_DID 0x0002 // Device ID Register
+#define PCI_CMD 0x0004 // PCI Command Register
+#define PCI_STS 0x0006 // PCI Status Register
+#define PCI_RID 0x0008 // Revision ID Register
+#define PCI_IFT 0x0009 // Interface Type
+#define PCI_SCC 0x000A // Sub Class Code Register
+#define PCI_BCC 0x000B // Base Class Code Register
+#define PCI_CLS 0x000C // Cache Line Size
+#define PCI_PMLT 0x000D // Primary Master Latency Timer
+#define PCI_HDR 0x000E // Header Type Register
+#define PCI_BIST 0x000F // Built in Self Test Register
+#define PCI_BAR0 0x0010 // Base Address Register 0
+#define PCI_BAR1 0x0014 // Base Address Register 1
+#define PCI_BAR2 0x0018 // Base Address Register 2
+#define PCI_PBUS 0x0018 // Primary Bus Number Register
+#define PCI_SBUS 0x0019 // Secondary Bus Number Register
+#define PCI_SUBUS 0x001A // Subordinate Bus Number Register
+#define PCI_SMLT 0x001B // Secondary Master Latency Timer
+#define PCI_BAR3 0x001C // Base Address Register 3
+#define PCI_IOBASE 0x001C // I/O base Register
+#define PCI_IOLIMIT 0x001D // I/O Limit Register
+#define PCI_SECSTATUS 0x001E // Secondary Status Register
+#define PCI_BAR4 0x0020 // Base Address Register 4
+#define PCI_MEMBASE 0x0020 // Memory Base Register
+#define PCI_MEMLIMIT 0x0022 // Memory Limit Register
+#define PCI_BAR5 0x0024 // Base Address Register 5
+#define PCI_PRE_MEMBASE 0x0024 // Prefetchable memory Base register
+#define PCI_PRE_MEMLIMIT 0x0026 // Prefetchable memory Limit register
+#define PCI_PRE_MEMBASE_U 0x0028 // Prefetchable memory base upper 32 bits
+#define PCI_PRE_MEMLIMIT_U 0x002C // Prefetchable memory limit upper 32 bits
+#define PCI_SVID 0x002C // Subsystem Vendor ID
+#define PCI_SID 0x002E // Subsystem ID
+#define PCI_IOBASE_U 0x0030 // I/O base Upper Register
+#define PCI_IOLIMIT_U 0x0032 // I/O Limit Upper Register
+#define PCI_CAPP 0x0034 // Capabilities Pointer
+#define PCI_EROM 0x0038 // Expansion ROM Base Address
+#define PCI_INTLINE 0x003C // Interrupt Line Register
+#define PCI_INTPIN 0x003D // Interrupt Pin Register
+#define PCI_MAXGNT 0x003E // Max Grant Register
+#define PCI_BRIDGE_CNTL 0x003E // Bridge Control Register
+#define PCI_MAXLAT 0x003F // Max Latency Register
+#endif
+//
+// Bit Difinitions
+//
+#ifndef BIT0
+#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
+#endif
+
+
+//
+// Common Memory mapped Io access macros ------------------------------------------
+//
+#define IohMmioAddress( BaseAddr, Register ) \
+ ( (UINTN)BaseAddr + \
+ (UINTN)(Register) \
+ )
+
+//
+// UINT64
+//
+#define IohMmio64Ptr( BaseAddr, Register ) \
+ ( (volatile UINT64 *)IohMmioAddress( BaseAddr, Register ) )
+
+#define IohMmio64( BaseAddr, Register ) \
+ *IohMmio64Ptr( BaseAddr, Register )
+
+#define IohMmio64Or( BaseAddr, Register, OrData ) \
+ IohMmio64( BaseAddr, Register ) = \
+ (UINT64) ( \
+ IohMmio64( BaseAddr, Register ) | \
+ (UINT64)(OrData) \
+ )
+
+#define IohMmio64And( BaseAddr, Register, AndData ) \
+ IohMmio64( BaseAddr, Register ) = \
+ (UINT64) ( \
+ IohMmio64( BaseAddr, Register ) & \
+ (UINT64)(AndData) \
+ )
+
+#define IohMmio64AndThenOr( BaseAddr, Register, AndData, OrData ) \
+ IohMmio64( BaseAddr, Register ) = \
+ (UINT64) ( \
+ ( IohMmio64( BaseAddr, Register ) & \
+ (UINT64)(AndData) \
+ ) | \
+ (UINT64)(OrData) \
+ )
+
+//
+// UINT32
+//
+#define IohMmio32Ptr( BaseAddr, Register ) \
+ ( (volatile UINT32 *)IohMmioAddress( BaseAddr, Register ) )
+
+#define IohMmio32( BaseAddr, Register ) \
+ *IohMmio32Ptr( BaseAddr, Register )
+
+#define IohMmio32Or( BaseAddr, Register, OrData ) \
+ IohMmio32( BaseAddr, Register ) = \
+ (UINT32) ( \
+ IohMmio32( BaseAddr, Register ) | \
+ (UINT32)(OrData) \
+ )
+
+#define IohMmio32And( BaseAddr, Register, AndData ) \
+ IohMmio32( BaseAddr, Register ) = \
+ (UINT32) ( \
+ IohMmio32( BaseAddr, Register ) & \
+ (UINT32)(AndData) \
+ )
+
+#define IohMmio32AndThenOr( BaseAddr, Register, AndData, OrData ) \
+ IohMmio32( BaseAddr, Register ) = \
+ (UINT32) ( \
+ ( IohMmio32( BaseAddr, Register ) & \
+ (UINT32)(AndData) \
+ ) | \
+ (UINT32)(OrData) \
+ )
+//
+// UINT16
+//
+
+#define IohMmio16Ptr( BaseAddr, Register ) \
+ ( (volatile UINT16 *)IohMmioAddress( BaseAddr, Register ) )
+
+#define IohMmio16( BaseAddr, Register ) \
+ *IohMmio16Ptr( BaseAddr, Register )
+
+#define IohMmio16Or( BaseAddr, Register, OrData ) \
+ IohMmio16( BaseAddr, Register ) = \
+ (UINT16) ( \
+ IohMmio16( BaseAddr, Register ) | \
+ (UINT16)(OrData) \
+ )
+
+#define IohMmio16And( BaseAddr, Register, AndData ) \
+ IohMmio16( BaseAddr, Register ) = \
+ (UINT16) ( \
+ IohMmio16( BaseAddr, Register ) & \
+ (UINT16)(AndData) \
+ )
+
+#define IohMmio16AndThenOr( BaseAddr, Register, AndData, OrData ) \
+ IohMmio16( BaseAddr, Register ) = \
+ (UINT16) ( \
+ ( IohMmio16( BaseAddr, Register ) & \
+ (UINT16)(AndData) \
+ ) | \
+ (UINT16)(OrData) \
+ )
+//
+// UINT8
+//
+#define IohMmio8Ptr( BaseAddr, Register ) \
+ ( (volatile UINT8 *)IohMmioAddress( BaseAddr, Register ) )
+
+#define IohMmio8( BaseAddr, Register ) \
+ *IohMmio8Ptr( BaseAddr, Register )
+
+#define IohMmio8Or( BaseAddr, Register, OrData ) \
+ IohMmio8( BaseAddr, Register ) = \
+ (UINT8) ( \
+ IohMmio8( BaseAddr, Register ) | \
+ (UINT8)(OrData) \
+ )
+
+#define IohMmio8And( BaseAddr, Register, AndData ) \
+ IohMmio8( BaseAddr, Register ) = \
+ (UINT8) ( \
+ IohMmio8( BaseAddr, Register ) & \
+ (UINT8)(AndData) \
+ )
+
+#define IohMmio8AndThenOr( BaseAddr, Register, AndData, OrData ) \
+ IohMmio8( BaseAddr, Register ) = \
+ (UINT8) ( \
+ ( IohMmio8( BaseAddr, Register ) & \
+ (UINT8)(AndData) \
+ ) | \
+ (UINT8)(OrData) \
+ )
+
+//
+// Common Memory mapped Pci access macros ------------------------------------------
+//
+#define Ioh_PCI_EXPRESS_BASE_ADDRESS 0xE0000000
+
+
+#define IohMmPciAddress( Segment, Bus, Device, Function, Register ) \
+ ( (UINTN)Ioh_PCI_EXPRESS_BASE_ADDRESS + \
+ (UINTN)(Bus << 20) + \
+ (UINTN)(Device << 15) + \
+ (UINTN)(Function << 12) + \
+ (UINTN)(Register) \
+ )
+
+//
+// UINT32
+//
+#define IohMmPci32Ptr( Segment, Bus, Device, Function, Register ) \
+ ( (volatile UINT32 *)IohMmPciAddress( Segment, Bus, Device, Function, Register ) )
+
+#define IohMmPci32( Segment, Bus, Device, Function, Register ) \
+ *IohMmPci32Ptr( Segment, Bus, Device, Function, Register )
+
+#define IohMmPci32Or( Segment, Bus, Device, Function, Register, OrData ) \
+ IohMmPci32( Segment, Bus, Device, Function, Register ) = \
+ (UINT32) ( \
+ IohMmPci32( Segment, Bus, Device, Function, Register ) | \
+ (UINT32)(OrData) \
+ )
+
+#define IohMmPci32And( Segment, Bus, Device, Function, Register, AndData ) \
+ IohMmPci32( Segment, Bus, Device, Function, Register ) = \
+ (UINT32) ( \
+ IohMmPci32( Segment, Bus, Device, Function, Register ) & \
+ (UINT32)(AndData) \
+ )
+
+#define IohMmPci32AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \
+ IohMmPci32( Segment, Bus, Device, Function, Register ) = \
+ (UINT32) ( \
+ ( IohMmPci32( Segment, Bus, Device, Function, Register ) & \
+ (UINT32)(AndData) \
+ ) | \
+ (UINT32)(OrData) \
+ )
+//
+// UINT16
+//
+#define IohMmPci16Ptr( Segment, Bus, Device, Function, Register ) \
+ ( (volatile UINT16 *)IohMmPciAddress( Segment, Bus, Device, Function, Register ) )
+
+#define IohMmPci16( Segment, Bus, Device, Function, Register ) \
+ *IohMmPci16Ptr( Segment, Bus, Device, Function, Register )
+
+#define IohMmPci16Or( Segment, Bus, Device, Function, Register, OrData ) \
+ IohMmPci16( Segment, Bus, Device, Function, Register ) = \
+ (UINT16) ( \
+ IohMmPci16( Segment, Bus, Device, Function, Register ) | \
+ (UINT16)(OrData) \
+ )
+
+#define IohMmPci16And( Segment, Bus, Device, Function, Register, AndData ) \
+ IohMmPci16( Segment, Bus, Device, Function, Register ) = \
+ (UINT16) ( \
+ IohMmPci16( Segment, Bus, Device, Function, Register ) & \
+ (UINT16)(AndData) \
+ )
+
+#define IohMmPci16AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \
+ IohMmPci16( Segment, Bus, Device, Function, Register ) = \
+ (UINT16) ( \
+ ( IohMmPci16( Segment, Bus, Device, Function, Register ) & \
+ (UINT16)(AndData) \
+ ) | \
+ (UINT16)(OrData) \
+ )
+//
+// UINT8
+//
+#define IohMmPci8Ptr( Segment, Bus, Device, Function, Register ) \
+ ( (volatile UINT8 *)IohMmPciAddress( Segment, Bus, Device, Function, Register ) )
+
+#define IohMmPci8( Segment, Bus, Device, Function, Register ) \
+ *IohMmPci8Ptr( Segment, Bus, Device, Function, Register )
+
+#define IohMmPci8Or( Segment, Bus, Device, Function, Register, OrData ) \
+ IohMmPci8( Segment, Bus, Device, Function, Register ) = \
+ (UINT8) ( \
+ IohMmPci8( Segment, Bus, Device, Function, Register ) | \
+ (UINT8)(OrData) \
+ )
+
+#define IohMmPci8And( Segment, Bus, Device, Function, Register, AndData ) \
+ IohMmPci8( Segment, Bus, Device, Function, Register ) = \
+ (UINT8) ( \
+ IohMmPci8( Segment, Bus, Device, Function, Register ) & \
+ (UINT8)(AndData) \
+ )
+
+#define IohMmPci8AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \
+ IohMmPci8( Segment, Bus, Device, Function, Register ) = \
+ (UINT8) ( \
+ ( IohMmPci8( Segment, Bus, Device, Function, Register ) & \
+ (UINT8)(AndData) \
+ ) | \
+ (UINT8)(OrData) \
+ )
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/Library/IohLib.h b/QuarkSocPkg/QuarkSouthCluster/Include/Library/IohLib.h
new file mode 100644
index 0000000..5a3a0e8
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/Library/IohLib.h
@@ -0,0 +1,47 @@
+/** @file
+ Library that provides Soc specific library services in PEI phase
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __IOH_LIB_H__
+#define __IOH_LIB_H__
+
+#define PCI_IOSF2AHB_0_DEV_NUM 20
+#define PCI_IOSF2AHB_1_DEV_NUM 21
+
+VOID
+EFIAPI
+EnableUsbMemIoBusMaster (
+ IN UINT8 UsbBusNumber
+ );
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/MMC.h b/QuarkSocPkg/QuarkSouthCluster/Include/MMC.h
new file mode 100644
index 0000000..dc855c3
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/MMC.h
@@ -0,0 +1,295 @@
+/** @file
+
+ Header file for Industry MMC 4.2 spec.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _MMC_H
+#define _MMC_H
+
+#pragma pack(1)
+//
+//Command definition
+//
+
+#define CMD0 0
+#define CMD1 1
+#define CMD2 2
+#define CMD3 3
+#define CMD4 4
+#define CMD6 6
+#define CMD7 7
+#define CMD8 8
+#define CMD9 9
+#define CMD10 10
+#define CMD11 11
+#define CMD12 12
+#define CMD13 13
+#define CMD14 14
+#define CMD15 15
+#define CMD16 16
+#define CMD17 17
+#define CMD18 18
+#define CMD19 19
+#define CMD20 20
+#define CMD23 23
+#define CMD24 24
+#define CMD25 25
+#define CMD26 26
+#define CMD27 27
+#define CMD28 28
+#define CMD29 29
+#define CMD30 30
+#define CMD35 35
+#define CMD36 36
+#define CMD38 38
+#define CMD39 39
+#define CMD40 40
+#define CMD42 42
+#define CMD55 55
+#define CMD56 56
+
+
+
+#define GO_IDLE_STATE CMD0
+#define SEND_OP_COND CMD1
+#define ALL_SEND_CID CMD2
+#define SET_RELATIVE_ADDR CMD3
+#define SET_DSR CMD4
+#define SWITCH CMD6
+#define SELECT_DESELECT_CARD CMD7
+#define SEND_EXT_CSD CMD8
+#define SEND_CSD CMD9
+#define SEND_CID CMD10
+#define READ_DAT_UNTIL_STOP CMD11
+#define STOP_TRANSMISSION CMD12
+#define SEND_STATUS CMD13
+#define BUSTEST_R CMD14
+#define GO_INACTIVE_STATE CMD15
+#define SET_BLOCKLEN CMD16
+#define READ_SINGLE_BLOCK CMD17
+#define READ_MULTIPLE_BLOCK CMD18
+#define BUSTEST_W CMD19
+#define WRITE_DAT_UNTIL_STOP CMD20
+#define SET_BLOCK_COUNT CMD23
+#define WRITE_BLOCK CMD24
+#define WRITE_MULTIPLE_BLOCK CMD25
+#define PROGRAM_CID CMD26
+#define PROGRAM_CSD CMD27
+#define SET_WRITE_PROT CMD28
+#define CLR_WRITE_PROT CMD29
+#define SEND_WRITE_PROT CMD30
+#define ERASE_GROUP_START CMD35
+#define ERASE_GROUP_END CMD36
+#define ERASE CMD38
+#define FAST_IO CMD39
+#define GO_IRQ_STATE CMD40
+#define LOCK_UNLOCK CMD42
+#define APP_CMD CMD55
+#define GEN_CMD CMD56
+
+
+
+#define FREQUENCY_OD (400 * 1000)
+#define FREQUENCY_MMC_PP (26 * 1000 * 1000)
+#define FREQUENCY_MMC_PP_HIGH (52 * 1000 * 1000)
+
+#define DEFAULT_DSR_VALUE 0x404
+
+//
+//Registers definition
+//
+
+typedef struct {
+ UINT32 Reserved0: 7; // 0
+ UINT32 V170_V195: 1; // 1.70V - 1.95V
+ UINT32 V200_V260: 7; // 2.00V - 2.60V
+ UINT32 V270_V360: 9; // 2.70V - 3.60V
+ UINT32 Reserved1: 5; // 0
+ UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode)
+ UINT32 Busy: 1; // This bit is set to LOW if the card has not finished the power up routine
+}OCR;
+
+
+typedef struct {
+ UINT8 NotUsed: 1; // 1
+ UINT8 CRC: 7; // CRC7 checksum
+ UINT8 MDT; // Manufacturing date
+ UINT32 PSN; // Product serial number
+ UINT8 PRV; // Product revision
+ UINT8 PNM[6]; // Product name
+ UINT16 OID; // OEM/Application ID
+ UINT8 MID; // Manufacturer ID
+}CID;
+
+
+typedef struct {
+ UINT8 NotUsed: 1; // 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+ UINT8 ECC: 2; // ECC code [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+ UINT16 CONTENT_PROT_APP: 1; // Content protection application [16:16]
+ UINT16 Reserved0: 4; // 0 [20:17]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 DEFAULT_ECC: 2; // Manufacturer default ECC [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+ UINT32 WP_GRP_SIZE: 5; // Write protect group size [36:32]
+ UINT32 ERASE_GRP_MULT: 5; // Erase group size multiplier [41:37]
+ UINT32 ERASE_GRP_SIZE: 5; // Erase group size [46:42]
+ UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47]
+ UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50]
+ UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53]
+ UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56]
+ UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59]
+ UINT32 C_SIZELow2: 2;// Device size [73:62]
+ UINT32 C_SIZEHigh10: 10;// Device size [73:62]
+ UINT32 Reserved1: 2; // 0 [75:74]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+ UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT32 CCC: 12;// Card command classes [95:84]
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+ UINT8 Reserved2: 2; // 0 [121:120]
+ UINT8 SPEC_VERS: 4; // System specification version [125:122]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+}CSD;
+
+typedef struct {
+ UINT8 Reserved0[181]; // 0 [0:180]
+ UINT8 ERASED_MEM_CONT; // Erased Memory Content [181]
+ UINT8 Reserved2; // Erased Memory Content [182]
+ UINT8 BUS_WIDTH; // Bus Width Mode [183]
+ UINT8 Reserved3; // 0 [184]
+ UINT8 HS_TIMING; // High Speed Interface Timing [185]
+ UINT8 Reserved4; // 0 [186]
+ UINT8 POWER_CLASS; // Power Class [187]
+ UINT8 Reserved5; // 0 [188]
+ UINT8 CMD_SET_REV; // Command Set Revision [189]
+ UINT8 Reserved6; // 0 [190]
+ UINT8 CMD_SET; // Command Set [191]
+ UINT8 EXT_CSD_REV; // Extended CSD Revision [192]
+ UINT8 Reserved7; // 0 [193]
+ UINT8 CSD_STRUCTURE; // CSD Structure Version [194]
+ UINT8 Reserved8; // 0 [195]
+ UINT8 CARD_TYPE; // Card Type [196]
+ UINT8 Reserved9[3]; // 0 [199:197]
+ UINT8 PWR_CL_52_195; // Power Class for 52MHz @ 1.95V [200]
+ UINT8 PWR_CL_26_195; // Power Class for 26MHz @ 1.95V [201]
+ UINT8 PWR_CL_52_360; // Power Class for 52MHz @ 3.6V [202]
+ UINT8 PWR_CL_26_360; // Power Class for 26MHz @ 3.6V [203]
+ UINT8 Reserved10; // 0 [204]
+ UINT8 MIN_PERF_R_4_26; // Minimum Read Performance for 4bit @26MHz [205]
+ UINT8 MIN_PERF_W_4_26; // Minimum Write Performance for 4bit @26MHz [206]
+ UINT8 MIN_PERF_R_8_26_4_52; // Minimum Read Performance for 8bit @26MHz/4bit @52MHz [207]
+ UINT8 MIN_PERF_W_8_26_4_52; // Minimum Write Performance for 8bit @26MHz/4bit @52MHz [208]
+ UINT8 MIN_PERF_R_8_52; // Minimum Read Performance for 8bit @52MHz [209]
+ UINT8 MIN_PERF_W_8_52; // Minimum Write Performance for 8bit @52MHz [210]
+ UINT8 Reserved11; // 0 [211]
+ UINT8 SEC_COUNT[4]; // Sector Count [215:212]
+ UINT8 Reserved12[288]; // 0 [503:216]
+ UINT8 S_CMD_SET; // Sector Count [504]
+ UINT8 Reserved13[7]; // Sector Count [511:505]
+}EXT_CSD;
+
+
+//
+//Card Status definition
+//
+typedef struct {
+ UINT32 Reserved0: 2; //Reserved for Manufacturer Test Mode
+ UINT32 Reserved1: 2; //Reserved for Application Specific commands
+ UINT32 Reserved2: 1; //
+ UINT32 SAPP_CMD: 1; //
+ UINT32 Reserved3: 1; //Reserved
+ UINT32 SWITCH_ERROR: 1; //
+ UINT32 READY_FOR_DATA: 1; //
+ UINT32 CURRENT_STATE: 4; //
+ UINT32 ERASE_RESET: 1; //
+ UINT32 Reserved4: 1; //Reserved
+ UINT32 WP_ERASE_SKIP: 1; //
+ UINT32 CID_CSD_OVERWRITE: 1; //
+ UINT32 OVERRUN: 1; //
+ UINT32 UNDERRUN: 1; //
+ UINT32 ERROR: 1; //
+ UINT32 CC_ERROR: 1; //
+ UINT32 CARD_ECC_FAILED: 1; //
+ UINT32 ILLEGAL_COMMAND: 1; //
+ UINT32 COM_CRC_ERROR: 1; //
+ UINT32 LOCK_UNLOCK_FAILED: 1; //
+ UINT32 CARD_IS_LOCKED: 1; //
+ UINT32 WP_VIOLATION: 1; //
+ UINT32 ERASE_PARAM: 1; //
+ UINT32 ERASE_SEQ_ERROR: 1; //
+ UINT32 BLOCK_LEN_ERROR: 1; //
+ UINT32 ADDRESS_MISALIGN: 1; //
+ UINT32 ADDRESS_OUT_OF_RANGE:1; //
+}CARD_STATUS;
+
+typedef struct {
+ UINT32 CmdSet: 3;
+ UINT32 Reserved0: 5;
+ UINT32 Value: 8;
+ UINT32 Index: 8;
+ UINT32 Access: 2;
+ UINT32 Reserved1: 6;
+}SWITCH_ARGUMENT;
+
+#define CommandSet_Mode 0
+#define SetBits_Mode 1
+#define ClearBits_Mode 2
+#define WriteByte_Mode 3
+
+
+#define Idle_STATE 0
+#define Ready_STATE 1
+#define Ident_STATE 2
+#define Stby_STATE 3
+#define Tran_STATE 4
+#define Data_STATE 5
+#define Rcv_STATE 6
+#define Prg_STATE 7
+#define Dis_STATE 8
+#define Btst_STATE 9
+
+
+
+#pragma pack()
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/Protocol/I2CHc.h b/QuarkSocPkg/QuarkSouthCluster/Include/Protocol/I2CHc.h
new file mode 100644
index 0000000..a136ba1
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/Protocol/I2CHc.h
@@ -0,0 +1,226 @@
+/** @file
+ The file provides defintion of I2C host controller management
+ functions and data transactions over the I2C Bus.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __I2C_HC_H__
+#define __I2C_HC_H__
+
+#define EFI_I2C_HC_PROTOCOL_GUID \
+ {0x855b7d58, 0x874b, 0x47eb, { 0xa5, 0xcf, 0x98, 0xed, 0xac, 0x80, 0x67, 0x96} }
+
+typedef struct _EFI_I2C_HC_PROTOCOL EFI_I2C_HC_PROTOCOL;
+
+///
+/// I2C Device Address
+///
+typedef struct {
+ ///
+ /// The I2C hardware address to which the I2C device is preassigned or allocated.
+ ///
+ UINTN I2CDeviceAddress : 10;
+} EFI_I2C_DEVICE_ADDRESS;
+
+///
+/// I2C Addressing Mode (7-bit or 10 bit)
+///
+typedef enum _EFI_I2C_ADDR_MODE {
+ EfiI2CSevenBitAddrMode,
+ EfiI2CTenBitAddrMode,
+} EFI_I2C_ADDR_MODE;
+
+/**
+
+ The WriteByte() function provides a standard way to execute a
+ standard single byte write to an IC2 device (without accessing
+ sub-addresses), as defined in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be written.
+
+ @param Buffer Contains the value of byte data to execute to the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_I2C_WRITEBYTE_OPERATION)(
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+);
+
+/**
+
+ The ReadByte() function provides a standard way to execute a
+ standard single byte read to an IC2 device (without accessing
+ sub-addresses), as defined in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be read.
+
+ @param Buffer Contains the value of byte data read from the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_I2C_READBYTE_OPERATION)(
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+);
+
+/**
+
+ The WriteMultipleByte() function provides a standard way to execute
+ multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
+ writing block of data), as defined in the I2C Specification.
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param Length No. of bytes to be written.
+
+ @param Buffer Contains the value of byte to be written to the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_I2C_WRITE_MULTIPLE_BYTE_OPERATION)(
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *Length,
+ IN OUT VOID *Buffer
+);
+
+/**
+
+ The ReadMultipleByte() function provides a standard way to execute
+ multiple byte writes to an IC2 device (e.g. when accessing sub-addresses
+ or when reading block of data), as defined in the I2C Specification
+ (I2C combined write/read protocol).
+
+ @param This A pointer to the EFI_I2C_PROTOCOL instance.
+
+ @param SlaveAddress The I2C slave address of the device
+ with which to communicate.
+
+ @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address.
+
+ @param WriteLength No. of bytes to be written. In this case data
+ written typically contains sub-address or sub-addresses
+ in Hi-Lo format, that need to be read (I2C combined
+ write/read protocol).
+
+ @param ReadLength No. of bytes to be read from I2C slave device.
+ need to be read.
+
+ @param Buffer Contains the value of byte data read from the
+ I2C slave device.
+
+
+ @retval EFI_SUCCESS I2C Operation completed successfully.
+
+ @retval EFI_DEVICE_ERROR The request was not completed due to error
+ accessing the slave device.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_I2C_READ_MULTIPLE_BYTE_OPERATION)(
+ IN CONST EFI_I2C_HC_PROTOCOL *This,
+ IN EFI_I2C_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_I2C_ADDR_MODE AddrMode,
+ IN UINTN *WriteLength,
+ IN UINTN *ReadLength,
+ IN OUT VOID *Buffer
+);
+
+
+//
+// The EFI_I2C_HC_PROTOCOL provides I2C host controller management and basic data
+// transactions over I2C. There is one EFI_I2C_HC_PROTOCOL instance for each I2C
+// host controller.
+//
+struct _EFI_I2C_HC_PROTOCOL {
+ EFI_I2C_WRITEBYTE_OPERATION WriteByte;
+ EFI_I2C_READBYTE_OPERATION ReadByte;
+ EFI_I2C_WRITE_MULTIPLE_BYTE_OPERATION WriteMultipleByte;
+ EFI_I2C_READ_MULTIPLE_BYTE_OPERATION ReadMultipleByte;
+};
+
+
+extern EFI_GUID gEfiI2CHcProtocolGuid;
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/SDCard.h b/QuarkSocPkg/QuarkSouthCluster/Include/SDCard.h
new file mode 100644
index 0000000..d03ab96
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/SDCard.h
@@ -0,0 +1,170 @@
+/** @file
+
+ Header file for Industry SD Card 2.0 spec.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SD_CARD_H
+#define _SD_CARD_H
+
+#include "MMC.h"
+
+#pragma pack(1)
+
+#define CHECK_PATTERN 0xAA ///< Physical Layer Simplified Specification Version 3.01 recommended 0xAA
+
+#define ACMD6 6
+#define ACMD13 13
+#define ACMD23 23
+#define ACMD41 41
+#define ACMD42 42
+#define ACMD51 51
+
+
+#define SWITCH_FUNC CMD6
+#define SEND_IF_COND CMD8
+
+
+#define SET_BUS_WIDTH ACMD6
+#define SD_STATUS ACMD13
+#define SET_WR_BLK_ERASE_COUNT ACMD23
+#define SD_SEND_OP_COND ACMD41
+#define SET_CLR_CARD_DETECT ACMD42
+#define SEND_SCR ACMD51
+
+
+
+#define SD_BUS_WIDTH_1 0
+#define SD_BUS_WIDTH_4 2
+
+
+
+#define FREQUENCY_SD_PP (25 * 1000 * 1000)
+#define FREQUENCY_SD_PP_HIGH (50 * 1000 * 1000)
+
+
+#define SD_SPEC_10 0
+#define SD_SPEC_11 1
+#define SD_SPEC_20 2
+
+
+#define VOLTAGE_27_36 0x1
+
+typedef struct {
+ UINT8 NotUsed: 1; // 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+ UINT8 ECC: 2; // ECC code [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+ UINT16 Reserved0: 5; // 0 [20:16]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 DEFAULT_ECC: 2; // Manufacturer default ECC [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+ UINT16 WP_GRP_SIZE: 7; // Write protect group size [38:32]
+ UINT16 SECTOR_SIZE: 7; // Erase sector size [45:39]
+ UINT16 ERASE_BLK_EN: 1; // Erase single block enable [46:46]
+ UINT16 Reserved1: 1; // 0 [47:47]
+
+ UINT32 C_SIZE: 22; // Device size [69:48]
+ UINT32 Reserved2: 6; // 0 [75:70]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+
+ UINT16 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT16 CCC: 12; // Card command classes [95:84]
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+ UINT8 Reserved3: 6; // 0 [125:120]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+}CSD_SDV2;
+
+typedef struct {
+ UINT32 Reserved0;
+ UINT32 Reserved1: 16;
+ UINT32 SD_BUS_WIDTH: 4;
+ UINT32 SD_SECURITY: 3;
+ UINT32 DATA_STAT_AFTER_ERASE: 1;
+ UINT32 SD_SPEC: 4;
+ UINT32 SCR_STRUCT: 4;
+}SCR;
+
+
+typedef struct {
+ UINT8 Reserved0[50];
+ UINT8 ERASE_OFFSET: 2;
+ UINT8 ERASE_TIMEOUT: 6;
+ UINT16 ERASE_SIZE;
+ UINT8 Reserved1: 4;
+ UINT8 AU_SIZE: 4;
+ UINT8 PERFORMANCE_MOVE;
+ UINT8 SPEED_CLASS;
+ UINT32 SIZE_OF_PROTECTED_AREA;
+ UINT32 SD_CARD_TYPE: 16;
+ UINT32 Reserved2: 13;
+ UINT32 SECURED_MODE: 1;
+ UINT32 DAT_BUS_WIDTH: 2;
+}SD_STATUS_REG;
+
+
+
+typedef struct {
+ UINT8 Reserved0[34];
+ UINT16 Group1BusyStatus;
+ UINT16 Group2BusyStatus;
+ UINT16 Group3BusyStatus;
+ UINT16 Group4BusyStatus;
+ UINT16 Group5BusyStatus;
+ UINT16 Group6BusyStatus;
+ UINT8 DataStructureVersion;
+ UINT8 Group21Status;
+ UINT8 Group43Status;
+ UINT8 Group65Status;
+ UINT16 Group1Function;
+ UINT16 Group2Function;
+ UINT16 Group3Function;
+ UINT16 Group4Function;
+ UINT16 Group5Function;
+ UINT16 Group6Function;
+ UINT16 MaxCurrent;
+}SWITCH_STATUS;
+
+
+#pragma pack()
+#endif
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/SDHostIo.h b/QuarkSocPkg/QuarkSouthCluster/Include/SDHostIo.h
new file mode 100644
index 0000000..366fd35
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Include/SDHostIo.h
@@ -0,0 +1,348 @@
+/** @file
+
+ Interface definition for EFI_SD_HOST_IO_PROTOCOL.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SD_HOST_IO_H
+#define _SD_HOST_IO_H
+
+#include "SDCard.h"
+#include "CEATA.h"
+
+
+#define EFI_SD_HOST_IO_PROTOCOL_GUID \
+ { \
+ 0xb63f8ec7, 0xa9c9, 0x4472, {0xa4, 0xc0, 0x4d, 0x8b, 0xf3, 0x65, 0xcc, 0x51} \
+ }
+
+///
+/// Forward reference for pure ANSI compatability
+///
+typedef struct _EFI_SD_HOST_IO_PROTOCOL EFI_SD_HOST_IO_PROTOCOL;
+
+
+
+typedef enum {
+ ResponseNo = 0,
+ ResponseR1,
+ ResponseR1b,
+ ResponseR2,
+ ResponseR3,
+ ResponseR4,
+ ResponseR5,
+ ResponseR5b,
+ ResponseR6,
+ ResponseR7
+}RESPONSE_TYPE;
+
+typedef enum {
+ NoData = 0,
+ InData,
+ OutData
+}TRANSFER_TYPE;
+
+typedef enum {
+ Reset_Auto = 0,
+ Reset_DAT,
+ Reset_CMD,
+ Reset_DAT_CMD,
+ Reset_All
+}RESET_TYPE;
+
+#define PCI_SUBCLASS_SD_HOST_CONTROLLER 0x05
+#define PCI_IF_STANDARD_HOST_NO_DMA 0x00
+#define PCI_IF_STANDARD_HOST_SUPPORT_DMA 0x01
+
+#define SDHCI_SPEC_100 0
+#define SDHCI_SPEC_200 1
+#define SDHCI_SPEC_300 2
+
+//
+//MMIO Registers definition for MMC/SDIO controller
+//
+#define MMIO_DMAADR 0x00
+#define MMIO_BLKSZ 0x04
+#define MMIO_BLKCNT 0x06
+#define MMIO_CMDARG 0x08
+#define MMIO_XFRMODE 0x0C
+#define MMIO_SDCMD 0x0E
+#define MMIO_RESP 0x10
+#define MMIO_BUFDATA 0x20
+#define MMIO_PSTATE 0x24
+#define MMIO_HOSTCTL 0x28
+#define MMIO_PWRCTL 0x29
+#define MMIO_BLKGAPCTL 0x2A
+#define MMIO_WAKECTL 0x2B
+#define MMIO_CLKCTL 0x2C
+#define V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL 0x80
+#define V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL 0x3FF
+#define B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK 0xC0
+
+#define MMIO_TOCTL 0x2E
+#define MMIO_SWRST 0x2F
+#define MMIO_NINTSTS 0x30
+#define MMIO_ERINTSTS 0x32
+#define MMIO_NINTEN 0x34
+#define MMIO_ERINTEN 0x36
+#define MMIO_NINTSIGEN 0x38
+#define MMIO_ERINTSIGEN 0x3A
+#define MMIO_AC12ERRSTS 0x3C
+#define MMIO_CAP 0x40
+#define MMIO_MCCAP 0x48
+#define MMIO_SLTINTSTS 0xFC
+#define MMIO_CTRLRVER 0xFE
+#define MMIO_SRST 0x1FC
+
+//
+// Protocol definitions
+//
+
+/**
+ The main function used to send the command to the card inserted into the SD host slot.
+ It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param CommandIndex The command index to set the command index field of command register.
+ @param Argument Command argument to set the argument field of command register.
+ @param DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param Buffer Contains the data read from / write to the device.
+ @param BufferSize The size of the buffer.
+ @param ResponseType RESPONSE_TYPE.
+ @param TimeOut Time out value in 1 ms unit.
+ @param ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+ @retval EFI_TIMEOUT
+ @retval EFI_DEVICE_ERROR
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SEND_COMMAND) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData OPTIONAL
+ );
+
+/**
+ Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.
+ It depends on the max frequency the host can support, divider, and host speed mode.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param MaxFrequency Max frequency in HZ.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_CLOCK_FREQUENCY) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 MaxFrequency
+ );
+
+
+/**
+ Set bus width of the host controller
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param BusWidth Bus width in 1, 4, 8 bits.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_BUS_WIDTH) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BusWidth
+ );
+
+/**
+ Set voltage which could supported by the host controller.
+ Support 0(Power off the host), 1.8V, 3.0V, 3.3V
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Voltage Units in 0.1 V.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_HOST_VOLTAGE) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 Voltage
+ );
+
+/**
+ Reset the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param ResetAll TRUE to reset all.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_RESET_SD_HOST) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN RESET_TYPE ResetType
+ );
+
+/**
+ Enable auto stop on the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Enable TRUE to enable, FALSE to disable.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_ENABLE_AUTO_STOP_CMD) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+/**
+ Find whether these is a card inserted into the slot. If so init the host.
+ If not, return EFI_NOT_FOUND.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_FOUND
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_DETECT_CARD_AND_INIT_HOST) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This
+ );
+
+/**
+ Set the Block length on the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param BlockLength card supportes block length.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_BLOCK_LENGTH) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BlockLength
+ );
+
+/**
+ Enable/Disable High Speed transfer mode
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Enable TRUE to Enable, FALSE to Disable
+
+ @return EFI_SUCCESS
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_HIGH_SPEED_MODE) (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+
+
+
+#define EFI_SD_HOST_IO_PROTOCOL_REVISION_01 0x02
+
+
+typedef struct {
+ UINT32 HighSpeedSupport: 1; //High speed supported
+ UINT32 V18Support: 1; //1.8V supported
+ UINT32 V30Support: 1; //3.0V supported
+ UINT32 V33Support: 1; //3.3V supported
+ UINT32 Reserved0: 12;
+ UINT32 BusWidth4: 1; // 4 bit width
+ UINT32 BusWidth8: 1; // 8 bit width
+ UINT32 Reserved1: 14;
+ UINT32 BoundarySize;
+}HOST_CAPABILITY;
+
+
+//
+// Interface structure for the SD HOST I/O Protocol
+//
+struct _EFI_SD_HOST_IO_PROTOCOL {
+ UINT32 Revision;
+ HOST_CAPABILITY HostCapability;
+ EFI_SD_HOST_IO_PROTOCOL_SEND_COMMAND SendCommand;
+ EFI_SD_HOST_IO_PROTOCOL_SET_CLOCK_FREQUENCY SetClockFrequency;
+ EFI_SD_HOST_IO_PROTOCOL_SET_BUS_WIDTH SetBusWidth;
+ EFI_SD_HOST_IO_PROTOCOL_SET_HOST_VOLTAGE SetHostVoltage;
+ EFI_SD_HOST_IO_PROTOCOL_RESET_SD_HOST ResetSDHost;
+ EFI_SD_HOST_IO_PROTOCOL_ENABLE_AUTO_STOP_CMD EnableAutoStopCmd;
+ EFI_SD_HOST_IO_PROTOCOL_DETECT_CARD_AND_INIT_HOST DetectCardAndInitHost;
+ EFI_SD_HOST_IO_PROTOCOL_SET_BLOCK_LENGTH SetBlockLength;
+ EFI_SD_HOST_IO_PROTOCOL_HIGH_SPEED_MODE HighSpeedMode;
+};
+
+extern EFI_GUID gEfiSDHostIoProtocolGuid;
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/CommonHeader.h b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/CommonHeader.h
new file mode 100644
index 0000000..64d1e42
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/CommonHeader.h
@@ -0,0 +1,79 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+#include <Ioh.h>
+#include <IohCommonDefinitions.h>
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/DevicePath.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/S3PciLib.h>
+#include <Library/S3IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IohLib.h>
+
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Pci.h>
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohBds.h b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohBds.h
new file mode 100644
index 0000000..eec0488
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohBds.h
@@ -0,0 +1,111 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ IohBds.h
+
+Abstract:
+
+ Head file for BDS Platform specific code
+
+--*/
+
+#ifndef _IOH_BDS_H
+#define _IOH_BDS_H
+
+#include <Protocol/DevicePath.h>
+#include <Library/DevicePathLib.h>
+
+extern EFI_DEVICE_PATH_PROTOCOL *gDeviceConnectOption [];
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+ { \
+ HARDWARE_DEVICE_PATH, \
+ HW_PCI_DP, \
+ { \
+ (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+ }, \
+ (Func), \
+ (Dev) \
+ }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+ { \
+ { \
+ ACPI_DEVICE_PATH, \
+ ACPI_DP, \
+ { \
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ EISA_PNP_ID((PnpId)), \
+ 0 \
+ }
+
+
+
+#define gEndEntire \
+ { \
+ END_DEVICE_PATH_TYPE, \
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, \
+ { \
+ END_DEVICE_PATH_LENGTH, \
+ 0 \
+ } \
+ }
+
+#define gPciRootBridge \
+ PNPID_DEVICE_PATH_NODE(0x0A03)
+
+
+//
+// Platform Root Bridge
+//
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
+
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH IohDevice;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} IOH_PCI_USB_DEVICE_PATH;
+
+//
+// Ioh BDS Functions
+//
+
+
+#endif // _IOH_BDS_H
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohData.c b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohData.c
new file mode 100644
index 0000000..f5fb655
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohData.c
@@ -0,0 +1,77 @@
+/*++
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Module Name:
+
+ IohData.c
+
+Abstract:
+
+ Defined the Ioh device path which will be used by
+ platform Bbd to perform the platform policy connect.
+
+--*/
+
+
+
+#include "IohBds.h"
+
+//
+// Predefined platform root bridge
+//
+PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {
+ gPciRootBridge,
+ gEndEntire
+};
+
+EFI_DEVICE_PATH_PROTOCOL* gPlatformRootBridges [] = {
+ (EFI_DEVICE_PATH_PROTOCOL*)&gPlatformRootBridge0,
+ NULL
+};
+
+
+
+//
+// Ioh USB EHCI controller device path
+//
+IOH_PCI_USB_DEVICE_PATH gIohUsbDevicePath0 = {
+ gPciRootBridge,
+ PCI_DEVICE_PATH_NODE(3, 0x14), // Ioh EHCI Usb device 20, function 3
+ gEndEntire
+};
+
+//
+// Ioh predefined device connecting option
+//
+EFI_DEVICE_PATH_PROTOCOL* gDeviceConnectOption [] = {
+ // (EFI_DEVICE_PATH_PROTOCOL*)&gIohUsbDevicePath0,
+ NULL
+};
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.c b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.c
new file mode 100644
index 0000000..c099db7
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.c
@@ -0,0 +1,80 @@
+/** @file
+QuarkSCSocId module initialization module
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "CommonHeader.h"
+#include "IohBds.h"
+#include "IohInit.h"
+//
+// Definitions
+//
+#define DXE_DEVICE_DISABLED 0
+#define DXE_DEVICE_ENABLED 1
+
+
+EFI_STATUS
+InitializeIohSsvidSsid (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Func
+ );
+
+/**
+ The entry function for IohInit driver.
+
+ This function just call initialization function.
+
+ @param ImageHandle The driver image handle for GmchInit driver
+ @param SystemTable The pointer to System Table
+
+ @retval EFI_SUCCESS Success to initialize every module.
+ @return EFI_STATUS The status of initialization work.
+
+**/
+EFI_STATUS
+EFIAPI
+IohInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+
+ InitializeIohSsvidSsid(IOH_BUS, PCI_IOSF2AHB_0_DEV_NUM, 0);
+
+ InitializeIohSsvidSsid(IOH_BUS, PCI_IOSF2AHB_1_DEV_NUM, 0);
+
+ //Enable Selected IOH Uart port
+ if (PcdGetBool(PcdIohUartEnable)) {
+ IohMmPci8(0, IOH_BUS, PCI_IOSF2AHB_0_DEV_NUM, PcdGet8(PcdIohUartFunctionNumber), PCI_REG_PCICMD) |= 0x7;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.h b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.h
new file mode 100644
index 0000000..28cd392
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.h
@@ -0,0 +1,41 @@
+/** @file
+ Some configuration of IOH Package
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __IOH_INIT_H__
+#define __IOH_INIT_H__
+
+#define IOH_BUS 0
+#define IOH_DEV 0
+#define IOH_FUN 0
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf
new file mode 100644
index 0000000..9d5b316
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf
@@ -0,0 +1,107 @@
+## @file
+# Component description file for Quark South Cluster Init driver.
+#
+# IohInit driver implement QuarkSCSocId related drivers, includes:
+# PciHostBridge, PciExpress, SmmAccess driver and LegacyRegion driver.
+#
+# This driver mainly do full initialization for the Soc chipet includes:
+# 1. Initialize the PCI Express device.
+# 2. Initialize the PciHostBridge, and allocate the I/O and memory space from GCD service.
+# 3. Initialize the SmmAccess module and install EFI_SMM_ACCESS_PROTOCOL
+# 4. Initialize the LegacyRegion module, install EFI_LEGACY_REGION_PROTOCOL and set below 1M
+# memory attribute from MTRR.
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IohInitDxe
+ FILE_GUID = 3FE2A8A3-C400-48F8-832F-7881A394C250
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = IohInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ IohInit.c
+ IohBds.h
+ IohData.c
+ IohInit.h
+ CommonHeader.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ S3BootScriptLib
+ PcdLib
+ HobLib
+ PciLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ S3PciLib
+ UefiLib
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+ UefiDriverEntryPoint
+ BaseLib
+ S3IoLib
+ IoLib
+ DevicePathLib
+ IohLib
+
+[Guids]
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiPciEnumerationCompleteProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiPciIoProtocolGuid
+
+[FeaturePcd]
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartEnable
+
+[FixedPcd]
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartFunctionNumber
+
+[Depex]
+ gEfiPciEnumerationCompleteProtocolGuid
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/CommonHeader.h b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/CommonHeader.h
new file mode 100644
index 0000000..fd2d5c2
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/CommonHeader.h
@@ -0,0 +1,53 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+#include <PiPei.h>
+#include <Ioh.h>
+#include <IohCommonDefinitions.h>
+
+#include <Library/IohLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CpuLib.h>
+#include <Library/PciCf8Lib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Pci22.h>
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.c b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.c
new file mode 100644
index 0000000..195c7b8
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.c
@@ -0,0 +1,81 @@
+/** @file
+ Lib function for Pei Quark South Cluster.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "CommonHeader.h"
+
+#define PCI_IOSF2AHB_0_MAX_FUNCS 7
+#define PCI_IOSF2AHB_1_MAX_FUNCS 3
+
+/**
+ Program SVID/SID the same as VID/DID*
+**/
+EFI_STATUS
+EFIAPI
+InitializeIohSsvidSsid (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Func
+ )
+{
+ UINTN j = 0;
+
+ for (j = 0; j <= PCI_IOSF2AHB_0_MAX_FUNCS; j++)
+ {
+ if (((Device == PCI_IOSF2AHB_1_DEV_NUM) && (j >= PCI_IOSF2AHB_1_MAX_FUNCS)))
+ {
+ continue;
+ }
+
+ IohMmPci32(0, Bus, Device, j, PCI_REG_SVID0) = IohMmPci32(0, Bus, Device, j, PCI_REG_VID);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/* Enable memory, io, and bus master for USB controller */
+VOID
+EFIAPI
+EnableUsbMemIoBusMaster (
+ IN UINT8 UsbBusNumber
+ )
+{
+ UINT16 CmdReg;
+
+ CmdReg = PciRead16 (PCI_LIB_ADDRESS (UsbBusNumber, IOH_USB_OHCI_DEVICE_NUMBER, IOH_OHCI_FUNCTION_NUMBER, PCI_REG_PCICMD));
+ CmdReg = (UINT16) (CmdReg | 0x7);
+ PciWrite16 (PCI_LIB_ADDRESS (UsbBusNumber, IOH_USB_OHCI_DEVICE_NUMBER, IOH_OHCI_FUNCTION_NUMBER, PCI_REG_PCICMD), CmdReg);
+
+ CmdReg = PciRead16 (PCI_LIB_ADDRESS (UsbBusNumber, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, PCI_REG_PCICMD));
+ CmdReg = (UINT16) (CmdReg | 0x7);
+ PciWrite16 (PCI_LIB_ADDRESS (UsbBusNumber, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, PCI_REG_PCICMD), CmdReg);
+}
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf
new file mode 100644
index 0000000..782b506
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf
@@ -0,0 +1,67 @@
+## @file
+# Intel Soc Library Instance
+#
+# Intel Soc Library Instance
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IohLib
+ FILE_GUID = B4C12297-7B19-4523-B165-81374D96716B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = IohLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# HOB Guid C Name: gEfiPciGInfoHobGuid Hob Type: GUID_EXTENSION
+#
+
+[Sources]
+ IohLib.c
+ CommonHeader.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ PciLib
+ IoLib
+ PciCf8Lib
+ BaseLib
+ CpuLib
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.c b/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.c
new file mode 100644
index 0000000..3087b13
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.c
@@ -0,0 +1,406 @@
+/** @file
+ Serial I/O Port library functions with no library constructor/destructor
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: IohSerialPortLib.c
+
+**/
+
+#include <PiPei.h>
+#include <IohAccess.h>
+
+#include <Library/SerialPortLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Protocol/SerialIo.h>
+#include <IndustryStandard/Pci22.h>
+#include "IohSerialPortLib.h"
+
+//
+// Routines local to this source module.
+//
+
+/**
+
+ Get Uart memory mapped base address.
+
+ Apply relavant mask before returning.
+
+ @return Uart memory mapped base address.
+
+**/
+STATIC
+UINT32
+GetUartMmioBaseAddress (
+ VOID
+ )
+{
+ UINT32 RegData32;
+
+ RegData32 = IohMmPci32 (
+ 0,
+ ((UINTN) PcdGet8(PcdIohUartBusNumber)),
+ ((UINTN) PcdGet8(PcdIohUartDevNumber)),
+ ((UINTN) PcdGet8(PcdIohUartFunctionNumber)),
+ PCI_BASE_ADDRESSREG_OFFSET
+ );
+
+ return RegData32 & B_IOH_UART_MEMBAR_ADDRESS_MASK;
+}
+
+/**
+
+ Ensure SerialPortInitialize has been called and return uart Mmio base addr.
+
+ @return Uart memory mapped base address.
+
+**/
+STATIC
+UINT32
+EnsureSerialPortInitialize (
+ VOID
+ )
+{
+ UINT32 UartMmioBase;
+
+ UartMmioBase = GetUartMmioBaseAddress ();
+ if (UartMmioBase == 0 || MmioRead8 (UartMmioBase + R_UART_SCR) != UART_SIGNATURE) {
+ //
+ // Mmio is not intialized or has been reprogrammed
+ // So need to re-initialize the base.
+ //
+ SerialPortInitialize ();
+ UartMmioBase = GetUartMmioBaseAddress ();
+ }
+
+ return UartMmioBase;
+}
+
+//
+// Routines exported by this source module.
+//
+
+/**
+
+ Programmed hardware of IOH Serial port.
+
+ @return Always return EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+IohInitSerialPort (
+ VOID
+ )
+{
+ UINT8 UartFunc;
+ UINT8 RegData8;
+ UINT8 IohUartBus;
+ UINT8 IohUartDev;
+ UINT32 UartMmioBase;
+
+ UartFunc = PcdGet8(PcdIohUartFunctionNumber);
+ IohUartBus = PcdGet8(PcdIohUartBusNumber);
+ IohUartDev = PcdGet8(PcdIohUartDevNumber);
+
+ //
+ // Check PCI memory resource is programmed or not
+ //
+ UartMmioBase = GetUartMmioBaseAddress ();
+ if (UartMmioBase == 0) {
+ UartMmioBase = (UINT32) PcdGet64(PcdIohUartMmioBase);
+ //
+ // Resource not programmed yet, so use predefined tempory memory resource
+ //
+ PciWrite32 (PCI_LIB_ADDRESS(IohUartBus, IohUartDev, UartFunc, PCI_BASE_ADDRESSREG_OFFSET), UartMmioBase);
+ }
+
+ //
+ // Check PCI command register is programmed or not
+ //
+ RegData8 = PciRead8 (PCI_LIB_ADDRESS(IohUartBus, IohUartDev, UartFunc, PCI_COMMAND_OFFSET));
+ if ((RegData8 & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
+ //
+ // Command register is not enabled, so enable it
+ //
+ PciWrite8 (PCI_LIB_ADDRESS(IohUartBus, IohUartDev, UartFunc, PCI_COMMAND_OFFSET), EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ MmioWrite8 (UartMmioBase + R_UART_SCR, UART_SIGNATURE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Programmed serial port controller.
+
+ @return Always return EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ UINT32 Divisor;
+ UINT8 OutputData;
+ UINT32 UartMmioBase;
+
+ UartMmioBase = GetUartMmioBaseAddress ();
+
+ if (UartMmioBase != 0 && MmioRead8 (UartMmioBase + R_UART_SCR) == UART_SIGNATURE) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Some init is done by the platform status code initialization.
+ //
+ IohInitSerialPort ();
+ UartMmioBase = GetUartMmioBaseAddress (); // Ensure correct Mmio Base.
+
+ //
+ // Calculate divisor for baud generator
+ //
+ Divisor = (UINT32)(((UINTN) PcdGet32 (PcdIohUartClkFreq)) / (UINTN)(PcdGet64 (PcdUartDefaultBaudRate)) / 16);
+
+ //
+ // Set communications format
+ //
+ switch (PcdGet8(PcdUartDefaultDataBits)) {
+ case 5:
+ OutputData = 0;
+ break;
+
+ case 6:
+ OutputData = 1;
+ break;
+
+ case 7:
+ OutputData = 2;
+ break;
+
+ case 8:
+ OutputData = 3;
+ break;
+
+ default:
+ OutputData = 0;
+ break;
+ }
+
+ switch (PcdGet8(PcdUartDefaultStopBits)) {
+ case OneFiveStopBits:
+ case TwoStopBits:
+ OutputData |= 0x04;
+ break;
+
+ case OneStopBit:
+ default:
+ OutputData &= 0xFB;
+ break;
+ }
+
+ switch (PcdGet8(PcdUartDefaultParity)) {
+ case EvenParity:
+ OutputData |= 0x18;
+ break;
+
+ case OddParity:
+ OutputData |= 0x08;
+ OutputData &= 0xCF;
+ break;
+
+ case MarkParity:
+ OutputData |= 0x28;
+ break;
+
+ case SpaceParity:
+ OutputData |= 0x38;
+ break;
+
+ case NoParity:
+ default:
+ OutputData &= 0xF7;
+ }
+
+ MmioWrite8 (
+ UartMmioBase + R_UART_LCR,
+ (UINT8)(OutputData | B_UARY_LCR_DLAB)
+ );
+
+ //
+ // Configure baud rate
+ //
+ MmioWrite8 (
+ UartMmioBase + R_UART_BAUD_HIGH,
+ (UINT8) (Divisor >> 8)
+ );
+
+ MmioWrite8 (
+ UartMmioBase + R_UART_BAUD_LOW,
+ (UINT8) (Divisor & 0xff)
+ );
+
+ //
+ // Switch back to bank 0
+ //
+ MmioWrite8 (
+ UartMmioBase + R_UART_LCR,
+ OutputData
+ );
+
+ //
+ // Enable FIFO, reset receive FIFO and transmit FIFO
+ //
+ MmioWrite8 (
+ UartMmioBase + R_UART_FCR,
+ (UINT8) (B_UARY_FCR_TRFIFIE | B_UARY_FCR_RESETRF | B_UARY_FCR_RESETTF)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write data to serial device.
+
+ If the buffer is NULL, then return 0;
+ if NumberOfBytes is zero, then return 0.
+
+ @param Buffer Point of data buffer which need to be writed.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Write data failed.
+ @retval !0 Actual number of bytes writed to serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ UINTN Result;
+ UINT32 UartMmioBase;
+
+ if (NULL == Buffer) {
+ return 0;
+ }
+
+ UartMmioBase = EnsureSerialPortInitialize ();
+
+ Result = NumberOfBytes;
+
+ while (NumberOfBytes--) {
+ //
+ // Wait for the serail port to be ready, to make sure both the transmit FIFO
+ // and shift register empty.
+ //
+ while ((MmioRead8 (UartMmioBase + R_UART_LSR) & B_UART_LSR_TEMT) == 0);
+
+ MmioWrite8 (UartMmioBase + R_UART_BAUD_THR, *Buffer++);
+ }
+
+ return Result;
+}
+
+
+/*
+ Read data from serial device and save the datas in buffer.
+
+ If the buffer is NULL, then return 0;
+ if NumberOfBytes is zero, then return 0.
+
+ @param Buffer Point of data buffer which need to be writed.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Read data failed.
+ @retval !0 Actual number of bytes raed to serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ UINTN Result;
+ UINT32 UartMmioBase;
+
+ if (NULL == Buffer) {
+ return 0;
+ }
+ UartMmioBase = EnsureSerialPortInitialize ();
+
+ Result = NumberOfBytes;
+
+ while (NumberOfBytes--) {
+ //
+ // Wait for the serail port to be ready.
+ //
+ while ((MmioRead8 (UartMmioBase + R_UART_LSR) & B_UART_LSR_RXRDY) == 0);
+
+ *Buffer++ = MmioRead8 (UartMmioBase + R_UART_BAUD_THR);
+ }
+
+ return Result;
+}
+
+
+/**
+ Poll the serial device to see if there is any data waiting.
+
+ If there is data waiting to be read from the serial port, then return
+ TRUE. If there is no data waiting to be read from the serial port, then
+ return FALSE.
+
+ @retval FALSE There is no data waiting to be read.
+ @retval TRUE Data is waiting to be read.
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+ UINT32 UartMmioBase;
+
+ UartMmioBase = EnsureSerialPortInitialize ();
+
+ //
+ // Read the serial port status
+ //
+ return (BOOLEAN)((MmioRead8 (UartMmioBase + R_UART_LSR) & B_UART_LSR_RXRDY) != 0);
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.h b/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.h
new file mode 100644
index 0000000..4c62969
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.h
@@ -0,0 +1,63 @@
+/** @file
+ Header file of Serial Port hardware definition.
+
+ Copyright (c) 2013 Intel Corporation.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Module Name: IohSerialPortLib.h
+
+**/
+
+#ifndef _IOH_SERIAL_PORT_LIB_H_
+#define _IOH_SERIAL_PORT_LIB_H_
+//
+// ---------------------------------------------
+// UART Register Offset and Bitmask of Value
+// ---------------------------------------------
+//
+#define R_UART_BAUD_THR 0
+#define R_UART_BAUD_LOW 0
+#define R_UART_BAUD_HIGH 0x04
+#define R_UART_IER 0x04
+#define R_UART_FCR 0x08
+#define B_UARY_FCR_TRFIFIE BIT0
+#define B_UARY_FCR_RESETRF BIT1
+#define B_UARY_FCR_RESETTF BIT2
+#define R_UART_LCR 0x0C
+#define B_UARY_LCR_DLAB BIT7
+#define R_UART_MCR 0x10
+#define R_UART_LSR 0x14
+#define B_UART_LSR_RXRDY BIT0
+#define B_UART_LSR_TXRDY BIT5
+#define B_UART_LSR_TEMT BIT6
+#define R_UART_MSR 0x18
+#define R_UART_SCR 0x1C
+
+#define UART_SIGNATURE 0x55
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.inf b/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.inf
new file mode 100644
index 0000000..9396dde
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Library/IohSerialPortLib/IohSerialPortLib.inf
@@ -0,0 +1,74 @@
+## @file
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IohSerialPortLib
+ FILE_GUID = ba1a6b82-be5c-4dd6-8c49-2cd605e1bdf2
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ IohSerialPortLib.c
+ IohSerialPortLib.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PciLib
+ IoLib
+ PcdLib
+
+[FeaturePcd]
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+ gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartFunctionNumber
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartBusNumber
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartDevNumber
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartMmioBase
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartClkFreq
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.c
new file mode 100644
index 0000000..dba8af4
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.c
@@ -0,0 +1,251 @@
+/** @file
+
+ UEFI Component Name(2) protocol implementation for SD controller driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "SDController.h"
+
+
+//
+// EFI Component Name Protocol
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSDControllerName = {
+ SDControllerGetDriverName,
+ SDControllerGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSDControllerName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SDControllerGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SDControllerGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSDControllerDriverNameTable[] = {
+ { "eng;en", L"EFI SD Host Controller Driver" },
+ { NULL, NULL }
+};
+
+
+//
+// EFI Component Name Functions
+//
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mSDControllerDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gSDControllerName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ SDHOST_DATA *SDHostData;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure this driver is currently managing ControllerHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gSDControllerDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSDHostIoProtocolGuid,
+ (VOID **) &SDHostIo,
+ gSDControllerDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SDHostData = SDHOST_DATA_FROM_THIS(SDHostIo);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ SDHostData->ControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gSDControllerName)
+ );
+
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.h b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.h
new file mode 100644
index 0000000..dc95f6e
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.h
@@ -0,0 +1,165 @@
+/** @file
+
+ This file contains the delarations for componet name routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#ifndef _COMPONENT_NAME_H_
+#define _COMPONENT_NAME_H_
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.c
new file mode 100755
index 0000000..c711d69
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.c
@@ -0,0 +1,1701 @@
+/** @file
+
+ The SD host controller driver model and HC protocol routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#include "SDController.h"
+
+
+EFI_DRIVER_BINDING_PROTOCOL gSDControllerDriverBinding = {
+ SDControllerSupported,
+ SDControllerStart,
+ SDControllerStop,
+ 0x20,
+ NULL,
+ NULL
+};
+
+
+EFI_SD_HOST_IO_PROTOCOL mSDHostIo = {
+ EFI_SD_HOST_IO_PROTOCOL_REVISION_01,
+ {
+ 0, // HighSpeedSupport
+ 0, // V18Support
+ 0, // V30Support
+ 0, // V33Support
+ 0, // Reserved0
+ 0, // BusWidth4
+ 0, // BusWidth8
+ 0, // Reserved1
+ (512 * 1024) //BoundarySize
+ },
+ SendCommand,
+ SetClockFrequency,
+ SetBusWidth,
+ SetHostVoltage,
+ ResetSDHost,
+ EnableAutoStopCmd,
+ DetectCardAndInitHost,
+ SetBlockLength,
+ HighSpeedMode
+};
+
+/**
+ Find sdclk_freq_sel and upr_sdclk_freq_sel bits
+ for Clock Control Register (CLK_CTL)Offset 2Ch when using 8bit or 10bit
+ divided clock mode.
+
+ @param BaseClockFreg Base Clock Frequency in Hz For SD Clock in the
+ Capabilities register.
+ @param TargetFreq Target Frequency in Hz to reach.
+ @param Is8BitMode True if 8-bit Divided Clock Mode else 10bit mode.
+ @param Bits sdclk_freq_sel and upr_sdclk_freq_sel bits for
+ TargetFreq.
+
+ @return EFI_SUCCESS // Bits setup.
+ @return EFI_UNSUPPORTED // Cannot divide base clock to reach target clock.
+**/
+STATIC
+EFI_STATUS
+DividedClockModeBits (
+ IN CONST UINTN BaseClockFreg,
+ IN CONST UINTN TargetFreq,
+ IN CONST BOOLEAN Is8BitMode,
+ OUT UINT16 *Bits
+ )
+{
+ UINTN N;
+ UINTN CurrFreq;
+
+ *Bits = 0;
+ CurrFreq = BaseClockFreg;
+ N = 0;
+ //
+ // N == 0 same for 8bit & 10bit mode i.e. BaseClockFreg of controller.
+ //
+ if (TargetFreq < CurrFreq) {
+ if (Is8BitMode) {
+ N = 1;
+ do {
+ //
+ // N values for 8bit mode when N > 0.
+ // Bit[15:8] SDCLK Frequency Select at offset 2Ch
+ // 80h - base clock divided by 256
+ // 40h - base clock divided by 128
+ // 20h - base clock divided by 64
+ // 10h - base clock divided by 32
+ // 08h - base clock divided by 16
+ // 04h - base clock divided by 8
+ // 02h - base clock divided by 4
+ // 01h - base clock divided by 2
+ //
+ CurrFreq = BaseClockFreg / (2 * N);
+ if (TargetFreq >= CurrFreq) {
+ break;
+ }
+ N *= 2;
+ if (N > V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL) {
+ return EFI_UNSUPPORTED;
+ }
+ } while (TRUE);
+ } else {
+ N = 1;
+ CurrFreq = BaseClockFreg / (2 * N);
+ //
+ // (try N = 0 or 1 first since don't want divide by 0).
+ //
+ if (TargetFreq < CurrFreq) {
+ //
+ // If still no match then calculate it for 10bit.
+ // N values for 10bit mode.
+ // N 1/2N Divided Clock (Duty 50%).
+ // from Spec "The length of divider is extended to 10 bits and all
+ // divider values shall be supported.
+ //
+ N = (BaseClockFreg / TargetFreq) / 2;
+
+ //
+ // Can only be N or N+1;
+ //
+ CurrFreq = BaseClockFreg / (2 * N);
+ if (TargetFreq < CurrFreq) {
+ N++;
+ CurrFreq = BaseClockFreg / (2 * N);
+ }
+
+ if (N > V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Set upper bits of SDCLK Frequency Select (bits 7:6 of reg 0x2c).
+ //
+ *Bits |= ((UINT16) ((N >> 2) & B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK));
+ }
+ }
+ }
+
+ //
+ // Set lower bits of SDCLK Frequency Select (bits 15:8 of reg 0x2c).
+ //
+ *Bits |= ((UINT16) ((UINT8) N) << 8);
+ DEBUG (
+ (EFI_D_INFO,
+ "SDIO:DividedClockModeBits: %dbit mode Want %dHz Got %dHz bits = %04x\r\n",
+ (Is8BitMode) ? 8 : 10,
+ TargetFreq,
+ CurrFreq,
+ (UINTN) *Bits
+ ));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Print type of error and command index
+
+ @param CommandIndex Command index to set the command index field of command register.
+ @param ErrorCode Error interrupt status read from host controller
+
+ @return EFI_DEVICE_ERROR
+ @return EFI_TIMEOUT
+ @return EFI_CRC_ERROR
+
+**/
+STATIC
+EFI_STATUS
+GetErrorReason (
+ IN UINT16 CommandIndex,
+ IN UINT16 ErrorCode
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_DEVICE_ERROR;
+
+ DEBUG((EFI_D_ERROR, "[%2d] -- ", CommandIndex));
+
+ if (ErrorCode & BIT0) {
+ Status = EFI_TIMEOUT;
+ DEBUG((EFI_D_ERROR, "Command Timeout Erro"));
+ }
+
+ if (ErrorCode & BIT1) {
+ Status = EFI_CRC_ERROR;
+ DEBUG((EFI_D_ERROR, "Command CRC Error"));
+ }
+
+ if (ErrorCode & BIT2) {
+ DEBUG((EFI_D_ERROR, "Command End Bit Error"));
+ }
+
+ if (ErrorCode & BIT3) {
+ DEBUG((EFI_D_ERROR, "Command Index Error"));
+ }
+ if (ErrorCode & BIT4) {
+ Status = EFI_TIMEOUT;
+ DEBUG((EFI_D_ERROR, "Data Timeout Error"));
+ }
+
+ if (ErrorCode & BIT5) {
+ Status = EFI_CRC_ERROR;
+ DEBUG((EFI_D_ERROR, "Data CRC Error"));
+ }
+
+ if (ErrorCode & BIT6) {
+ DEBUG((EFI_D_ERROR, "Data End Bit Error"));
+ }
+
+ if (ErrorCode & BIT7) {
+ DEBUG((EFI_D_ERROR, "Current Limit Error"));
+ }
+
+ if (ErrorCode & BIT8) {
+ DEBUG((EFI_D_ERROR, "Auto CMD12 Error"));
+ }
+
+ if (ErrorCode & BIT9) {
+ DEBUG((EFI_D_ERROR, "ADMA Error"));
+ }
+
+ DEBUG((EFI_D_ERROR, "\n"));
+
+ return Status;
+}
+/**
+ Enable/Disable High Speed transfer mode
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Enable TRUE to Enable, FALSE to Disable
+
+ @return EFI_SUCCESS
+**/
+EFI_STATUS
+HighSpeedMode (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ UINT32 Data;
+ SDHOST_DATA *SDHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SDHostData->PciIo;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ if (Enable) {
+ if (PcdGetBool(PcdSdHciQuirkNoHiSpd)) {
+ DEBUG ((EFI_D_INFO, "SDIO: Quirk never set High Speed Enable bit\r\n"));
+ return EFI_SUCCESS;
+ }
+ DEBUG ((EFI_D_INFO, "Enable High Speed transfer mode ... \r\n"));
+ Data |= BIT2;
+ } else {
+ Data &= ~BIT2;
+ }
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+ return EFI_SUCCESS;
+}
+/**
+ Power on/off the LED associated with the slot
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Enable TRUE to set LED on, FALSE to set LED off
+
+ @return EFI_SUCCESS
+**/
+STATIC
+EFI_STATUS
+HostLEDEnable (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ SDHOST_DATA *SDHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 Data;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SDHostData->PciIo;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ if (Enable) {
+ //
+ //LED On
+ //
+ Data |= BIT0;
+ } else {
+ //
+ //LED Off
+ //
+ Data &= ~BIT0;
+ }
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The main function used to send the command to the card inserted into the SD host slot.
+ It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param CommandIndex The command index to set the command index field of command register.
+ @param Argument Command argument to set the argument field of command register.
+ @param DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param Buffer Contains the data read from / write to the device.
+ @param BufferSize The size of the buffer.
+ @param ResponseType RESPONSE_TYPE.
+ @param TimeOut Time out value in 1 ms unit.
+ @param ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+ @retval EFI_TIMEOUT
+ @retval EFI_DEVICE_ERROR
+
+**/
+
+EFI_STATUS
+EFIAPI
+SendCommand (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData OPTIONAL
+ )
+/*++
+
+ Routine Description:
+ The main function used to send the command to the card inserted into the SD host
+ slot.
+ It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData
+
+ Arguments:
+ This - Pointer to EFI_SD_HOST_IO_PROTOCOL
+ CommandIndex - The command index to set the command index field of command register
+ Argument - Command argument to set the argument field of command register
+ DataType - TRANSFER_TYPE, indicates no data, data in or data out
+ Buffer - Contains the data read from / write to the device
+ BufferSize - The size of the buffer
+ ResponseType - RESPONSE_TYPE
+ TimeOut - Time out value in 1 ms unit
+ ResponseData - Depending on the ResponseType, such as CSD or card status
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_OUT_OF_RESOURCES
+ EFI_TIMEOUT
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ EFI_STATUS Status;
+ SDHOST_DATA *SDHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 ResponseDataCount;
+ UINT32 Data;
+ UINT64 Data64;
+ UINT8 Index;
+
+
+ Status = EFI_SUCCESS;
+ ResponseDataCount = 1;
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SDHostData->PciIo;
+
+ if (Buffer != NULL && DataType == NoData) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
+ goto Exit;
+ }
+
+ if (((UINTN)Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN)NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
+ goto Exit;
+ }
+
+ DEBUG ((EFI_D_INFO, "SendCommand: Command Index = %d \r\n", CommandIndex));
+ //
+ //Clear status bits
+ //
+ Data = 0x1FF;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_NINTSTS,
+ 1,
+ &Data
+ );
+
+ Data = 0x1FF;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_ERINTSTS,
+ 1,
+ &Data
+ );
+
+
+ if (Buffer != NULL) {
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64)MMIO_DMAADR,
+ 1,
+ &Buffer
+ );
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_BLKSZ,
+ 1,
+ &Data
+ );
+ Data &= ~(0xFFF);
+ if (BufferSize <= SDHostData->BlockLength) {
+ Data |= (BufferSize | 0x7000);
+ } else {
+ Data |= (SDHostData->BlockLength | 0x7000);
+ }
+
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_BLKSZ,
+ 1,
+ &Data
+ );
+ if (BufferSize <= SDHostData->BlockLength) {
+ Data = 1;
+ } else {
+ Data = BufferSize / SDHostData->BlockLength;
+ }
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_BLKCNT,
+ 1,
+ &Data
+ );
+
+ }
+
+ //
+ //Argument
+ //
+ Data = Argument;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64)MMIO_CMDARG,
+ 1,
+ &Data
+ );
+
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_XFRMODE,
+ 1,
+ &Data
+ );
+
+
+ DEBUG ((EFI_D_INFO, "Transfer mode read = 0x%x \r\n", (Data & 0xFFFF)));
+ //
+ //BIT0 - DMA Enable
+ //BIT2 - Auto Cmd12
+ //
+ if (DataType == InData) {
+ Data |= BIT4 | BIT0;
+ } else if (DataType == OutData){
+ Data &= ~BIT4;
+ Data |= BIT0;
+ }
+
+ if (BufferSize <= SDHostData->BlockLength) {
+ Data &= ~ (BIT5 | BIT1 | BIT2);
+ } else {
+ if (SDHostData->IsAutoStopCmd) {
+ Data |= (BIT5 | BIT1 | BIT2);
+ } else {
+ Data |= (BIT5 | BIT1);
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "Transfer mode write = 0x%x \r\n", (Data & 0xffff)));
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_XFRMODE,
+ 1,
+ &Data
+ );
+ //
+ //Command
+ //
+ //ResponseTypeSelect IndexCheck CRCCheck ResponseType
+ // 00 0 0 NoResponse
+ // 01 0 1 R2
+ // 10 0 0 R3, R4
+ // 10 1 1 R1, R5, R6, R7
+ // 11 1 1 R1b, R5b
+ //
+ switch (ResponseType) {
+ case ResponseNo:
+ Data = (CommandIndex << 8);
+ ResponseDataCount = 0;
+ break;
+
+ case ResponseR1:
+ case ResponseR5:
+ case ResponseR6:
+ case ResponseR7:
+ Data = (CommandIndex << 8) | BIT1 | BIT4| BIT3;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR1b:
+ case ResponseR5b:
+ Data = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR2:
+ Data = (CommandIndex << 8) | BIT0 | BIT3;
+ ResponseDataCount = 4;
+ break;
+
+ case ResponseR3:
+ case ResponseR4:
+ Data = (CommandIndex << 8) | BIT1;
+ ResponseDataCount = 1;
+ break;
+
+ default:
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
+ goto Exit;
+ }
+
+ if (DataType != NoData) {
+ Data |= BIT5;
+ }
+
+ HostLEDEnable (This, TRUE);
+
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_SDCMD,
+ 1,
+ &Data
+ );
+
+
+ Data = 0;
+ do {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_ERINTSTS,
+ 1,
+ &Data
+ );
+
+ if ((Data & 0x1FF) != 0) {
+ Status = GetErrorReason (CommandIndex, (UINT16)Data);
+ DEBUG ((EFI_D_ERROR, "SendCommand: Error happens \r\n"));
+ goto Exit;
+ }
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_NINTSTS,
+ 1,
+ &Data
+ );
+
+ if ((Data & BIT0) == BIT0) {
+ //
+ //Command completed, can read response
+ //
+ if (DataType == NoData) {
+ break;
+ } else {
+ //
+ //Transfer completed
+ //
+ if ((Data & BIT1) == BIT1) {
+ break;
+ }
+ }
+ }
+
+ gBS->Stall (1 * 1000);
+
+ TimeOut --;
+
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((EFI_D_ERROR, "SendCommand: Time out \r\n"));
+ goto Exit;
+ }
+
+ if (ResponseData != NULL) {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64)MMIO_RESP,
+ ResponseDataCount,
+ ResponseData
+ );
+ if (ResponseType == ResponseR2) {
+ //
+ // Adjustment for R2 response
+ //
+ Data = 1;
+ for (Index = 0; Index < ResponseDataCount; Index++) {
+ Data64 = LShiftU64(*ResponseData, 8);
+ *ResponseData = (UINT32)((Data64 & 0xFFFFFFFF) | Data);
+ Data = (UINT32)RShiftU64 (Data64, 32);
+ ResponseData++;
+ }
+ }
+ }
+
+Exit:
+ HostLEDEnable (This, FALSE);
+ return Status;
+}
+
+/**
+ Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.
+ It depends on the max frequency the host can support, divider, and host speed mode.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param MaxFrequency Max frequency in HZ.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+SetClockFrequency (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 MaxFrequency
+ )
+{
+ UINT32 Data;
+ UINT16 FreqSelBits;
+ EFI_STATUS Status;
+ SDHOST_DATA *SDHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 TimeOutCount;
+ UINT32 Revision;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SDHostData->PciIo;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_CTRLRVER,
+ 1,
+ &Revision
+ );
+ Revision &= 0x000000FF;
+
+ Status = DividedClockModeBits (
+ SDHostData->BaseClockInMHz * 1000 * 1000,
+ MaxFrequency,
+ (Revision < SDHCI_SPEC_300),
+ &FreqSelBits
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Cannot reach MaxFrequency with SDHostData->BaseClockInMHz.
+ //
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Data = 0;
+
+ //
+ //Enable internal clock and Stop Clock Enable
+ //
+ Data = BIT0;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ TimeOutCount = TIME_OUT_1S;
+ do {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+ gBS->Stall (1 * 1000);
+ TimeOutCount --;
+ if (TimeOutCount == 0) {
+ DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));
+ return EFI_TIMEOUT;
+ }
+ } while ((Data & BIT1) != BIT1);
+
+ DEBUG ((EFI_D_INFO, "Base Clock In MHz: %d\r\n", SDHostData->BaseClockInMHz));
+ HighSpeedMode (
+ This,
+ (MaxFrequency > (25 * 1000 * 1000)) && (This->HostCapability.HighSpeedSupport)
+ );
+
+ Data = (BIT0 | ((UINT32) FreqSelBits));
+ DEBUG ((EFI_D_INFO, "Data write to MMIO_CLKCTL: 0x%04x \r\n", Data));
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ TimeOutCount = TIME_OUT_1S;
+ do {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+ gBS->Stall (1 * 1000);
+ TimeOutCount --;
+ if (TimeOutCount == 0) {
+ DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));
+ return EFI_TIMEOUT;
+ }
+ } while ((Data & BIT1) != BIT1);
+ gBS->Stall (20 * 1000);
+ Data |= BIT2;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_CLKCTL,
+ 1,
+ &Data
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set bus width of the host controller
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param BusWidth Bus width in 1, 4, 8 bits.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusWidth (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BusWidth
+ )
+{
+ SDHOST_DATA *SDHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Data;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+
+
+ if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) {
+ DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((SDHostData->SDHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) {
+ DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciIo = SDHostData->PciIo;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+ //
+ // BIT5 8-bit MMC Support (MMC8):
+ // If set, IOH supports 8-bit MMC. When cleared, IOH does not support this feature
+ //
+ if (BusWidth == 8) {
+ DEBUG ((EFI_D_INFO, "Bus Width is 8-bit ... \r\n"));
+ Data |= BIT5;
+ } else if (BusWidth == 4) {
+ DEBUG ((EFI_D_INFO, "Bus Width is 4-bit ... \r\n"));
+ Data &= ~BIT5;
+ Data |= BIT1;
+ } else {
+ DEBUG ((EFI_D_INFO, "Bus Width is 1-bit ... \r\n"));
+ Data &= ~BIT5;
+ Data &= ~BIT1;
+ }
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_HOSTCTL,
+ 1,
+ &Data
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set voltage which could supported by the host controller.
+ Support 0(Power off the host), 1.8V, 3.0V, 3.3V
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Voltage Units in 0.1 V.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostVoltage (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 Voltage
+ )
+{
+ SDHOST_DATA *SDHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Data;
+ EFI_STATUS Status;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SDHostData->PciIo;
+ Status = EFI_SUCCESS;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_PWRCTL,
+ 1,
+ &Data
+ );
+
+ if (Voltage == 0) {
+ //
+ //Power Off the host
+ //
+ Data &= ~BIT0;
+ } else if (Voltage <= 18 && This->HostCapability.V18Support) {
+ //
+ //1.8V
+ //
+ Data |= (BIT1 | BIT3 | BIT0);
+ } else if (Voltage > 18 && Voltage <= 30 && This->HostCapability.V30Support) {
+ //
+ //3.0V
+ //
+ Data |= (BIT2 | BIT3 | BIT0);
+ } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) {
+ //
+ //3.3V
+ //
+ Data |= (BIT1 | BIT2 | BIT3 | BIT0);
+ } else {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_PWRCTL,
+ 1,
+ &Data
+ );
+ gBS->Stall (10 * 1000);
+
+Exit:
+ return Status;
+}
+
+
+
+/**
+ Reset the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param ResetAll TRUE to reset all.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+ResetSDHost (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN RESET_TYPE ResetType
+ )
+{
+ SDHOST_DATA *SDHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 Data;
+ UINT16 ErrStatus;
+ UINT32 Mask;
+ UINT32 TimeOutCount;
+ UINT16 SaveClkCtl;
+ UINT16 ZeroClkCtl;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SDHostData->PciIo;
+ Mask = 0;
+ ErrStatus = 0;
+
+ if (ResetType == Reset_Auto) {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_ERINTSTS,
+ 1,
+ &ErrStatus
+ );
+ if ((ErrStatus & 0xF) != 0) {
+ //
+ //Command Line
+ //
+ Mask |= BIT1;
+ }
+ if ((ErrStatus & 0x70) != 0) {
+ //
+ //Data Line
+ //
+ Mask |= BIT2;
+ }
+ }
+
+
+ if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) {
+ Mask |= BIT2;
+ }
+ if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) {
+ Mask |= BIT1;
+ }
+ if (ResetType == Reset_All) {
+ Mask = BIT0;
+ }
+
+ if (Mask == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // To improve SD stability, we zero the MMIO_CLKCTL register and
+ // stall for 50 microseconds before reseting the controller. We
+ // restore the register setting following the reset operation.
+ //
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_CLKCTL,
+ 1,
+ &SaveClkCtl
+ );
+
+ ZeroClkCtl = (UINT16) 0;
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_CLKCTL,
+ 1,
+ &ZeroClkCtl
+ );
+
+ gBS->Stall (50);
+
+ //
+ // Reset the SD host controller
+ //
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_SWRST,
+ 1,
+ &Mask
+ );
+
+ Data = 0;
+ TimeOutCount = TIME_OUT_1S;
+ do {
+
+ gBS->Stall (1 * 1000);
+
+ TimeOutCount --;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_SWRST,
+ 1,
+ &Data
+ );
+ if ((Data & Mask) == 0) {
+ break;
+ }
+ } while (TimeOutCount > 0);
+
+ //
+ // We now restore the MMIO_CLKCTL register which we set to 0 above.
+ //
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_CLKCTL,
+ 1,
+ &SaveClkCtl
+ );
+
+ if (TimeOutCount == 0) {
+ DEBUG ((EFI_D_ERROR, "ResetSDHost: Time out \r\n"));
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Enable auto stop on the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Enable TRUE to enable, FALSE to disable.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+EnableAutoStopCmd (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ SDHOST_DATA *SDHostData;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+
+ SDHostData->IsAutoStopCmd = Enable;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the Block length on the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param BlockLength card supportes block length.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+SetBlockLength (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BlockLength
+ )
+{
+ SDHOST_DATA *SDHostData;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+
+ DEBUG ((EFI_D_INFO, "Block length on the host controller: %d \r\n", BlockLength));
+ SDHostData->BlockLength = BlockLength;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Find whether these is a card inserted into the slot. If so init the host.
+ If not, return EFI_NOT_FOUND.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_FOUND
+
+**/
+EFI_STATUS
+EFIAPI
+DetectCardAndInitHost (
+ IN EFI_SD_HOST_IO_PROTOCOL *This
+ )
+{
+ SDHOST_DATA *SDHostData;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 Data;
+ EFI_STATUS Status;
+ UINT8 Voltages[] = { 33, 30, 18 };
+ UINTN Loop;
+
+ SDHostData = SDHOST_DATA_FROM_THIS (This);
+ PciIo = SDHostData->PciIo;
+ Status = EFI_NOT_FOUND;
+
+ Data = 0;
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64)MMIO_PSTATE,
+ 1,
+ &Data
+ );
+
+ if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) {
+ //
+ // Has no card inserted
+ //
+ DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: No Cards \r\n"));
+ goto Exit;
+ }
+ DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: Find Cards \r\n"));
+
+ for (Loop = 0; Loop < sizeof (Voltages); Loop++) {
+ DEBUG ((
+ EFI_D_INFO,
+ "DetectCardAndInitHost: SetHostVoltage %d.%dV \r\n",
+ Voltages[Loop] / 10,
+ Voltages[Loop] % 10
+ ));
+ Status = SetHostVoltage (This, Voltages[Loop]);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [failed]\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [done]\n"));
+ break;
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set voltage \r\n"));
+ goto Exit;
+ }
+
+ Status = SetClockFrequency (This, FREQUENCY_OD);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set frequency \r\n"));
+ goto Exit;
+ }
+
+ //
+ //Enable normal status change
+ //
+
+ Data = (BIT0 | BIT1);
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_NINTEN,
+ 1,
+ &Data
+ );
+
+ //
+ //Enable error status change
+ //
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_ERINTEN,
+ 1,
+ &Data
+ );
+
+ Data |= (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8);
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0,
+ (UINT64)MMIO_ERINTEN,
+ 1,
+ &Data
+ );
+
+ //
+ //Data transfer Timeout control
+ //
+ Data = 0x0E;
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_TOCTL,
+ 1,
+ &Data
+ );
+ //
+ //Set Default Bus width as 1 bit
+ //
+ SetBusWidth (This, 1);
+
+Exit:
+ return Status;
+
+}
+
+/**
+ Entry point for EFI drivers.
+
+ @param ImageHandle EFI_HANDLE.
+ @param SystemTable EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS Driver is successfully loaded.
+ @return Others Failed.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSDController (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSDControllerDriverBinding,
+ ImageHandle,
+ &gSDControllerName,
+ &gSDControllerName2
+ );
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has SDHostIoProtocol installed will be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS OpenStatus;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_CLASSC PciClass;
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (OpenStatus)) {
+ return OpenStatus;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (PCI_CLASSC) / sizeof (UINT8),
+ &PciClass
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Test whether the controller belongs to SD type
+ //
+ if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) ||
+ (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER)
+ ) {
+
+ Status = EFI_UNSUPPORTED;
+ }
+
+ON_EXIT:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+/**
+ Starting the SD Host Controller Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ SDHOST_DATA *SDHostData;
+ UINT32 Data;
+ UINT32 Revision;
+
+
+ SDHostData = NULL;
+ Data = 0;
+
+ //
+ // Open PCI I/O Protocol and save pointer to open protocol
+ // in private data area.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Enable the SD Host Controller MMIO space
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+
+ SDHostData = (SDHOST_DATA*)AllocateZeroPool(sizeof (SDHOST_DATA));
+ if (SDHostData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ SDHostData->Signature = SDHOST_DATA_SIGNATURE;
+ SDHostData->PciIo = PciIo;
+
+ CopyMem (&SDHostData->SDHostIo, &mSDHostIo, sizeof (EFI_SD_HOST_IO_PROTOCOL));
+
+ ResetSDHost (&SDHostData->SDHostIo, Reset_All);
+
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ (UINT64)MMIO_CAP,
+ 1,
+ &Data
+ );
+ if ((Data & BIT18) != 0) {
+ SDHostData->SDHostIo.HostCapability.BusWidth8 = TRUE;
+ }
+
+ if ((Data & BIT21) != 0) {
+ SDHostData->SDHostIo.HostCapability.HighSpeedSupport = TRUE;
+ }
+
+ if ((Data & BIT24) != 0) {
+ SDHostData->SDHostIo.HostCapability.V33Support = TRUE;
+ }
+
+ if ((Data & BIT25) != 0) {
+ SDHostData->SDHostIo.HostCapability.V30Support = TRUE;
+ }
+
+ if ((Data & BIT26) != 0) {
+ SDHostData->SDHostIo.HostCapability.V18Support = TRUE;
+ }
+
+ SDHostData->SDHostIo.HostCapability.BusWidth4 = TRUE;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ (UINT64)MMIO_CTRLRVER,
+ 1,
+ &Revision
+ );
+
+
+
+ Revision &= 0x000000FF;
+ if(Revision < SDHCI_SPEC_300) {
+ SDHostData->BaseClockInMHz = (Data >> 8) & 0x3F;
+ }
+ else {
+ SDHostData->BaseClockInMHz = (Data >> 8) & 0xFF;
+
+ }
+
+ SDHostData->BlockLength = BLOCK_SIZE;
+ SDHostData->IsAutoStopCmd = TRUE;
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiSDHostIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &SDHostData->SDHostIo
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Install the component name protocol
+ //
+ SDHostData->ControllerNameTable = NULL;
+
+ AddUnicodeString2 (
+ "eng",
+ gSDControllerName.SupportedLanguages,
+ &SDHostData->ControllerNameTable,
+ L"SD Host Controller",
+ TRUE
+ );
+ AddUnicodeString2 (
+ "en",
+ gSDControllerName2.SupportedLanguages,
+ &SDHostData->ControllerNameTable,
+ L"SD Host Controller",
+ FALSE
+ );
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ if (SDHostData != NULL) {
+ FreePool (SDHostData);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ SDHOST_DATA *SDHostData;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSDHostIoProtocolGuid,
+ (VOID **) &SDHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ //
+ // Test whether the Controller handler passed in is a valid
+ // Usb controller handle that should be supported, if not,
+ // return the error status directly
+ //
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SetHostVoltage (SDHostIo, 0);
+
+ SDHostData = SDHOST_DATA_FROM_THIS(SDHostIo);
+
+ //
+ // Uninstall Block I/O protocol from the device handle
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiSDHostIoProtocolGuid,
+ SDHostIo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FreeUnicodeStringTable (SDHostData->ControllerNameTable);
+
+ FreePool (SDHostData);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.h b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.h
new file mode 100644
index 0000000..60810d0
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.h
@@ -0,0 +1,334 @@
+/** @file
+
+ The definition for SD host controller driver model and HC protocol routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SD_CONTROLLER_H_
+#define _SD_CONTROLLER_H_
+
+
+#include <Uefi.h>
+
+
+#include <Protocol/PciIo.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Pci22.h>
+
+
+#include "ComponentName.h"
+#include "SDHostIo.h"
+
+
+extern EFI_DRIVER_BINDING_PROTOCOL gSDControllerDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gSDControllerName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gSDControllerName2;
+
+
+#define SDHOST_DATA_SIGNATURE SIGNATURE_32 ('s', 'd', 'h', 's')
+
+#define BLOCK_SIZE 0x200
+#define TIME_OUT_1S 1000
+
+#pragma pack(1)
+//
+// PCI Class Code structure
+//
+typedef struct {
+ UINT8 PI;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} PCI_CLASSC;
+
+#pragma pack()
+
+
+typedef struct {
+ UINTN Signature;
+ EFI_SD_HOST_IO_PROTOCOL SDHostIo;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ BOOLEAN IsAutoStopCmd;
+ UINT32 BaseClockInMHz;
+ UINT32 CurrentClockInKHz;
+ UINT32 BlockLength;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+}SDHOST_DATA;
+
+#define SDHOST_DATA_FROM_THIS(a) \
+ CR(a, SDHOST_DATA, SDHostIo, SDHOST_DATA_SIGNATURE)
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has SDHostIoProtocol installed will be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starting the SD Host Controller Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+SDControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ The main function used to send the command to the card inserted into the SD host slot.
+ It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param CommandIndex The command index to set the command index field of command register.
+ @param Argument Command argument to set the argument field of command register.
+ @param DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param Buffer Contains the data read from / write to the device.
+ @param BufferSize The size of the buffer.
+ @param ResponseType RESPONSE_TYPE.
+ @param TimeOut Time out value in 1 ms unit.
+ @param ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+ @retval EFI_TIMEOUT
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+SendCommand (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData OPTIONAL
+ );
+
+/**
+ Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.
+ It depends on the max frequency the host can support, divider, and host speed mode.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param MaxFrequency Max frequency in HZ.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+SetClockFrequency (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 MaxFrequencyInKHz
+ );
+
+/**
+ Set bus width of the host controller
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param BusWidth Bus width in 1, 4, 8 bits.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusWidth (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BusWidth
+ );
+
+
+/**
+ Set voltage which could supported by the host controller.
+ Support 0(Power off the host), 1.8V, 3.0V, 3.3V
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Voltage Units in 0.1 V.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+EFIAPI
+SetHostVoltage (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 Voltage
+ );
+
+
+/**
+ Reset the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param ResetAll TRUE to reset all.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+ResetSDHost (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN RESET_TYPE ResetType
+ );
+
+
+/**
+ Enable auto stop on the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Enable TRUE to enable, FALSE to disable.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+EnableAutoStopCmd (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+/**
+ Find whether these is a card inserted into the slot. If so init the host.
+ If not, return EFI_NOT_FOUND.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_FOUND
+
+**/
+EFI_STATUS
+EFIAPI
+DetectCardAndInitHost (
+ IN EFI_SD_HOST_IO_PROTOCOL *This
+ );
+
+/**
+ Set the Block length on the host controller.
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param BlockLength card supportes block length.
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+
+**/
+EFI_STATUS
+EFIAPI
+SetBlockLength (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT32 BlockLength
+ );
+
+/**
+ Enable/Disable High Speed transfer mode
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param Enable TRUE to Enable, FALSE to Disable
+
+ @return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+HighSpeedMode (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf
new file mode 100644
index 0000000..a4f8b08
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf
@@ -0,0 +1,82 @@
+## @file
+#
+# Component Description File For SDControllerDxe Module.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SDController
+ FILE_GUID = 90A330BD-6F89-4900-933A-C25EB4356348
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSDController
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gSDControllerDriverBinding
+# COMPONENT_NAME = gSDControllerName
+# COMPONENT_NAME2 = gSDControllerName2
+#
+
+[Sources]
+ SDController.c
+ SDController.h
+ ComponentName.c
+ ComponentName.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+# DebugLibConOut
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiSDHostIoProtocolGuid ## BY_START
+
+[FeaturePcd]
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdSdHciQuirkNoHiSpd
+
+[Pcd.common]
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c
new file mode 100644
index 0000000..9baa848
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c
@@ -0,0 +1,676 @@
+/** @file
+
+ CEATA specific functions implementation
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "SDMediaDevice.h"
+
+/**
+ Send RW_MULTIPLE_REGISTER command
+
+ @param CardData Pointer to CARD_DATA.
+ @param Address Register address.
+ @param ByteCount Buffer size.
+ @param Write TRUE means write, FALSE means read.
+ @param Buffer Buffer pointer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadWriteMultipleRegister (
+ IN CARD_DATA *CardData,
+ IN UINT16 Address,
+ IN UINT8 ByteCount,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ EFI_STATUS Status;
+ UINT32 Argument;
+
+ Status = EFI_SUCCESS;
+ SDHostIo = CardData->SDHostIo;
+
+ if ((Address % 4 != 0) || (ByteCount % 4 != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Argument = (Address << 16) | ByteCount;
+ if (Write) {
+ Argument |= BIT31;
+ }
+
+
+ if (Write) {
+ CopyMem (CardData->AlignedBuffer, Buffer, ByteCount);
+
+ Status = SendCommand (
+ SDHostIo,
+ RW_MULTIPLE_REGISTER,
+ Argument,
+ OutData,
+ CardData->AlignedBuffer,
+ ByteCount,
+ ResponseR1b,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ } else {
+ Status = SendCommand (
+ SDHostIo,
+ RW_MULTIPLE_REGISTER,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ ByteCount,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Buffer, CardData->AlignedBuffer, ByteCount);
+ }
+
+ }
+Exit:
+ return Status;
+}
+
+/**
+ Send ReadWriteMultipleBlock command with RW_MULTIPLE_REGISTER command
+
+ @param CardData Pointer to CARD_DATA.
+ @param DataUnitCount Buffer size in 512 bytes unit.
+ @param Write TRUE means write, FALSE means read.
+ @param Buffer Buffer pointer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadWriteMultipleBlock (
+ IN CARD_DATA *CardData,
+ IN UINT16 DataUnitCount,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ EFI_STATUS Status;
+ UINT32 TransferLength;
+
+ Status = EFI_SUCCESS;
+ SDHostIo = CardData->SDHostIo;
+
+ TransferLength = DataUnitCount * DATA_UNIT_SIZE;
+ if (TransferLength > SDHostIo->HostCapability.BoundarySize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Write) {
+ CopyMem (CardData->AlignedBuffer, Buffer, TransferLength);
+
+ Status = SendCommand (
+ SDHostIo,
+ RW_MULTIPLE_BLOCK,
+ (DataUnitCount | BIT31),
+ OutData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1b,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ } else {
+ Status = SendCommand (
+ SDHostIo,
+ RW_MULTIPLE_BLOCK,
+ DataUnitCount,
+ InData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Buffer, CardData->AlignedBuffer, TransferLength);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Send software reset
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SoftwareReset (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data;
+ UINT32 TimeOut;
+
+ Data = BIT2;
+
+ Status = FastIO (CardData, Reg_Control, &Data, TRUE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ TimeOut = 5 * 1000;
+
+ do {
+ gBS->Stall (1 * 1000);
+ Status = FastIO (CardData, Reg_Control, &Data, FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ if ((Data & BIT2) == BIT2) {
+ break;
+ }
+
+ TimeOut--;
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+ Data &= ~BIT2;
+ Status = FastIO (CardData, Reg_Control, &Data, TRUE);
+
+ TimeOut = 5 * 1000;
+
+ do {
+ gBS->Stall (1 * 1000);
+ Status = FastIO (CardData, Reg_Control, &Data, FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ if ((Data & BIT2) != BIT2) {
+ break;
+ }
+
+ TimeOut--;
+ } while (TimeOut > 0);
+
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+
+Exit:
+ return Status;
+}
+
+
+/**
+ SendATACommand specificed in Taskfile
+
+ @param CardData Pointer to CARD_DATA.
+ @param TaskFile Pointer to TASK_FILE.
+ @param Write TRUE means write, FALSE means read.
+ @param Buffer If NULL, means no data transfer, neither read nor write.
+ @param SectorCount Buffer size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SendATACommand (
+ IN CARD_DATA *CardData,
+ IN TASK_FILE *TaskFile,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ UINT8 Data;
+ UINT32 TimeOut;
+
+ SDHostIo = CardData->SDHostIo;
+
+ //
+ //Write register
+ //
+ Status = ReadWriteMultipleRegister (
+ CardData,
+ 0,
+ sizeof (TASK_FILE),
+ TRUE,
+ (UINT8*)TaskFile
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister 0x%x\n", Status));
+ goto Exit;
+ }
+
+ TimeOut = 5000;
+ do {
+ gBS->Stall (1 * 1000);
+ Data = 0;
+ Status = FastIO (
+ CardData,
+ Reg_Command_Status,
+ &Data,
+ FALSE
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (((Data & BIT7) == 0) && ((Data & BIT6) == BIT6)) {
+ break;
+ }
+
+ TimeOut --;
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister FastIO EFI_TIMEOUT 0x%x\n", Data));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+
+ if (Buffer != NULL) {
+ Status = ReadWriteMultipleBlock (
+ CardData,
+ SectorCount,
+ Write,
+ (UINT8*)Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock EFI_TIMEOUT 0x%x\n", Status));
+ goto Exit;
+ }
+
+ TimeOut = 5 * 1000;
+ do {
+ gBS->Stall (1 * 1000);
+
+ Data = 0;
+ Status = FastIO (
+ CardData,
+ Reg_Command_Status,
+ &Data,
+ FALSE
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (((Data & BIT7) == 0) && ((Data & BIT3) == 0)) {
+ break;
+ }
+
+ TimeOut --;
+ } while (TimeOut > 0);
+ if (TimeOut == 0) {
+ DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock FastIO EFI_TIMEOUT 0x%x\n", Data));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+
+ if (((Data & BIT6) == BIT6) && (Data & BIT0) == 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ SoftwareReset (CardData);
+ }
+
+ return Status;
+}
+
+/**
+ IDENTIFY_DEVICE command
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+IndentifyDevice (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ //The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = IDENTIFY_DEVICE;
+
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ (UINT8*)&(CardData->IndentifyDeviceData),
+ 1
+ );
+
+
+ return Status;
+}
+
+/**
+ FLUSH_CACHE_EXT command
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+FlushCache (
+ IN CARD_DATA *CardData
+ )
+{
+
+ //
+ //Hitachi CE-ATA will always make the busy high after
+ //receving this command
+ //
+/*
+ EFI_STATUS Status;
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+ //
+ //The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = FLUSH_CACHE_EXT;
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ NULL,
+ 0
+ );
+*/
+ return EFI_SUCCESS;
+}
+
+/**
+ STANDBY_IMMEDIATE command
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+StandByImmediate (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+ //
+ //The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = STANDBY_IMMEDIATE;
+
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ NULL,
+ 0
+ );
+ return Status;
+}
+
+/**
+ READ_DMA_EXT command
+
+ @param CardData Pointer to CARD_DATA.
+ @param LBA The starting logical block address to read from on the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+ //
+ //The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = READ_DMA_EXT;
+
+ CardData->TaskFile.SectorCount = (UINT8)SectorCount;
+ CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);
+
+ CardData->TaskFile.LBALow = (UINT8)LBA;
+ CardData->TaskFile.LBAMid = (UINT8)RShiftU64(LBA, 8);
+ CardData->TaskFile.LBAHigh = (UINT8)RShiftU64(LBA, 16);
+
+ CardData->TaskFile.LBALow_Exp = (UINT8)RShiftU64(LBA, 24);
+ CardData->TaskFile.LBAMid_Exp = (UINT8)RShiftU64(LBA, 32);
+ CardData->TaskFile.LBAHigh_Exp = (UINT8)RShiftU64(LBA, 40);
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ Buffer,
+ SectorCount
+ );
+ return Status;
+
+}
+
+/**
+ WRITE_DMA_EXT command
+
+ @param CardData Pointer to CARD_DATA.
+ @param LBA The starting logical block address to read from on the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+WriteDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+ //
+ //The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = WRITE_DMA_EXT;
+
+ CardData->TaskFile.SectorCount = (UINT8)SectorCount;
+ CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);
+
+ CardData->TaskFile.LBALow = (UINT8)LBA;
+ CardData->TaskFile.LBAMid = (UINT8)RShiftU64(LBA, 8);
+ CardData->TaskFile.LBAHigh = (UINT8)RShiftU64(LBA, 16);
+
+ CardData->TaskFile.LBALow_Exp = (UINT8)RShiftU64(LBA, 24);
+ CardData->TaskFile.LBAMid_Exp = (UINT8)RShiftU64(LBA, 32);
+ CardData->TaskFile.LBAHigh_Exp = (UINT8)RShiftU64(LBA, 40);
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ TRUE,
+ Buffer,
+ SectorCount
+ );
+ return Status;
+
+}
+
+
+/**
+ Judge whether it is CE-ATA device or not.
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval TRUE
+ @retval FALSE
+
+**/
+BOOLEAN
+IsCEATADevice (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ Status = ReadWriteMultipleRegister (
+ CardData,
+ 0,
+ sizeof (TASK_FILE),
+ FALSE,
+ (UINT8*)&CardData->TaskFile
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ //To bring back the normal MMC card to work
+ //
+ CardData->SDHostIo->ResetSDHost (CardData->SDHostIo, Reset_DAT_CMD);
+ return FALSE;
+ }
+
+ if (CardData->TaskFile.LBAMid == CE_ATA_SIG_CE &&
+ CardData->TaskFile.LBAHigh == CE_ATA_SIG_AA
+ ) {
+ //
+ //Disable Auto CMD for CE-ATA
+ //
+ CardData->SDHostIo->EnableAutoStopCmd (CardData->SDHostIo, FALSE);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c
new file mode 100644
index 0000000..52d24ce
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c
@@ -0,0 +1,414 @@
+/** @file
+
+ Block I/O protocol for CE-ATA device
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "SDMediaDevice.h"
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
+
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param ExtendedVerification Indicates that the driver may perform a more exhaustive.
+ verification operation of the device during reset.
+ (This parameter is ingored in this driver.)
+
+ @retval EFI_SUCCESS Success
+**/
+EFI_STATUS
+EFIAPI
+CEATABlockReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+
+ CardData = CARD_DATA_FROM_THIS(This);
+ SDHostIo = CardData->SDHostIo;
+
+ if (!ExtendedVerification) {
+ Status = SoftwareReset (CardData);
+ } else {
+ Status = SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" ));
+ return Status;
+ }
+ Status = MMCSDCardInit (CardData);
+ }
+
+
+ return Status;
+
+ }
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
+
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param MediaId The media id that the write request is for.
+ @param LBA The starting logical block address to read from on the device.
+ The caller is responsible for writing to only legitimate locations.
+ @param BufferSize The size of the Buffer in bytes. This must be a multiple of the
+ intrinsic block size of the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+**/
+EFI_STATUS
+EFIAPI
+CEATABlockReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ UINT32 TransferSize;
+ UINT8 *pBuf;
+ UINT32 Index;
+ UINT64 Address;
+ UINT32 Remainder;
+ UINT64 CEATALBA;
+ UINT32 BoundarySize;
+
+ Status = EFI_SUCCESS;
+ CardData = CARD_DATA_FROM_THIS(This);
+ pBuf = Buffer;
+ Index = 0;
+ Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);
+ BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));
+ goto Exit;
+ }
+
+ if (MediaId != CardData->BlockIoMedia.MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" ));
+ goto Exit;
+ }
+
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" ));
+ goto Exit;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));
+ goto Exit;
+ }
+
+
+ do {
+ if (BufferSize < BoundarySize) {
+ TransferSize = (UINT32)BufferSize;
+ } else {
+ TransferSize = BoundarySize;
+ }
+
+ Address += Index * TransferSize;
+ CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);
+ ASSERT(Remainder == 0);
+
+ Status = ReadDMAExt (
+ CardData,
+ CEATALBA,
+ pBuf,
+ (UINT16)(TransferSize / DATA_UNIT_SIZE)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));
+ This->Reset (This, TRUE);
+ goto Exit;
+ }
+ BufferSize -= TransferSize;
+ pBuf += TransferSize;
+ Index ++;
+ } while (BufferSize != 0);
+
+
+Exit:
+ return Status;
+}
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
+
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param MediaId The media id that the write request is for.
+ @param LBA The starting logical block address to read from on the device.
+ The caller is responsible for writing to only legitimate locations.
+ @param BufferSize The size of the Buffer in bytes. This must be a multiple of the
+ intrinsic block size of the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+**/
+EFI_STATUS
+EFIAPI
+CEATABlockWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ UINT32 TransferSize;
+ UINT8 *pBuf;
+ UINT32 Index;
+ UINT64 Address;
+ UINT32 Remainder;
+ UINT64 CEATALBA;
+ UINT32 BoundarySize;
+
+
+ Status = EFI_SUCCESS;
+ CardData = CARD_DATA_FROM_THIS(This);
+ pBuf = Buffer;
+ Index = 0;
+ Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);
+ BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;
+
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (MediaId != CardData->BlockIoMedia.MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ goto Exit;
+ }
+
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Exit;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ if (CardData->BlockIoMedia.ReadOnly) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+
+ if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ CardData->NeedFlush = TRUE;
+
+ do {
+ if (BufferSize < BoundarySize) {
+ TransferSize = (UINT32)BufferSize;
+ } else {
+ TransferSize = BoundarySize;
+ }
+
+ Address += Index * TransferSize;
+ CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);
+ ASSERT(Remainder == 0);
+
+ Status = WriteDMAExt (
+ CardData,
+ CEATALBA,
+ pBuf,
+ (UINT16)(TransferSize / DATA_UNIT_SIZE)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));
+ This->Reset (This, TRUE);
+ goto Exit;
+ }
+ BufferSize -= TransferSize;
+ pBuf += TransferSize;
+ Index ++;
+ } while (BufferSize != 0);
+
+
+Exit:
+ return Status;
+}
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
+ (In this driver, this function just returns EFI_SUCCESS.)
+
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval Others
+**/
+EFI_STATUS
+EFIAPI
+CEATABlockFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+
+ CardData = CARD_DATA_FROM_THIS(This);
+
+ if (CardData->NeedFlush) {
+ CardData->NeedFlush = FALSE;
+ Status = FlushCache (CardData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ CEATA card BlockIo init function.
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval Others
+**/
+EFI_STATUS
+CEATABlockIoInit (
+ IN CARD_DATA *CardData
+ )
+/*++
+
+ Routine Description:
+ CEATA card BlockIo init function
+
+ Arguments:
+ CardData - Pointer to CARD_DATA
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 MaxSize;
+ UINT32 Remainder;
+ //
+ //BlockIO protocol
+ //
+ CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
+ CardData->BlockIo.Media = &(CardData->BlockIoMedia);
+ CardData->BlockIo.Reset = CEATABlockReset;
+ CardData->BlockIo.ReadBlocks = CEATABlockReadBlocks ;
+ CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;
+ CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;
+
+ CardData->BlockIoMedia.MediaId = 0;
+ CardData->BlockIoMedia.RemovableMedia = FALSE;
+ CardData->BlockIoMedia.MediaPresent = TRUE;
+ CardData->BlockIoMedia.LogicalPartition = FALSE;
+
+ if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {
+ CardData->BlockIoMedia.ReadOnly = TRUE;
+ } else {
+ CardData->BlockIoMedia.ReadOnly = FALSE;
+ }
+
+
+ CardData->BlockIoMedia.WriteCaching = FALSE;
+ CardData->BlockIoMedia.IoAlign = 1;
+
+ Status = IndentifyDevice (CardData);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ //Some device does not support this feature
+ //
+
+ if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {
+ CardData->BlockIoMedia.ReadOnly = TRUE;
+ }
+
+ CardData->BlockIoMedia.BlockSize = (1 << CardData->IndentifyDeviceData.Sectorsize);
+ ASSERT(CardData->BlockIoMedia.BlockSize >= 12);
+
+
+ MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA);
+ MaxSize = MultU64x32 (MaxSize, 512);
+
+ Remainder = 0;
+ CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);
+ ASSERT(Remainder == 0);
+
+ CardData->BlockIoMedia.LastBlock = (EFI_LBA)(CardData->BlockNumber - 1);
+
+
+Exit:
+ return Status;
+
+}
+
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.c
new file mode 100644
index 0000000..561de7d
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.c
@@ -0,0 +1,239 @@
+/** @file
+
+ UEFI Component Name(2) protocol implementation for SD media device driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "SDMediaDevice.h"
+
+
+//
+// EFI Component Name Protocol
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSDMediaDeviceName = {
+ SDMediaDeviceGetDriverName,
+ SDMediaDeviceGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSDMediaDeviceName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SDMediaDeviceGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SDMediaDeviceGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSDMediaDeviceDriverNameTable[] = {
+ { "eng;en", L"UEFI MMC/SD Media Device Driver" },
+ { NULL, NULL }
+};
+
+
+//
+// EFI Component Name Functions
+//
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mSDMediaDeviceDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gSDMediaDeviceName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ CARD_DATA *CardData;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ gSDMediaDeviceDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CardData = CARD_DATA_FROM_THIS (BlockIo);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ CardData->ControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gSDMediaDeviceName)
+ );
+
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.h b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.h
new file mode 100644
index 0000000..a7dbea2
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.h
@@ -0,0 +1,163 @@
+/** @file
+
+ This file contains the delarations for componet name routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _COMPONENT_NAME_H_
+#define _COMPONENT_NAME_H_
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c
new file mode 100644
index 0000000..ffc2dc0
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c
@@ -0,0 +1,482 @@
+/** @file
+
+ Block I/O protocol for MMC/SD device
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "SDMediaDevice.h"
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
+
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param ExtendedVerification Indicates that the driver may perform a more exhaustive.
+ verification operation of the device during reset.
+ (This parameter is ingored in this driver.)
+
+ @retval EFI_SUCCESS Success
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ CARD_DATA *CardData;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+
+ CardData = CARD_DATA_FROM_THIS(This);
+ SDHostIo = CardData->SDHostIo;
+
+ return SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);
+ }
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
+
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param MediaId The media id that the write request is for.
+ @param LBA The starting logical block address to read from on the device.
+ The caller is responsible for writing to only legitimate locations.
+ @param BufferSize The size of the Buffer in bytes. This must be a multiple of the
+ intrinsic block size of the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ CARD_DATA *CardData;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ UINT32 RemainingLength;
+ UINT32 TransferLength;
+ UINT8 *BufferPointer;
+
+ DEBUG((EFI_D_INFO, "Read(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));
+ Status = EFI_SUCCESS;
+ CardData = CARD_DATA_FROM_THIS(This);
+ SDHostIo = CardData->SDHostIo;
+
+ if (CardData->CardType == SDMemoryCard2High) {
+ //
+ //Block Address
+ //
+ Address = (UINT32)DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);
+ } else {
+ //
+ //Byte Address
+ //
+ Address = (UINT32)MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);
+ }
+
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks:Invalid parameter \r\n"));
+ goto Done;
+ }
+
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Bad buffer size \r\n"));
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+
+ if (BufferSize <= CardData->BlockIoMedia.BlockSize) {
+ Status = SendCommand (
+ SDHostIo,
+ READ_SINGLE_BLOCK,
+ Address,
+ InData,
+ CardData->AlignedBuffer,
+ (UINT32)BufferSize,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Buffer, CardData->AlignedBuffer, BufferSize);
+ }
+
+ } else {
+
+ BufferPointer = Buffer;
+ RemainingLength = (UINT32)BufferSize;
+
+ while (RemainingLength > 0) {
+ if (RemainingLength > SDHostIo->HostCapability.BoundarySize) {
+ TransferLength = SDHostIo->HostCapability.BoundarySize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ Status = SendCommand (
+ SDHostIo,
+ READ_MULTIPLE_BLOCK,
+ Address,
+ InData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Fail to send READ_MULTIPLE_BLOCK \r\n"));
+ break;
+ }
+
+ CopyMem (BufferPointer, CardData->AlignedBuffer, TransferLength);
+
+ if (CardData->CardType == SDMemoryCard2High) {
+ //
+ //Block Address
+ //
+ Address += TransferLength / 512;
+ } else {
+ //
+ //Byte Address
+ //
+ Address += TransferLength;
+ }
+ BufferPointer += TransferLength;
+ RemainingLength -= TransferLength;
+ }
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ if ((CardData->CardType == SDMemoryCard) ||
+ (CardData->CardType == SDMemoryCard2)||
+ (CardData->CardType == SDMemoryCard2High)) {
+ SendCommand (
+ SDHostIo,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ } else {
+ SendCommand (
+ SDHostIo,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ }
+
+ }
+
+
+Done:
+ return Status;
+}
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
+
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.
+ @param MediaId The media id that the write request is for.
+ @param LBA The starting logical block address to read from on the device.
+ The caller is responsible for writing to only legitimate locations.
+ @param BufferSize The size of the Buffer in bytes. This must be a multiple of the
+ intrinsic block size of the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ CARD_DATA *CardData;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ UINT32 RemainingLength;
+ UINT32 TransferLength;
+ UINT8 *BufferPointer;
+
+ DEBUG((EFI_D_INFO, "Write(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));
+ Status = EFI_SUCCESS;
+ CardData = CARD_DATA_FROM_THIS(This);
+ SDHostIo = CardData->SDHostIo;
+ if (CardData->CardType == SDMemoryCard2High) {
+ //
+ //Block Address
+ //
+ Address = (UINT32)DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);
+ } else {
+ //
+ //Byte Address
+ //
+ Address = (UINT32)MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);
+ }
+
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Invalid parameter \r\n"));
+ goto Done;
+ }
+
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Bad buffer size \r\n"));
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ if (This->Media->ReadOnly == TRUE) {
+ Status = EFI_WRITE_PROTECTED;
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Write protected \r\n"));
+ goto Done;
+ }
+
+
+ if (BufferSize <= CardData->BlockIoMedia.BlockSize) {
+ CopyMem (CardData->AlignedBuffer, Buffer, BufferSize);
+
+ Status = SendCommand (
+ SDHostIo,
+ WRITE_BLOCK,
+ Address,
+ OutData,
+ CardData->AlignedBuffer,
+ (UINT32)BufferSize,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ } else {
+ BufferPointer = Buffer;
+ RemainingLength = (UINT32)BufferSize;
+
+ while (RemainingLength > 0) {
+ if (RemainingLength > SDHostIo->HostCapability.BoundarySize) {
+ TransferLength = SDHostIo->HostCapability.BoundarySize;
+ } else {
+ TransferLength = RemainingLength;
+ }
+
+ if ((CardData->CardType == SDMemoryCard) ||
+ (CardData->CardType == SDMemoryCard2)||
+ (CardData->CardType == SDMemoryCard2High)) {
+ //
+ // Write performance improvement
+ //
+ if ((TransferLength / CardData->BlockIoMedia.BlockSize) > 64) {
+ Status = SendAppCommand (
+ CardData,
+ SET_WR_BLK_ERASE_COUNT,
+ (UINT32)(TransferLength / CardData->BlockIoMedia.BlockSize),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ }
+ }
+
+ CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);
+
+ Status = SendCommand (
+ SDHostIo,
+ WRITE_MULTIPLE_BLOCK,
+ Address,
+ OutData,
+ CardData->AlignedBuffer,
+ (UINT32)TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Fail to send command WRITE_MULTIPLE_BLOCK \r\n"));
+ break;
+ }
+
+
+ if (CardData->CardType == SDMemoryCard2High) {
+ //
+ //Block Address
+ //
+ Address += TransferLength / 512;
+ } else {
+ //
+ //Byte Address
+ //
+ Address += TransferLength;
+ }
+ BufferPointer += TransferLength;
+ RemainingLength -= TransferLength;
+ }
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ SendCommand (
+ SDHostIo,
+ STOP_TRANSMISSION,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+
+ }
+
+
+Done:
+ return EFI_SUCCESS;
+}
+
+/**
+ Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
+ (In this driver, this function just returns EFI_SUCCESS.)
+
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.
+
+ @retval EFI_SUCCESS
+ @retval Others
+**/
+EFI_STATUS
+EFIAPI
+MMCSDBlockFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ MMC/SD card BlockIo init function.
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval Others
+**/
+EFI_STATUS
+MMCSDBlockIoInit (
+ IN CARD_DATA *CardData
+ )
+{
+ //
+ //BlockIO protocol
+ //
+ CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
+ CardData->BlockIo.Media = &(CardData->BlockIoMedia);
+ CardData->BlockIo.Reset = MMCSDBlockReset;
+ CardData->BlockIo.ReadBlocks = MMCSDBlockReadBlocks ;
+ CardData->BlockIo.WriteBlocks = MMCSDBlockWriteBlocks;
+ CardData->BlockIo.FlushBlocks = MMCSDBlockFlushBlocks;
+
+ CardData->BlockIoMedia.MediaId = 0;
+ CardData->BlockIoMedia.RemovableMedia = FALSE;
+ CardData->BlockIoMedia.MediaPresent = TRUE;
+ CardData->BlockIoMedia.LogicalPartition = FALSE;
+
+ if (CardData->CSDRegister.PERM_WRITE_PROTECT || CardData->CSDRegister.TMP_WRITE_PROTECT) {
+ CardData->BlockIoMedia.ReadOnly = TRUE;
+ } else {
+ CardData->BlockIoMedia.ReadOnly = FALSE;
+ }
+
+
+ CardData->BlockIoMedia.WriteCaching = FALSE;
+ CardData->BlockIoMedia.BlockSize = CardData->BlockLen;
+ CardData->BlockIoMedia.IoAlign = 1;
+ CardData->BlockIoMedia.LastBlock = (EFI_LBA)(CardData->BlockNumber - 1);
+
+
+ return EFI_SUCCESS;
+
+}
+
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c
new file mode 100644
index 0000000..6ae0c5a
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c
@@ -0,0 +1,1730 @@
+/** @file
+
+ MMC/SD transfer specific functions
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "SDMediaDevice.h"
+
+/**
+ Check card status, print the debug info and check the error
+
+ @param Status Status got from card status register.
+
+ @retval EFI_SUCCESS
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+CheckCardStatus (
+ IN UINT32 Status
+ )
+{
+ CARD_STATUS *CardStatus;
+ CardStatus = (CARD_STATUS*)(&Status);
+
+ if (CardStatus->ADDRESS_OUT_OF_RANGE) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_OUT_OF_RANGE\n"));
+ }
+
+ if (CardStatus->ADDRESS_MISALIGN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_MISALIGN\n"));
+ }
+
+ if (CardStatus->BLOCK_LEN_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: BLOCK_LEN_ERROR\n"));
+ }
+
+ if (CardStatus->ERASE_SEQ_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_SEQ_ERROR\n"));
+ }
+
+ if (CardStatus->ERASE_PARAM) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_PARAM\n"));
+ }
+
+ if (CardStatus->WP_VIOLATION) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: WP_VIOLATION\n"));
+ }
+
+ if (CardStatus->CARD_IS_LOCKED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CARD_IS_LOCKED\n"));
+ }
+
+ if (CardStatus->LOCK_UNLOCK_FAILED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: LOCK_UNLOCK_FAILED\n"));
+ }
+
+ if (CardStatus->COM_CRC_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: COM_CRC_ERROR\n"));
+ }
+
+ if (CardStatus->ILLEGAL_COMMAND) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ILLEGAL_COMMAND\n"));
+ }
+
+ if (CardStatus->CARD_ECC_FAILED) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CARD_ECC_FAILED\n"));
+ }
+
+ if (CardStatus->CC_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CC_ERROR\n"));
+ }
+
+ if (CardStatus->ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERROR\n"));
+ }
+
+ if (CardStatus->UNDERRUN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: UNDERRUN\n"));
+ }
+
+ if (CardStatus->OVERRUN) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: OVERRUN\n"));
+ }
+
+ if (CardStatus->CID_CSD_OVERWRITE) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: CID_CSD_OVERWRITE\n"));
+ }
+
+ if (CardStatus->WP_ERASE_SKIP) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: WP_ERASE_SKIP\n"));
+ }
+
+ if (CardStatus->ERASE_RESET) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_RESET\n"));
+ }
+
+ if (CardStatus->SWITCH_ERROR) {
+ DEBUG ((EFI_D_ERROR, "CardStatus: SWITCH_ERROR\n"));
+ }
+
+ if ((Status & 0xFCFFA080) != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send command by using Host IO protocol
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param CommandIndex The command index to set the command index field of command register.
+ @param Argument Command argument to set the argument field of command register.
+ @param DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param Buffer Contains the data read from / write to the device.
+ @param BufferSize The size of the buffer.
+ @param ResponseType RESPONSE_TYPE.
+ @param TimeOut Time out value in 1 ms unit.
+ @param ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+SendCommand (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+
+ EFI_STATUS Status;
+
+ Status = This->SendCommand (
+ This,
+ CommandIndex,
+ Argument,
+ DataType,
+ Buffer,
+ BufferSize,
+ ResponseType,
+ TimeOut,
+ ResponseData
+ );
+ if (!EFI_ERROR (Status)) {
+ if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {
+ ASSERT(ResponseData != NULL);
+ Status = CheckCardStatus (*ResponseData);
+ }
+ } else {
+ This->ResetSDHost (This, Reset_DAT_CMD);
+ }
+
+ return Status;
+}
+
+/**
+ Send the card APP_CMD command with the following command indicated by CommandIndex
+
+ @param CardData Pointer to CARD_DATA.
+ @param CommandIndex The command index to set the command index field of command register.
+ @param Argument Command argument to set the argument field of command register.
+ @param DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param Buffer Contains the data read from / write to the device.
+ @param BufferSize The size of the buffer.
+ @param ResponseType RESPONSE_TYPE.
+ @param TimeOut Time out value in 1 ms unit.
+ @param ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+SendAppCommand (
+ IN CARD_DATA *CardData,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ UINT8 Index;
+
+ SDHostIo = CardData->SDHostIo;
+ Status = EFI_SUCCESS;
+
+ for (Index = 0; Index < 2; Index++) {
+ Status = SDHostIo->SendCommand (
+ SDHostIo,
+ APP_CMD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = CheckCardStatus (*(UINT32*)&(CardData->CardStatus));
+ if (CardData->CardStatus.SAPP_CMD != 1) {
+ Status = EFI_DEVICE_ERROR;
+ }
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ } else {
+ SDHostIo->ResetSDHost (SDHostIo, Reset_Auto);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SDHostIo->SendCommand (
+ SDHostIo,
+ CommandIndex,
+ Argument,
+ DataType,
+ Buffer,
+ BufferSize,
+ ResponseType,
+ TimeOut,
+ ResponseData
+ );
+ if (!EFI_ERROR (Status)) {
+ if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {
+ ASSERT(ResponseData != NULL);
+ Status = CheckCardStatus (*ResponseData);
+ }
+ } else {
+ SDHostIo->ResetSDHost (SDHostIo, Reset_Auto);
+ }
+
+ return Status;
+}
+
+
+/**
+ Send the card FAST_IO command
+
+ @param CardData Pointer to CARD_DATA.
+ @param RegisterAddress Register Address.
+ @param RegisterData Pointer to register Data.
+ @param Write TRUE for write, FALSE for read.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+FastIO (
+ IN CARD_DATA *CardData,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT8 *RegisterData,
+ IN BOOLEAN Write
+ )
+{
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ EFI_STATUS Status;
+ UINT32 Argument;
+ UINT32 Data;
+
+ Status = EFI_SUCCESS;
+ SDHostIo = CardData->SDHostIo;
+
+ if (RegisterData == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Argument = (CardData->Address << 16) | (RegisterAddress << 8);
+ if (Write) {
+ Argument |= BIT15 | (*RegisterData);
+ }
+
+ Status = SendCommand (
+ SDHostIo,
+ FAST_IO,
+ Argument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR4,
+ TIMEOUT_COMMAND,
+ &Data
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Data & BIT15) == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ if (!Write) {
+ *RegisterData = (UINT8)Data;
+ }
+
+Exit:
+ return Status;
+}
+
+/**
+ Send the card GO_INACTIVE_STATE command.
+
+ @param CardData Pointer to CARD_DATA.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+PutCardInactive (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ EFI_STATUS Status;
+
+ SDHostIo = CardData->SDHostIo;
+
+ Status = SendCommand (
+ SDHostIo,
+ GO_INACTIVE_STATE,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+
+ return Status;
+
+}
+
+/**
+ Get card interested information for CSD rergister
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+CaculateCardParameter (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Frequency;
+ UINT32 Multiple;
+ UINT32 CSize;
+ CSD_SDV2 *CsdSDV2;
+
+ Status = EFI_SUCCESS;
+
+ switch (CardData->CSDRegister.TRAN_SPEED & 0x7) {
+ case 0:
+ Frequency = 100 * 1000;
+ break;
+
+ case 1:
+ Frequency = 1 * 1000 * 1000;
+ break;
+
+ case 2:
+ Frequency = 10 * 1000 * 1000;
+ break;
+
+ case 3:
+ Frequency = 100 * 1000 * 1000;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ switch ((CardData->CSDRegister.TRAN_SPEED >> 3) & 0xF) {
+ case 1:
+ Multiple = 10;
+ break;
+
+ case 2:
+ Multiple = 12;
+ break;
+
+ case 3:
+ Multiple = 13;
+ break;
+
+ case 4:
+ Multiple = 15;
+ break;
+
+ case 5:
+ Multiple = 20;
+ break;
+
+ case 6:
+ if (CardData->CardType == MMCCard) {
+ Multiple = 26;
+ } else {
+ Multiple = 25;
+ }
+ break;
+
+ case 7:
+ Multiple = 30;
+ break;
+
+ case 8:
+ Multiple = 35;
+ break;
+
+ case 9:
+ Multiple = 40;
+ break;
+
+ case 10:
+ Multiple = 45;
+ break;
+
+ case 11:
+ if (CardData->CardType == MMCCard) {
+ Multiple = 52;
+ } else {
+ Multiple = 50;
+ }
+ break;
+
+ case 12:
+ Multiple = 55;
+ break;
+
+ case 13:
+ Multiple = 60;
+ break;
+
+ case 14:
+ Multiple = 70;
+ break;
+
+ case 15:
+ Multiple = 80;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Frequency = Frequency * Multiple / 10;
+ CardData->MaxFrequency = Frequency;
+
+ CardData->BlockLen = 1 << CardData->CSDRegister.READ_BL_LEN;
+
+ if (CardData->CardType == SDMemoryCard2High) {
+ ASSERT(CardData->CSDRegister.CSD_STRUCTURE == 1);
+ CsdSDV2 = (CSD_SDV2*)&CardData->CSDRegister;
+ //
+ // The SD Spec 2.0 says (CSize + 1) * 512K is the total size, so block numbber is (CSize + 1) * 1K
+ // the K here means 1024 not 1000
+ //
+ CardData->BlockNumber = DivU64x32 (MultU64x32 (CsdSDV2->C_SIZE + 1, 512 * 1024) , CardData->BlockLen);
+ } else {
+ //
+ // For MMC card > 2G, the block number will be recaculate later
+ //
+ CSize = CardData->CSDRegister.C_SIZELow2 | (CardData->CSDRegister.C_SIZEHigh10 << 2);
+ CardData->BlockNumber = MultU64x32 (LShiftU64 (1, CardData->CSDRegister.C_SIZE_MULT + 2), CSize + 1);
+ }
+
+ //
+ //For >= 2G card, BlockLen may be 1024, but the transfer size is still 512 bytes
+ //
+ if (CardData->BlockLen > 512) {
+ CardData->BlockNumber = DivU64x32 (MultU64x32 (CardData->BlockNumber, CardData->BlockLen), 512);
+ CardData->BlockLen = 512;
+ }
+
+
+Exit:
+ return Status;
+}
+
+/**
+ Test the bus width setting for MMC card.It is used only for verification purpose.
+
+ @param CardData Pointer to CARD_DATA.
+ @param Width 1, 4, 8 bits.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+MMCCardBusWidthTest (
+ IN CARD_DATA *CardData,
+ IN UINT32 Width
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ UINT64 Data;
+ UINT64 Value;
+
+ ASSERT(CardData != NULL);
+
+ SDHostIo = CardData->SDHostIo;
+
+ Value = 0;
+
+ switch (Width) {
+ case 1:
+ Data = 0x80;
+ break;
+
+ case 4:
+ Data = 0x5A;
+ break;
+
+ case 8:
+ Data = 0xAA55;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ CopyMem (CardData->AlignedBuffer, &Data, Width);
+ Status = SendCommand (
+ SDHostIo,
+ BUSTEST_W,
+ 0,
+ OutData,
+ CardData->AlignedBuffer,
+ Width,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_W 0x%x\n", *(UINT32*)&(CardData->CardStatus)));
+ goto Exit;
+ }
+
+ gBS->Stall (10 * 1000);
+
+ Data = 0;
+
+ Status = SendCommand (
+ SDHostIo,
+ BUSTEST_R,
+ 0,
+ InData,
+ CardData->AlignedBuffer,
+ Width,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_R 0x%x\n", *(UINT32*)&(CardData->CardStatus)));
+ goto Exit;
+ }
+ CopyMem (&Data, CardData->AlignedBuffer, Width);
+
+ switch (Width) {
+ case 1:
+ Value = (~(Data ^ 0x80)) & 0xC0;
+ break;
+ case 4:
+ Value = (~(Data ^ 0x5A)) & 0xFF;
+ break;
+ case 8:
+ Value = (~(Data ^ 0xAA55)) & 0xFFFF;
+ break;
+ }
+
+ if (Value == 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+
+Exit:
+ return Status;
+}
+
+/**
+ This function can detect these card types:
+ 1. MMC card
+ 2. SD 1.1 card
+ 3. SD 2.0 standard card
+ 3. SD 2.0 high capacity card
+
+ @param CardData Pointer to CARD_DATA.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+GetCardType (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ UINT32 Argument;
+ UINT32 ResponseData;
+ UINT32 Count;
+ BOOLEAN SDCommand8Support;
+
+
+ SDHostIo = CardData->SDHostIo;
+
+ //
+ // Reset the card
+ //
+ Status = SendCommand (
+ SDHostIo,
+ GO_IDLE_STATE,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ //
+ //No spec requirment, can be adjusted
+ //
+ gBS->Stall (10 * 1000);
+
+
+ //
+ // Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass
+ // MMC and SD1.1 card will fail this command
+ //
+ Argument = (VOLTAGE_27_36 << 8) | CHECK_PATTERN;
+ ResponseData = 0;
+ SDCommand8Support = FALSE;
+
+ Status = SendCommand (
+ SDHostIo,
+ SEND_IF_COND,
+ Argument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR7,
+ TIMEOUT_COMMAND,
+ &ResponseData
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_TIMEOUT) {
+ DEBUG((EFI_D_ERROR, "SEND_IF_COND Fail, none time out error\n"));
+ goto Exit;
+ }
+ } else {
+ if (ResponseData != Argument) {
+ DEBUG((EFI_D_ERROR, "SEND_IF_COND Fail, respond data does not match send data\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ SDCommand8Support = TRUE;
+ }
+
+
+ Argument = 0;
+ if (SDHostIo->HostCapability.V30Support == TRUE) {
+ Argument |= BIT17 | BIT18;
+ } else if (SDHostIo->HostCapability.V33Support == TRUE) {
+ Argument |= BIT20 | BIT21;
+ }
+
+ if (SDCommand8Support) {
+ //
+ //If command SD_SEND_OP_COND sucessed, it should be set.
+ // SD 1.1 card will ignore it
+ // SD 2.0 standard card will repsond with CCS 0, SD high capacity card will respond with CCS 1
+ // CCS is BIT30 of OCR
+ Argument |= BIT30;
+ }
+
+
+ Count = 20;
+ //
+ //Only SD card will respond to this command, and spec says the card only checks condition at first ACMD41 command
+ //
+ do {
+ Status = SendAppCommand (
+ CardData,
+ SD_SEND_OP_COND,
+ Argument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->OCRRegister)
+ );
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_TIMEOUT) && (!SDCommand8Support)) {
+ CardData->CardType = MMCCard;
+ Status = EFI_SUCCESS;
+ DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, MMC card was identified\n"));
+ } else {
+ //
+ // Not as expected, MMC card should has no response, which means timeout.
+ // SD card should pass this command
+ //
+ DEBUG((EFI_D_ERROR, "SD_SEND_OP_COND Fail, check whether it is neither a MMC card nor a SD card\n"));
+ }
+ goto Exit;
+ }
+ //
+ //Avoid waiting if sucess. Busy bit 0 means not ready
+ //
+ if (CardData->OCRRegister.Busy == 1) {
+ break;
+ }
+
+ gBS->Stall (50 * 1000);
+ Count--;
+ if (Count == 0) {
+ DEBUG((EFI_D_ERROR, "Card is always in busy state\n"));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ } while (1);
+
+ //
+ //Check supported voltage
+ //
+ Argument = 0;
+ if (SDHostIo->HostCapability.V30Support == TRUE) {
+ if ((CardData->OCRRegister.V270_V360 & BIT2) == BIT2) {
+ Argument |= BIT17;
+ } else if ((CardData->OCRRegister.V270_V360 & BIT3) == BIT3) {
+ Argument |= BIT18;
+ }
+ } else if (SDHostIo->HostCapability.V33Support == TRUE) {
+ if ((CardData->OCRRegister.V270_V360 & BIT5) == BIT5) {
+ Argument |= BIT20;
+ } else if ((CardData->OCRRegister.V270_V360 & BIT6) == BIT6) {
+ Argument |= BIT21;
+ }
+ }
+
+ if (Argument == 0) {
+ //
+ //No matched support voltage
+ //
+ PutCardInactive (CardData);
+ DEBUG((EFI_D_ERROR, "No matched voltage for this card\n"));
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ CardData->CardType = SDMemoryCard;
+ if (SDCommand8Support == TRUE) {
+ CardData->CardType = SDMemoryCard2;
+ DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above standard card was identified\n"));
+ }
+
+ if ((CardData->OCRRegister.AccessMode & BIT1) == BIT1) {
+ CardData->CardType = SDMemoryCard2High;
+ DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above high capacity card was identified\n"));
+ }
+
+
+
+Exit:
+ return Status;
+}
+
+/**
+ MMC card high/low voltage selection function
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_BAD_BUFFER_SIZE
+
+**/
+EFI_STATUS
+MMCCardVoltageSelection (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ UINT8 Index;
+ UINT8 Retry;
+ UINT32 TimeOut;
+
+
+ SDHostIo = CardData->SDHostIo;
+ Status = EFI_SUCCESS;
+ //
+ //First try the high voltage, then if supported choose the low voltage
+ //
+ for (Index = 0; Index < 2; Index++) {
+
+ for (Retry = 0; Retry < 3; Retry++) {
+ //
+ // To bring back the normal MMC card to work
+ // after sending the SD command. Otherwise some
+ // card could not work
+
+ Status = SendCommand (
+ SDHostIo,
+ GO_IDLE_STATE,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));
+ continue;
+ }
+ //
+ //CE-ATA device needs long delay
+ //
+ gBS->Stall ((Retry + 1) * 50 * 1000);
+
+ //
+ //Get OCR register to check voltage support, first time the OCR is 0
+ //
+ Status = SendCommand (
+ SDHostIo,
+ SEND_OP_COND,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->OCRRegister)
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (Retry == 3) {
+ DEBUG((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ if (CardData->OCRRegister.V170_V195 == 1) {
+ CardData->DualVoltage = TRUE;
+ }
+ if (CardData->OCRRegister.V270_V360 != 0x1F &&
+ CardData->OCRRegister.V200_V260 != 0) {
+ DEBUG((EFI_D_ERROR, "Incompatiable voltage device\n"));
+ PutCardInactive (CardData);
+ Status = EFI_INCOMPATIBLE_VERSION;
+ goto Exit;
+ }
+
+ if (Index == 0) {
+ //
+ //Choose the high voltage first
+ //
+ CardData->OCRRegister.V170_V195 = 0;
+ } else {
+ //
+ //Choose the low voltage
+ //
+ CardData->OCRRegister.V170_V195 = 1;
+ CardData->OCRRegister.V270_V360 = 0;
+ }
+
+ //
+ //TimeOut Value, 5000 * 100 * 1000 = 5 s
+ //
+ TimeOut = 5000;
+
+ do {
+ Status = SendCommand (
+ SDHostIo,
+ SEND_OP_COND,
+ *(UINT32*)&(CardData->OCRRegister),
+ NoData,
+ NULL,
+ 0,
+ ResponseR3,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->OCRRegister)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ gBS->Stall (1 * 1000);
+ TimeOut--;
+ DEBUG((EFI_D_ERROR, "Card is always in busy state, timeout:%d(in 5000)\n", TimeOut));
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ } while (CardData->OCRRegister.Busy != 1);
+
+ if (CardData->DualVoltage == TRUE && SDHostIo->HostCapability.V18Support == TRUE) {
+ //
+ //Power Off the card and then power on into low voltage
+ //
+ SDHostIo->SetHostVoltage (SDHostIo, 0);
+ gBS->Stall (1 * 1000);
+ SDHostIo->SetHostVoltage (SDHostIo, 18);
+ } else {
+ //
+ //Not support the low voltage, exit
+ //
+ break;
+ }
+ }
+
+Exit:
+ return Status;
+
+}
+
+/**
+ This function set the bus and device width for MMC card
+
+ @param CardData Pointer to CARD_DATA.
+ @param Width 1, 4, 8 bits.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+
+**/
+EFI_STATUS
+MMCCardSetBusWidth (
+ IN CARD_DATA *CardData,
+ IN UINT8 BusWidth
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ SWITCH_ARGUMENT SwitchArgument;
+ UINT8 Value;
+
+ SDHostIo = CardData->SDHostIo;
+ Value = 0;
+ switch (BusWidth) {
+ case 8:
+ Value = 2;
+ break;
+
+ case 4:
+ Value = 1;
+ break;
+
+ case 1:
+ Value = 0;
+ break;
+
+ default:
+ ASSERT(0);
+ }
+
+
+ ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = Value;
+ SwitchArgument.Index = (UINT32)((UINTN)
+ (&(CardData->ExtCSDRegister.BUS_WIDTH)) - (UINTN)(&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ SDHostIo,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ SDHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SWITCH %d bits Fail\n", BusWidth));
+ goto Exit;
+ } else {
+ DEBUG((EFI_D_ERROR, "MMCCardSetBusWidth:SWITCH Card Status:0x%x\n", *(UINT32*)&(CardData->CardStatus)));
+ Status = SDHostIo->SetBusWidth (SDHostIo, BusWidth);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SWITCH set %d bits Fail\n", BusWidth));
+ goto Exit;
+ }
+ gBS->Stall (5 * 1000);
+ }
+ }
+
+ //Status = SDHostIo->HighSpeedMode (SDHostIo, TRUE);
+ //if (EFI_ERROR (Status)) {
+ // DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest: Fail to enable high speed mode\n"));
+ // goto Exit;
+ //}
+
+ Status = MMCCardBusWidthTest (CardData, BusWidth);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest %d bit Fail\n", BusWidth));
+ goto Exit;
+ }
+
+ CardData->CurrentBusWidth = BusWidth;
+
+Exit:
+ return Status;
+}
+
+
+/**
+ MMC/SD card init function
+
+ @param CardData Pointer to CARD_DATA.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+MMCSDCardInit (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ SWITCH_ARGUMENT SwitchArgument;
+ UINT32 Data;
+ UINT32 Argument;
+ UINT8 PowerValue;
+
+ ASSERT(CardData != NULL);
+ SDHostIo = CardData->SDHostIo;
+
+ Status = GetCardType (CardData);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ ASSERT (CardData->CardType != UnknownCard);
+ //
+ //MMC, SD card need host auto stop command support
+ //
+ SDHostIo->EnableAutoStopCmd (SDHostIo, TRUE);
+
+ if (CardData->CardType == MMCCard) {
+ Status = MMCCardVoltageSelection (CardData);
+ if (EFI_ERROR(Status)) {
+ goto Exit;
+ }
+ }
+
+ //
+ // Get CID Register, but the info is not used currently
+ //
+ Status = SendCommand (
+ SDHostIo,
+ ALL_SEND_CID,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR2,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CIDRegister)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "ALL_SEND_CID Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ //
+ //SET_RELATIVE_ADDR
+ //
+ if (CardData->CardType == MMCCard) {
+ //
+ //Hard code the RCA address
+ //
+ CardData->Address = 1;
+
+ //
+ // Set RCA Register
+ //
+ Status = SendCommand (
+ SDHostIo,
+ SET_RELATIVE_ADDR,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ } else {
+ Data = 0;
+ Status = SendCommand (
+ SDHostIo,
+ SET_RELATIVE_ADDR,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR6,
+ TIMEOUT_COMMAND,
+ &Data
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ CardData->Address = (UINT16)(Data >> 16);
+ *(UINT32*)&CardData->CardStatus = Data & 0x1FFF;
+ CardData->CardStatus.ERROR = (Data >> 13) & 0x1;
+ CardData->CardStatus.ILLEGAL_COMMAND = (Data >> 14) & 0x1;
+ CardData->CardStatus.COM_CRC_ERROR = (Data >> 15) & 0x1;
+ Status = CheckCardStatus (*(UINT32*)&CardData->CardStatus);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ }
+
+ //
+ // Get CSD Register
+ //
+ Status = SendCommand (
+ SDHostIo,
+ SEND_CSD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR2,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CSDRegister)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SEND_CSD Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ DEBUG((EFI_D_INFO, "CardData->CSDRegister.SPEC_VERS = 0x%x\n", CardData->CSDRegister.SPEC_VERS));
+ DEBUG((EFI_D_INFO, "CardData->CSDRegister.CSD_STRUCTURE = 0x%x\n", CardData->CSDRegister.CSD_STRUCTURE));
+
+ Status = CaculateCardParameter (CardData);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+
+ //
+ // It is platform and hardware specific, need hadrware engineer input
+ //
+ if (CardData->CSDRegister.DSR_IMP == 1) {
+ //
+ // Default is 0x404
+ //
+ Status = SendCommand (
+ SDHostIo,
+ SET_DSR,
+ (DEFAULT_DSR_VALUE << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseNo,
+ TIMEOUT_COMMAND,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SET_DSR Fail Status = 0x%x\n", Status));
+ //
+ // Assume can operate even fail
+ //
+ }
+ }
+ //
+ //Change clock frequency from 400KHz to max supported when not in high speed mode
+ //Workaround to downgrade the frequency of MMC Card ver4.0 or above
+ //In other words, don't enable high speed mode for the MMC card ver4.0 or above
+ if ((CardData->CSDRegister.SPEC_VERS >= 4) && (CardData->CardType == MMCCard) ) {
+ CardData->CSDRegister.SPEC_VERS = 3;
+ }
+ Status = SDHostIo->SetClockFrequency (SDHostIo, CardData->MaxFrequency);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n"));
+ goto Exit;
+ }
+
+ //
+ //Put the card into tran state
+ //
+ Status = SendCommand (
+ SDHostIo,
+ SELECT_DESELECT_CARD,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SELECT_DESELECT_CARD Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ //
+ // No spec requirment, can be adjusted
+ //
+ gBS->Stall (5 * 1000);
+ //
+ // No need to do so
+ //
+ //
+ Status = SendCommand (
+ SDHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SELECT_DESELECT_CARD SEND_STATUS Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ //
+ //if the SPEC_VERS indicates a version 4.0 or higher
+ //The card is a high speed card and support Switch
+ //and Send_ext_csd command
+ //otherwise it is an old card
+ //
+
+ if (CardData->CardType == MMCCard) {
+ //
+ //Only V4.0 and above supports more than 1 bits and high speed
+ //
+ if (CardData->CSDRegister.SPEC_VERS >= 4) {
+ //
+ //Get ExtCSDRegister
+ //
+ Status = SendCommand (
+ SDHostIo,
+ SEND_EXT_CSD,
+ 0x0,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (EXT_CSD),
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SEND_EXT_CSD Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof (EXT_CSD));
+
+ //
+ // Recaculate the block number for >2G MMC card
+ //
+ Data = (CardData->ExtCSDRegister.SEC_COUNT[0]) |
+ (CardData->ExtCSDRegister.SEC_COUNT[1] << 8) |
+ (CardData->ExtCSDRegister.SEC_COUNT[2] << 16) |
+ (CardData->ExtCSDRegister.SEC_COUNT[3] << 24);
+
+ if (Data != 0) {
+ CardData->BlockNumber = Data;
+ }
+ //
+ // Check current chipset capability and the plugged-in card
+ // whether supports HighSpeed
+ //
+ if (SDHostIo->HostCapability.HighSpeedSupport) {
+
+ //
+ //Change card timing to high speed interface timing
+ //
+ ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = 1;
+ SwitchArgument.Index = (UINT32)((UINTN)
+ (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN)(&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ CardData->SDHostIo,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "MMCSDCardInit:SWITCH frequency Fail Status = 0x%x\n", Status));
+ }
+
+ gBS->Stall (5 * 1000);
+
+
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ SDHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Change host clock to support high speed and enable chispet to
+ // support speed
+ //
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_MMC_PP_HIGH);
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_MMC_PP);
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n"));
+ goto Exit;
+ }
+ //
+ // It seems no need to stall after changing bus freqeuncy.
+ // It is said that the freqeuncy can be changed at any time. Just appends 8 clocks after command.
+ // But SetClock alreay has delay.
+ //
+ }
+ }
+
+ }
+
+
+ Status = MMCCardBusWidthTest (CardData, 1);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest 1 bit Fail Status = 0x%x\n", Status));
+ }
+
+ //
+ // Prefer wide bus width for performance
+ //
+ //
+ // Set to BusWidth bits mode, only version 4.0 or above support more than 1 bits
+ //
+ if (SDHostIo->HostCapability.BusWidth8 == TRUE) {
+ Status = MMCCardSetBusWidth (CardData, 8);
+ if (EFI_ERROR (Status)) {
+ //
+ // CE-ATA may support 8 bits and 4 bits, but has no software method for detection
+ //
+ Status = MMCCardSetBusWidth (CardData, 4);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+ } else if (SDHostIo->HostCapability.BusWidth4 == TRUE) {
+ Status = MMCCardSetBusWidth (CardData, 4);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ }
+
+ PowerValue = 0;
+
+ if (CardData->CurrentBusWidth == 8) {
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;
+ PowerValue = PowerValue >> 4;
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;
+ PowerValue = PowerValue >> 4;
+ }
+ } else if (CardData->CurrentBusWidth == 4) {
+ if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;
+ PowerValue = PowerValue & 0xF;
+ } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {
+ PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;
+ PowerValue = PowerValue & 0xF;
+ }
+ }
+
+ if (PowerValue != 0) {
+ //
+ //Update Power Class
+ //
+ ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = PowerValue;
+ SwitchArgument.Index = (UINT32)((UINTN)
+ (&(CardData->ExtCSDRegister.POWER_CLASS)) - (UINTN)(&(CardData->ExtCSDRegister)));
+ SwitchArgument.Access = WriteByte_Mode;
+ Status = SendCommand (
+ SDHostIo,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = SendCommand (
+ SDHostIo,
+ SEND_STATUS,
+ (CardData->Address << 16),
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SWITCH Power Class Fail Status = 0x%x\n", Status));
+ }
+ //gBS->Stall (10 * 1000);
+ }
+ }
+
+
+
+ } else {
+
+
+ DEBUG((EFI_D_ERROR, "MMC Card version %d only supportes 1 bits at lower transfer speed\n",CardData->CSDRegister.SPEC_VERS));
+ }
+ } else {
+ //
+ // Pin 1, at power up this line has a 50KOhm pull up enabled in the card.
+ // This pull-up should be disconnected by the user, during regular data transfer,
+ // with SET_CLR_CARD_DETECT (ACMD42) command
+ //
+ Status = SendAppCommand (
+ CardData,
+ SET_CLR_CARD_DETECT,
+ 0,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SET_CLR_CARD_DETECT Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ /*
+ //
+ // Don't rely on SCR and SD status, some cards have unexpected SCR.
+ // It only sets private section, the other bits are 0
+ // such as Sandisk Ultra II 4.0G, KinSton mini SD 128M, Toshiba 2.0GB
+ // Some card even fail this command, KinSton SD 4GB
+ //
+ Status = SendAppCommand (
+ CardData,
+ SEND_SCR,
+ 0,
+ InData,
+ (UINT8*)&(CardData->SCRRegister),
+ sizeof(SCR),
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // SD memory card at least supports 1 and 4 bits.
+ //
+ // ASSERT ((CardData->SCRRegister.SD_BUS_WIDTH & (BIT0 | BIT2)) == (BIT0 | BIT2));
+ */
+
+ //
+ // Set Bus Width to 4
+ //
+ Status = SendAppCommand (
+ CardData,
+ SET_BUS_WIDTH,
+ SD_BUS_WIDTH_4,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SET_BUS_WIDTH 4 bits Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+
+ Status = SDHostIo->SetBusWidth (SDHostIo, 4);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CardData->CurrentBusWidth = 4;
+
+
+ if ((SDHostIo->HostCapability.HighSpeedSupport == FALSE) ||
+ ((CardData->CSDRegister.CCC & BIT10) != BIT10)) {
+ //
+ // Host must support high speed
+ // Card must support Switch function
+ //
+ goto Exit;
+ }
+
+ //
+ //Mode = 0, group 1, function 1, check operation
+ //
+ Argument = 0xFFFF01;
+ ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));
+
+ Status = SendCommand (
+ SDHostIo,
+ SWITCH_FUNC,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (SWITCH_STATUS),
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));
+
+ if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||
+ ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {
+ //
+ // 1. SD 1.1 card does not suppport busy bit
+ // 2. Ready state
+ //
+ //
+
+ //
+ //Mode = 1, group 1, function 1, BIT31 set means set mode
+ //
+ Argument = 0xFFFF01 | BIT31;
+ ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));
+
+ Status = SendCommand (
+ SDHostIo,
+ SWITCH_FUNC,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ sizeof (SWITCH_STATUS),
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));
+
+ if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||
+ ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {
+ //
+ // 1. SD 1.1 card does not suppport busy bit
+ // 2. Ready state
+ //
+
+ //
+ // 8 clocks, (1/ 25M) * 8 ==> 320 us, so 1ms > 0.32 ms
+ //
+ gBS->Stall (1000);
+
+ //
+ //Change host clock
+ //
+ Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_SD_PP_HIGH);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ }
+ }
+ }
+
+ //
+ // Set Block Length, to improve compatibility in case of some cards
+ //
+ Status = SendCommand (
+ SDHostIo,
+ SET_BLOCKLEN,
+ 512,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1,
+ TIMEOUT_COMMAND,
+ (UINT32*)&(CardData->CardStatus)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "SET_BLOCKLEN Fail Status = 0x%x\n", Status));
+ goto Exit;
+ }
+ SDHostIo->SetBlockLength (SDHostIo, 512);
+
+
+Exit:
+ return Status;
+}
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.c
new file mode 100755
index 0000000..1b539e2
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.c
@@ -0,0 +1,345 @@
+/** @file
+
+ The definition for SD media device driver model and blkio protocol routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "SDMediaDevice.h"
+
+
+EFI_DRIVER_BINDING_PROTOCOL gSDMediaDeviceDriverBinding = {
+ SDMediaDeviceSupported,
+ SDMediaDeviceStart,
+ SDMediaDeviceStop,
+ 0x20,
+ NULL,
+ NULL
+};
+
+/**
+ Entry point for EFI drivers.
+
+ @param ImageHandle EFI_HANDLE.
+ @param SystemTable EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS Driver is successfully loaded.
+ @return Others Failed.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSDMediaDevice (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSDMediaDeviceDriverBinding,
+ ImageHandle,
+ &gSDMediaDeviceName,
+ &gSDMediaDeviceName2
+ );
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has BlockIoProtocol installed will be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSDHostIoProtocolGuid,
+ (VOID **)&SDHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSDHostIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+Exit:
+ return Status;
+}
+
+/**
+ Starting the SD Media Device Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ CARD_DATA *CardData;
+
+ CardData = NULL;
+
+ //
+ // Open PCI I/O Protocol and save pointer to open protocol
+ // in private data area.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSDHostIoProtocolGuid,
+ (VOID **) &SDHostIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to open gEfiSDHostIoProtocolGuid \r\n"));
+ goto Exit;
+ }
+
+ Status = SDHostIo->DetectCardAndInitHost (SDHostIo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: Fail to DetectCardAndInitHost \r\n"));
+ goto Exit;
+ }
+
+ CardData = (CARD_DATA*)AllocateZeroPool(sizeof (CARD_DATA));
+ if (CardData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to AllocateZeroPool(CARD_DATA) \r\n"));
+ goto Exit;
+ }
+
+ ASSERT (SDHostIo->HostCapability.BoundarySize >= 4 * 1024);
+ CardData->RawBufferPointer = (UINT8*)((UINTN)DMA_MEMORY_TOP);
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (2 * SDHostIo->HostCapability.BoundarySize),
+ (EFI_PHYSICAL_ADDRESS *)(&CardData->RawBufferPointer)
+ );
+
+ if (CardData->RawBufferPointer == NULL) {
+ DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to AllocateZeroPool(2*x) \r\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ CardData->AlignedBuffer = CardData->RawBufferPointer - ((UINTN)(CardData->RawBufferPointer) & (SDHostIo->HostCapability.BoundarySize - 1)) + SDHostIo->HostCapability.BoundarySize;
+
+ CardData->Signature = CARD_DATA_SIGNATURE;
+ CardData->SDHostIo = SDHostIo;
+
+ Status = MMCSDCardInit (CardData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to MMCSDCardInit \r\n"));
+ goto Exit;
+ }
+
+ if (CardData->CardType == MMCCard) {
+ if (IsCEATADevice (CardData)) {
+ CardData->CardType = CEATACard;
+ }
+ }
+
+ if (CardData->CardType == CEATACard) {
+ Status = CEATABlockIoInit (CardData);
+ } else {
+ Status = MMCSDBlockIoInit (CardData);
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to BlockIoInit \r\n"));
+ goto Exit;
+ }
+
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiBlockIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &CardData->BlockIo
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to install gEfiBlockIoProtocolGuid \r\n"));
+ goto Exit;
+ }
+
+ //
+ // Install the component name protocol
+ //
+ CardData->ControllerNameTable = NULL;
+
+ AddUnicodeString2 (
+ "eng",
+ gSDMediaDeviceName.SupportedLanguages,
+ &CardData->ControllerNameTable,
+ L"MMC/SD Media Device",
+ TRUE
+ );
+ AddUnicodeString2 (
+ "en",
+ gSDMediaDeviceName2.SupportedLanguages,
+ &CardData->ControllerNameTable,
+ L"MMC/SD Media Device",
+ FALSE
+ );
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: End with failure\r\n"));
+ if (CardData != NULL) {
+ if (CardData->RawBufferPointer != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * SDHostIo->HostCapability.BoundarySize));
+ }
+ FreePool (CardData);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ CARD_DATA *CardData;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ //
+ // First find BlockIo Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **)&BlockIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CardData = CARD_DATA_FROM_THIS(BlockIo);
+
+ //
+ // Uninstall Block I/O protocol from the device handle
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ BlockIo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CardData != NULL) {
+ if (CardData->RawBufferPointer != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * CardData->SDHostIo->HostCapability.BoundarySize));
+ }
+ FreeUnicodeStringTable (CardData->ControllerNameTable);
+ FreePool (CardData);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSDHostIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.h b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.h
new file mode 100644
index 0000000..358b47f
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.h
@@ -0,0 +1,485 @@
+/** @file
+
+ The definition for SD media device driver model and blkio protocol routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SD_MEDIA_DEVICE_H_
+#define _SD_MEDIA_DEVICE_H_
+
+
+#include <Uefi.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/BlockIo.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Pci22.h>
+
+#include "ComponentName.h"
+#include "SDHostIo.h"
+
+
+extern EFI_DRIVER_BINDING_PROTOCOL gSDMediaDeviceDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gSDMediaDeviceName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gSDMediaDeviceName2;
+
+//
+// Define the region of memory used for DMA memory
+//
+#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL
+
+#define CARD_DATA_SIGNATURE SIGNATURE_32 ('c', 'a', 'r', 'd')
+
+//
+// Command timeout will be max 100 ms
+//
+#define TIMEOUT_COMMAND 100
+#define TIMEOUT_DATA 5000
+
+typedef enum{
+ UnknownCard = 0,
+ MMCCard, // MMC card
+ CEATACard, // CE-ATA device
+ SDMemoryCard, // SD 1.1 card
+ SDMemoryCard2, // SD 2.0 or above standard card
+ SDMemoryCard2High // SD 2.0 or above high capacity card
+}CARD_TYPE;
+
+
+typedef struct {
+ //
+ //BlockIO
+ //
+ UINTN Signature;
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+
+ EFI_BLOCK_IO_MEDIA BlockIoMedia;
+
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+ CARD_TYPE CardType;
+
+ UINT8 CurrentBusWidth;
+ BOOLEAN DualVoltage;
+ BOOLEAN NeedFlush;
+ UINT8 Reserved[3];
+
+ UINT16 Address;
+ UINT32 BlockLen;
+ UINT32 MaxFrequency;
+ UINT64 BlockNumber;
+ //
+ //Common used
+ //
+ CARD_STATUS CardStatus;
+ OCR OCRRegister;
+ CID CIDRegister;
+ CSD CSDRegister;
+ EXT_CSD ExtCSDRegister;
+ UINT8 *RawBufferPointer;
+ UINT8 *AlignedBuffer;
+ //
+ //CE-ATA specific
+ //
+ TASK_FILE TaskFile;
+ IDENTIFY_DEVICE_DATA IndentifyDeviceData;
+ //
+ //SD specific
+ //
+ SCR SCRRegister;
+ SD_STATUS_REG SDSattus;
+ SWITCH_STATUS SwitchStatus;
+}CARD_DATA;
+
+#define CARD_DATA_FROM_THIS(a) \
+ CR(a, CARD_DATA, BlockIo, CARD_DATA_SIGNATURE)
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has BlockIoProtocol installed will be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starting the SD Media Device Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+SDMediaDeviceStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ MMC/SD card init function
+
+ @param CardData Pointer to CARD_DATA.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+MMCSDCardInit (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ Send command by using Host IO protocol
+
+ @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
+ @param CommandIndex The command index to set the command index field of command register.
+ @param Argument Command argument to set the argument field of command register.
+ @param DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param Buffer Contains the data read from / write to the device.
+ @param BufferSize The size of the buffer.
+ @param ResponseType RESPONSE_TYPE.
+ @param TimeOut Time out value in 1 ms unit.
+ @param ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+SendCommand (
+ IN EFI_SD_HOST_IO_PROTOCOL *This,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ );
+
+/**
+ Send the card APP_CMD command with the following command indicated by CommandIndex
+
+ @param CardData Pointer to CARD_DATA.
+ @param CommandIndex The command index to set the command index field of command register.
+ @param Argument Command argument to set the argument field of command register.
+ @param DataType TRANSFER_TYPE, indicates no data, data in or data out.
+ @param Buffer Contains the data read from / write to the device.
+ @param BufferSize The size of the buffer.
+ @param ResponseType RESPONSE_TYPE.
+ @param TimeOut Time out value in 1 ms unit.
+ @param ResponseData Depending on the ResponseType, such as CSD or card status.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_UNSUPPORTED
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+SendAppCommand (
+ IN CARD_DATA *CardData,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ );
+
+/**
+ Send the card FAST_IO command
+
+ @param CardData Pointer to CARD_DATA.
+ @param RegisterAddress Register Address.
+ @param RegisterData Pointer to register Data.
+ @param Write TRUE for write, FALSE for read.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+FastIO (
+ IN CARD_DATA *CardData,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT8 *RegisterData,
+ IN BOOLEAN Write
+ );
+
+/**
+ Judge whether it is CE-ATA device or not.
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval TRUE
+ @retval FALSE
+
+**/
+BOOLEAN
+IsCEATADevice (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ Send software reset
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SoftwareReset (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ SendATACommand specificed in Taskfile
+
+ @param CardData Pointer to CARD_DATA.
+ @param TaskFile Pointer to TASK_FILE.
+ @param Write TRUE means write, FALSE means read.
+ @param Buffer If NULL, means no data transfer, neither read nor write.
+ @param SectorCount Buffer size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SendATACommand (
+ IN CARD_DATA *CardData,
+ IN TASK_FILE *TaskFile,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ );
+
+/**
+ IDENTIFY_DEVICE command
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+IndentifyDevice (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ FLUSH_CACHE_EXT command
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+FlushCache (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ STANDBY_IMMEDIATE command
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+StandByImmediate (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ READ_DMA_EXT command
+
+ @param CardData Pointer to CARD_DATA.
+ @param LBA The starting logical block address to read from on the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ );
+
+/**
+ WRITE_DMA_EXT command
+
+ @param CardData Pointer to CARD_DATA.
+ @param LBA The starting logical block address to read from on the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+WriteDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ );
+
+/**
+ CEATA card BlockIo init function.
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval Others
+**/
+EFI_STATUS
+CEATABlockIoInit (
+ IN CARD_DATA *CardData
+ );
+
+/**
+ MMC/SD card BlockIo init function.
+
+ @param CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS
+ @retval Others
+**/
+EFI_STATUS
+MMCSDBlockIoInit (
+ IN CARD_DATA *CardData
+ );
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf
new file mode 100644
index 0000000..ed6174b
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf
@@ -0,0 +1,85 @@
+## @file
+#
+# Component Description File For SDMediaDeviceDxe Module.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SDMediaDevice
+ FILE_GUID = 80897901-91F6-4efe-9579-3353A0C02DAB
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSDMediaDevice
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gSDMediaDeviceDriverBinding
+# COMPONENT_NAME = gSDMediaDeviceName
+# COMPONENT_NAME2 = gSDMediaDeviceName2
+#
+
+[Sources]
+ SDMediaDevice.c
+ SDMediaDevice.h
+ MMCSDTransfer.c
+ CEATA.c
+ CEATABlockIo.c
+ MMCSDBlockIo.c
+ ComponentName.c
+ ComponentName.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+# DebugLibConOut
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiSDHostIoProtocolGuid ## TO_START
+ gEfiBlockIoProtocolGuid ## BY_START
+
+[Pcd.common]
diff --git a/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/ComponentName.c b/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/ComponentName.c
new file mode 100644
index 0000000..1fe5606
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/ComponentName.c
@@ -0,0 +1,269 @@
+/** @file
+ UEFI Component Name and Name2 protocol for Isa serial driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Serial.h"
+
+#define SERIAL_PORT_NAME "IOH Serial Port # "
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIohSerialComponentName = {
+ IohSerialComponentNameGetDriverName,
+ IohSerialComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIohSerialComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IohSerialComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IohSerialComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIohSerialDriverNameTable[] = {
+ {
+ "eng;en",
+ L"QuarkSCSocId Serial Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mIohSerialDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gIohSerialComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ SERIAL_DEV *SerialDevice;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the Block I/O Protocol on Controller
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ gSerialControllerDriver.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Serial Controller's Device structure
+ //
+ SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ SerialDevice->ControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gIohSerialComponentName)
+ );
+}
+
+/**
+ Add the ISO639-2 and RFC4646 component name both for the Serial IO device
+
+ @param SerialDevice A pointer to the SERIAL_DEV instance.
+
+**/
+VOID
+AddName (
+ IN SERIAL_DEV *SerialDevice
+ )
+{
+ CHAR16 SerialPortName[sizeof (SERIAL_PORT_NAME)];
+
+ StrCpy (SerialPortName, L"IOH Serial Port # ");
+ SerialPortName[sizeof (SERIAL_PORT_NAME) - 2] = (CHAR16) (L'0' + 1);
+ AddUnicodeString2 (
+ "eng",
+ gIohSerialComponentName.SupportedLanguages,
+ &SerialDevice->ControllerNameTable,
+ (CHAR16 *) SerialPortName,
+ TRUE
+ );
+ AddUnicodeString2 (
+ "en",
+ gIohSerialComponentName2.SupportedLanguages,
+ &SerialDevice->ControllerNameTable,
+ (CHAR16 *) SerialPortName,
+ FALSE
+ );
+
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.c b/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.c
new file mode 100644
index 0000000..9198080
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.c
@@ -0,0 +1,1797 @@
+/** @file
+ Serial driver for standard UARTS on IOH.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "Serial.h"
+
+//
+// IOH Serial Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = {
+ SerialControllerDriverSupported,
+ SerialControllerDriverStart,
+ SerialControllerDriverStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+
+SERIAL_DEV gSerialDevTempate = {
+ SERIAL_DEV_SIGNATURE,
+ NULL,
+ { // SerialIo
+ SERIAL_IO_INTERFACE_REVISION,
+ IohSerialReset,
+ IohSerialSetAttributes,
+ IohSerialSetControl,
+ IohSerialGetControl,
+ IohSerialWrite,
+ IohSerialRead,
+ NULL
+ },
+ { // SerialMode
+ SERIAL_PORT_DEFAULT_CONTROL_MASK,
+ SERIAL_PORT_DEFAULT_TIMEOUT,
+ FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
+ SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,
+ FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
+ FixedPcdGet8 (PcdUartDefaultParity), // Parity
+ FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
+ },
+ NULL,
+ NULL,
+ { // UartDevicePath
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ {
+ (UINT8) (sizeof (UART_DEVICE_PATH)),
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
+ }
+ },
+ 0,
+ FixedPcdGet64 (PcdUartDefaultBaudRate),
+ FixedPcdGet8 (PcdUartDefaultDataBits),
+ FixedPcdGet8 (PcdUartDefaultParity),
+ FixedPcdGet8 (PcdUartDefaultStopBits)
+ },
+ 0, //BaseAddress
+ {
+ 0,
+ 0,
+ SERIAL_MAX_BUFFER_SIZE,
+ { 0 }
+ },
+ {
+ 0,
+ 0,
+ SERIAL_MAX_BUFFER_SIZE,
+ { 0 }
+ },
+ FALSE,
+ FALSE,
+ Uart16550A,
+ NULL
+};
+
+/**
+ The user Entry Point for module IohSerial. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeIohSerial (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSerialControllerDriver,
+ ImageHandle,
+ &gIohSerialComponentName,
+ &gIohSerialComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ return Status;
+}
+
+/**
+ This function converts an input device structure to a Unicode string.
+
+ @param DevPath A pointer to the device path structure.
+
+ @return A new allocated Unicode string that represents the device path.
+
+**/
+CHAR16 *
+EFIAPI
+DevicePathToStr (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+/**
+ Check to see if this driver supports the given controller
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @return EFI_SUCCESS This driver can support the given controller
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ UINT16 Did;
+ UART_DEVICE_PATH *UartNode;
+
+ //
+ // Check RemainingDevicePath validation
+ //
+ if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // Check if RemainingDevicePath is the End of Device Path Node,
+ // if yes, go on checking other conditions
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node,
+ // check its validation
+ //
+ UartNode = (UART_DEVICE_PATH *) RemainingDevicePath;
+ if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||
+ UartNode->Header.SubType != MSG_UART_DP ||
+ sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UartNode)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Check PCI device information
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ // Not PCI device?
+ return EFI_UNSUPPORTED;
+ }
+ // Retrieve PCI configuration for this device
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Did = SYNOPSIS_UART0_DID;
+ if (Pci.Hdr.ClassCode[2] != PCI_CLASS_SCC ||
+ Pci.Hdr.ClassCode[1] != PCI_SUBCLASS_SERIAL ||
+ Pci.Hdr.ClassCode[0] != PCI_IF_16550 ||
+ Pci.Hdr.VendorId != 0x8086 ||
+ Pci.Hdr.DeviceId != Did) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the UART Device Path and test it
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Start to management the controller passed in
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @return EFI_SUCCESS Driver is started successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+
+{
+ EFI_STATUS Status;
+ SERIAL_DEV *SerialDevice;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ UART_DEVICE_PATH *UartNode;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ SerialDevice = NULL;
+ //
+ // Get the Parent Device Path
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ return Status;
+ }
+ //
+ // Report status code enable the serial
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT,
+ ParentDevicePath
+ );
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (RemainingDevicePath != NULL) {
+ if (IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath is the End of Device Path Node,
+ // skip enumerate any device and return EFI_SUCESSS
+ //
+ return EFI_SUCCESS;
+ }
+
+ if (Status == EFI_ALREADY_STARTED) {
+ UartNode = (UART_DEVICE_PATH *) RemainingDevicePath;
+ Status = SerialIo->SetAttributes (
+ SerialIo,
+ UartNode->BaudRate,
+ SerialIo->Mode->ReceiveFifoDepth,
+ SerialIo->Mode->Timeout,
+ (EFI_PARITY_TYPE) UartNode->Parity,
+ UartNode->DataBits,
+ (EFI_STOP_BITS_TYPE) UartNode->StopBits
+ );
+ return Status;
+ }
+ } else if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Initialize the serial device instance
+ //
+ SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTempate);
+ if (SerialDevice == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ //
+ // Get the BAR of the UART
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ // Not PCI device?
+ return EFI_UNSUPPORTED;
+ }
+ // Retrieve PCI configuration for this device
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ } else {
+ if (FeaturePcdGet(PcdIohUartUseMmio)) {
+ SerialDevice->BaseAddress = Pci.Device.Bar[0] & 0xFFFFFFF0;
+ //DEBUG((EFI_D_INFO, "UART MMIOBASE=0x%x\n", SerialDevice->BaseAddress));
+ } else {
+ SerialDevice->BaseAddress = Pci.Device.Bar[0] & 0xFFFFFFF8;
+ //DEBUG((EFI_D_INFO, "UART IOBASE=0x%x\n", SerialDevice->BaseAddress));
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode);
+ SerialDevice->ParentDevicePath = ParentDevicePath;
+
+ //
+ // Check if RemainingDevicePath is NULL,
+ // if yes, use the values from the gSerialDevTempate as no remaining device path was
+ // passed in.
+ //
+ if (RemainingDevicePath != NULL) {
+ //
+ // If RemainingDevicePath isn't NULL,
+ // match the configuration of the RemainingDevicePath. IsHandleSupported()
+ // already checked to make sure the RemainingDevicePath contains settings
+ // that we can support.
+ //
+ CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
+ }
+
+ AddName (SerialDevice);
+
+ //
+ // Report status code the serial present
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT,
+ ParentDevicePath
+ );
+
+ if (!IohSerialPortPresent (SerialDevice)) {
+ Status = EFI_DEVICE_ERROR;
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE,
+ EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT,
+ ParentDevicePath
+ );
+ goto Error;
+ }
+
+ //
+ // Build the device path by appending the UART node to the ParentDevicePath.
+ // The Uart setings are zero here, since SetAttribute() will update them to match
+ // the default setings.
+ //
+ SerialDevice->DevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&SerialDevice->UartDevicePath
+ );
+ if (SerialDevice->DevicePath == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Error;
+ }
+
+ //
+ // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
+ //
+ SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate;
+ SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits;
+ SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity;
+ SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits;
+
+ //
+ // Issue a reset to initialize the COM port
+ //
+ Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo);
+ if (EFI_ERROR (Status)) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE,
+ EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
+ ParentDevicePath
+ );
+ goto Error;
+ }
+ //
+ // Install protocol interfaces for the serial device.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &SerialDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ &gEfiSerialIoProtocolGuid,
+ &SerialDevice->SerialIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+Error:
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSerialIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ if (SerialDevice != NULL) {
+ if (SerialDevice->DevicePath != NULL) {
+ gBS->FreePool (SerialDevice->DevicePath);
+ }
+
+ FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
+ gBS->FreePool (SerialDevice);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Disconnect this driver with the controller, uninstall related protocol instance
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param NumberOfChildren Number of child device.
+ @param ChildHandleBuffer A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Operation successfully
+ @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ BOOLEAN AllChildrenStopped;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ SERIAL_DEV *SerialDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+
+ //
+ // Report the status code disable the serial
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT,
+ DevicePath
+ );
+
+ //
+ // Complete all outstanding transactions to Controller.
+ // Don't allow any new transaction to Controller to be started.
+ //
+ if (NumberOfChildren == 0) {
+ //
+ // Close the bus driver
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ &gEfiSerialIoProtocolGuid,
+ &SerialDevice->SerialIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ if (SerialDevice->DevicePath != NULL) {
+ gBS->FreePool (SerialDevice->DevicePath);
+ }
+
+ FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
+ gBS->FreePool (SerialDevice);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Detect whether specific FIFO is full or not.
+
+ @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @return whether specific FIFO is full or not
+
+**/
+BOOLEAN
+IohSerialFifoFull (
+ IN SERIAL_DEV_FIFO *Fifo
+ )
+
+{
+ if (Fifo->Surplus == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Detect whether specific FIFO is empty or not.
+
+ @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @return whether specific FIFO is empty or not
+
+**/
+BOOLEAN
+IohSerialFifoEmpty (
+ IN SERIAL_DEV_FIFO *Fifo
+ )
+
+{
+ if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Add data to specific FIFO.
+
+ @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param Data the data added to FIFO
+
+ @retval EFI_SUCCESS Add data to specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
+
+**/
+EFI_STATUS
+IohSerialFifoAdd (
+ IN SERIAL_DEV_FIFO *Fifo,
+ IN UINT8 Data
+ )
+
+{
+ //
+ // if FIFO full can not add data
+ //
+ if (IohSerialFifoFull (Fifo)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // FIFO is not full can add data
+ //
+ Fifo->Data[Fifo->Last] = Data;
+ Fifo->Surplus--;
+ Fifo->Last++;
+ if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) {
+ Fifo->Last = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Remove data from specific FIFO.
+
+ @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param Data the data removed from FIFO
+
+ @retval EFI_SUCCESS Remove data from specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
+
+**/
+EFI_STATUS
+IohSerialFifoRemove (
+ IN SERIAL_DEV_FIFO *Fifo,
+ OUT UINT8 *Data
+ )
+
+{
+ //
+ // if FIFO is empty, no data can remove
+ //
+ if (IohSerialFifoEmpty (Fifo)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // FIFO is not empty, can remove data
+ //
+ *Data = Fifo->Data[Fifo->First];
+ Fifo->Surplus++;
+ Fifo->First++;
+ if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) {
+ Fifo->First = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads and writes all avaliable data.
+
+ @param SerialDevice The device to flush
+
+ @retval EFI_SUCCESS Data was read/written successfully.
+ @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
+ this happens, pending writes are not done.
+
+**/
+EFI_STATUS
+IohSerialReceiveTransmit (
+ IN SERIAL_DEV *SerialDevice
+ )
+
+{
+ SERIAL_PORT_LSR Lsr;
+ UINT8 Data;
+ BOOLEAN ReceiveFifoFull;
+ SERIAL_PORT_MSR Msr;
+ SERIAL_PORT_MCR Mcr;
+ UINTN TimeOut;
+
+ Data = 0;
+
+ //
+ // Begin the read or write
+ //
+ if (SerialDevice->SoftwareLoopbackEnable) {
+ do {
+ ReceiveFifoFull = IohSerialFifoFull (&SerialDevice->Receive);
+ if (!IohSerialFifoEmpty (&SerialDevice->Transmit)) {
+ IohSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ if (ReceiveFifoFull) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ IohSerialFifoAdd (&SerialDevice->Receive, Data);
+ }
+ } while (!IohSerialFifoEmpty (&SerialDevice->Transmit));
+ } else {
+ ReceiveFifoFull = IohSerialFifoFull (&SerialDevice->Receive);
+ //
+ // For full handshake flow control, tell the peer to send data
+ // if receive buffer is available.
+ //
+ if (SerialDevice->HardwareFlowControl &&
+ !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)&&
+ !ReceiveFifoFull
+ ) {
+ Mcr.Data = READ_MCR (SerialDevice);
+ Mcr.Bits.Rts = 1;
+ WRITE_MCR (SerialDevice, Mcr.Data);
+ }
+ do {
+ Lsr.Data = READ_LSR (SerialDevice);
+
+ //
+ // Flush incomming data to prevent a an overrun during a long write
+ //
+ if ((Lsr.Bits.Dr == 1) && !ReceiveFifoFull) {
+ ReceiveFifoFull = IohSerialFifoFull (&SerialDevice->Receive);
+ if (!ReceiveFifoFull) {
+ if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Oe == 1 || Lsr.Bits.Pe == 1 || Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE,
+ EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
+ SerialDevice->DevicePath
+ );
+ if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Pe == 1|| Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {
+ Data = READ_RBR (SerialDevice);
+ continue;
+ }
+ }
+
+ Data = READ_RBR (SerialDevice);
+
+ IohSerialFifoAdd (&SerialDevice->Receive, Data);
+
+ //
+ // For full handshake flow control, if receive buffer full
+ // tell the peer to stop sending data.
+ //
+ if (SerialDevice->HardwareFlowControl &&
+ !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake) &&
+ IohSerialFifoFull (&SerialDevice->Receive)
+ ) {
+ Mcr.Data = READ_MCR (SerialDevice);
+ Mcr.Bits.Rts = 0;
+ WRITE_MCR (SerialDevice, Mcr.Data);
+ }
+
+
+ continue;
+ } else {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,
+ SerialDevice->DevicePath
+ );
+ }
+ }
+ //
+ // Do the write
+ //
+ if (Lsr.Bits.Thre == 1 && !IohSerialFifoEmpty (&SerialDevice->Transmit)) {
+ //
+ // Make sure the transmit data will not be missed
+ //
+ if (SerialDevice->HardwareFlowControl) {
+ //
+ // For half handshake flow control assert RTS before sending.
+ //
+ if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) {
+ Mcr.Data = READ_MCR (SerialDevice);
+ Mcr.Bits.Rts= 0;
+ WRITE_MCR (SerialDevice, Mcr.Data);
+ }
+ //
+ // Wait for CTS
+ //
+ TimeOut = 0;
+ Msr.Data = READ_MSR (SerialDevice);
+ while ((Msr.Bits.Dcd == 1) && ((Msr.Bits.Cts == 0) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) {
+ gBS->Stall (TIMEOUT_STALL_INTERVAL);
+ TimeOut++;
+ if (TimeOut > 5) {
+ break;
+ }
+
+ Msr.Data = READ_MSR (SerialDevice);
+ }
+
+ if ((Msr.Bits.Dcd == 0) || ((Msr.Bits.Cts == 1) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) {
+ IohSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ WRITE_THR (SerialDevice, Data);
+ }
+
+ //
+ // For half handshake flow control, tell DCE we are done.
+ //
+ if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) {
+ Mcr.Data = READ_MCR (SerialDevice);
+ Mcr.Bits.Rts = 1;
+ WRITE_MCR (SerialDevice, Mcr.Data);
+ }
+ } else {
+ IohSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ WRITE_THR (SerialDevice, Data);
+ }
+ }
+ } while (Lsr.Bits.Thre == 1 && !IohSerialFifoEmpty (&SerialDevice->Transmit));
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// Interface Functions
+//
+/**
+ Reset serial device.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+
+ @retval EFI_SUCCESS Reset successfully
+ @retval EFI_DEVICE_ERROR Failed to reset
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialReset (
+ IN EFI_SERIAL_IO_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_LCR Lcr;
+ SERIAL_PORT_IER Ier;
+ SERIAL_PORT_MCR Mcr;
+ SERIAL_PORT_FCR Fcr;
+ EFI_TPL Tpl;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ //
+ // Report the status code reset the serial
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,
+ SerialDevice->DevicePath
+ );
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Make sure DLAB is 0.
+ //
+ Lcr.Data = READ_LCR (SerialDevice);
+ Lcr.Bits.DLab = 0;
+ WRITE_LCR (SerialDevice, Lcr.Data);
+
+ //
+ // Turn off all interrupts
+ //
+ Ier.Data = READ_IER (SerialDevice);
+ Ier.Bits.Ravie = 0;
+ Ier.Bits.Theie = 0;
+ Ier.Bits.Rie = 0;
+ Ier.Bits.Mie = 0;
+ WRITE_IER (SerialDevice, Ier.Data);
+
+ //
+ // Disable the FIFO.
+ //
+ Fcr.Bits.TrFIFOE = 0;
+ WRITE_FCR (SerialDevice, Fcr.Data);
+
+ //
+ // Turn off loopback and disable device interrupt.
+ //
+ Mcr.Data = READ_MCR (SerialDevice);
+ Mcr.Bits.Out1 = 0;
+ Mcr.Bits.Out2 = 0;
+ Mcr.Bits.Lme = 0;
+ WRITE_MCR (SerialDevice, Mcr.Data);
+
+ //
+ // Clear the scratch pad register
+ //
+ WRITE_SCR (SerialDevice, 0);
+
+ //
+ // Go set the current attributes
+ //
+ Status = This->SetAttributes (
+ This,
+ This->Mode->BaudRate,
+ This->Mode->ReceiveFifoDepth,
+ This->Mode->Timeout,
+ (EFI_PARITY_TYPE) This->Mode->Parity,
+ (UINT8) This->Mode->DataBits,
+ (EFI_STOP_BITS_TYPE) This->Mode->StopBits
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Go set the current control bits
+ //
+ Status = This->SetControl (
+ This,
+ This->Mode->ControlMask
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // for 16550A enable FIFO, 16550 disable FIFO
+ //
+ Fcr.Bits.TrFIFOE = 1;
+ Fcr.Bits.ResetRF = 1;
+ Fcr.Bits.ResetTF = 1;
+ WRITE_FCR (SerialDevice, Fcr.Data);
+
+ //
+ // Reset the software FIFO
+ //
+ SerialDevice->Receive.First = 0;
+ SerialDevice->Receive.Last = 0;
+ SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;
+ SerialDevice->Transmit.First = 0;
+ SerialDevice->Transmit.Last = 0;
+ SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;
+
+ gBS->RestoreTPL (Tpl);
+
+ //
+ // Device reset is complete
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Set new attributes to a serial device.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param BaudRate The baudrate of the serial device
+ @param ReceiveFifoDepth The depth of receive FIFO buffer
+ @param Timeout The request timeout for a single char
+ @param Parity The type of parity used in serial device
+ @param DataBits Number of databits used in serial device
+ @param StopBits Number of stopbits used in serial device
+
+ @retval EFI_SUCCESS The new attributes were set
+ @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
+ @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialSetAttributes (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT64 BaudRate,
+ IN UINT32 ReceiveFifoDepth,
+ IN UINT32 Timeout,
+ IN EFI_PARITY_TYPE Parity,
+ IN UINT8 DataBits,
+ IN EFI_STOP_BITS_TYPE StopBits
+ )
+{
+ EFI_STATUS Status;
+ SERIAL_DEV *SerialDevice;
+ UINT32 Divisor;
+ UINT32 Remained;
+ SERIAL_PORT_LCR Lcr;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ EFI_TPL Tpl;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ //
+ // Check for default settings and fill in actual values.
+ //
+ if (BaudRate == 0) {
+ BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
+ }
+
+ if (ReceiveFifoDepth == 0) {
+ ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
+ }
+
+ if (Timeout == 0) {
+ Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
+ }
+
+ if (Parity == DefaultParity) {
+ Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity);
+ }
+
+ if (DataBits == 0) {
+ DataBits = PcdGet8 (PcdUartDefaultDataBits);
+ }
+
+ if (StopBits == DefaultStopBits) {
+ StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);
+ }
+ //
+ // 5 and 6 data bits can not be verified on a 16550A UART
+ // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
+ //
+ if ((DataBits == 5) || (DataBits == 6)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure all parameters are valid
+ //
+ if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
+ // 38400,57600,115200
+ //
+ if (BaudRate < 75) {
+ BaudRate = 50;
+ } else if (BaudRate < 110) {
+ BaudRate = 75;
+ } else if (BaudRate < 134) {
+ BaudRate = 110;
+ } else if (BaudRate < 150) {
+ BaudRate = 134;
+ } else if (BaudRate < 300) {
+ BaudRate = 150;
+ } else if (BaudRate < 600) {
+ BaudRate = 300;
+ } else if (BaudRate < 1200) {
+ BaudRate = 600;
+ } else if (BaudRate < 1800) {
+ BaudRate = 1200;
+ } else if (BaudRate < 2000) {
+ BaudRate = 1800;
+ } else if (BaudRate < 2400) {
+ BaudRate = 2000;
+ } else if (BaudRate < 3600) {
+ BaudRate = 2400;
+ } else if (BaudRate < 4800) {
+ BaudRate = 3600;
+ } else if (BaudRate < 7200) {
+ BaudRate = 4800;
+ } else if (BaudRate < 9600) {
+ BaudRate = 7200;
+ } else if (BaudRate < 19200) {
+ BaudRate = 9600;
+ } else if (BaudRate < 38400) {
+ BaudRate = 19200;
+ } else if (BaudRate < 57600) {
+ BaudRate = 38400;
+ } else if (BaudRate < 115200) {
+ BaudRate = 57600;
+ } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {
+ BaudRate = 115200;
+ }
+
+ if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Parity < NoParity) || (Parity > SpaceParity)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DataBits < 5) || (DataBits > 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
+ //
+ if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Compute divisor use to program the baud rate using a round determination
+ //
+ Divisor = (UINT32) DivU64x32Remainder (
+ PcdGet32 (PcdIohUartClkFreq),
+ ((UINT32) BaudRate * 16),
+ &Remained
+ );
+
+ if ((Divisor == 0) || ((Divisor & 0xffff0000) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Put serial port on Divisor Latch Mode
+ //
+ Lcr.Data = READ_LCR (SerialDevice);
+ Lcr.Bits.DLab = 1;
+ WRITE_LCR (SerialDevice, Lcr.Data);
+
+ //
+ // Write the divisor to the serial port
+ //
+ WRITE_DLL (SerialDevice, (UINT8) (Divisor & 0xff));
+ WRITE_DLM (SerialDevice, (UINT8) ((Divisor >> 8) & 0xff));
+
+ //
+ // Put serial port back in normal mode and set remaining attributes.
+ //
+ Lcr.Bits.DLab = 0;
+
+ switch (Parity) {
+ case NoParity:
+ Lcr.Bits.ParEn = 0;
+ Lcr.Bits.EvenPar = 0;
+ Lcr.Bits.SticPar = 0;
+ break;
+
+ case EvenParity:
+ Lcr.Bits.ParEn = 1;
+ Lcr.Bits.EvenPar = 1;
+ Lcr.Bits.SticPar = 0;
+ break;
+
+ case OddParity:
+ Lcr.Bits.ParEn = 1;
+ Lcr.Bits.EvenPar = 0;
+ Lcr.Bits.SticPar = 0;
+ break;
+
+ case SpaceParity:
+ Lcr.Bits.ParEn = 1;
+ Lcr.Bits.EvenPar = 1;
+ Lcr.Bits.SticPar = 1;
+ break;
+
+ case MarkParity:
+ Lcr.Bits.ParEn = 1;
+ Lcr.Bits.EvenPar = 0;
+ Lcr.Bits.SticPar = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (StopBits) {
+ case OneStopBit:
+ Lcr.Bits.StopB = 0;
+ break;
+
+ case OneFiveStopBits:
+ case TwoStopBits:
+ Lcr.Bits.StopB = 1;
+ break;
+
+ default:
+ break;
+ }
+ //
+ // DataBits
+ //
+ Lcr.Bits.SerialDB = (UINT8) ((DataBits - 5) & 0x03);
+ WRITE_LCR (SerialDevice, Lcr.Data);
+
+ //
+ // Set the Serial I/O mode
+ //
+ This->Mode->BaudRate = BaudRate;
+ This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;
+ This->Mode->Timeout = Timeout;
+ This->Mode->Parity = Parity;
+ This->Mode->DataBits = DataBits;
+ This->Mode->StopBits = StopBits;
+
+ //
+ // See if Device Path Node has actually changed
+ //
+ if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&
+ SerialDevice->UartDevicePath.DataBits == DataBits &&
+ SerialDevice->UartDevicePath.Parity == Parity &&
+ SerialDevice->UartDevicePath.StopBits == StopBits
+ ) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_SUCCESS;
+ }
+ //
+ // Update the device path
+ //
+ SerialDevice->UartDevicePath.BaudRate = BaudRate;
+ SerialDevice->UartDevicePath.DataBits = DataBits;
+ SerialDevice->UartDevicePath.Parity = (UINT8) Parity;
+ SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
+
+ NewDevicePath = AppendDevicePathNode (
+ SerialDevice->ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath
+ );
+ if (NewDevicePath == NULL) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (SerialDevice->Handle != NULL) {
+ Status = gBS->ReinstallProtocolInterface (
+ SerialDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ NewDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (Tpl);
+ return Status;
+ }
+ }
+
+ if (SerialDevice->DevicePath != NULL) {
+ gBS->FreePool (SerialDevice->DevicePath);
+ }
+
+ SerialDevice->DevicePath = NewDevicePath;
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set Control Bits.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param Control Control bits that can be settable
+
+ @retval EFI_SUCCESS New Control bits were set successfully
+ @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialSetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT32 Control
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_MCR Mcr;
+ EFI_TPL Tpl;
+
+ //
+ // The control bits that can be set are :
+ // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
+ // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
+ // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
+ // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
+ //
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ //
+ // first determine the parameter is invalid
+ //
+ if ((Control & 0xffff8ffc) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Mcr.Data = READ_MCR (SerialDevice);
+ Mcr.Bits.DtrC = 0;
+ Mcr.Bits.Rts = 0;
+ Mcr.Bits.Lme = 0;
+ SerialDevice->SoftwareLoopbackEnable = FALSE;
+ SerialDevice->HardwareFlowControl = FALSE;
+
+ if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
+ Mcr.Bits.DtrC = 1;
+ }
+
+ if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
+ Mcr.Bits.Rts = 1;
+ }
+
+ if ((Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
+ Mcr.Bits.Lme = 1;
+ }
+
+ if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
+ SerialDevice->HardwareFlowControl = TRUE;
+ }
+
+ WRITE_MCR (SerialDevice, Mcr.Data);
+
+ if ((Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
+ SerialDevice->SoftwareLoopbackEnable = TRUE;
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get ControlBits.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param Control Control signals of the serial device
+
+ @retval EFI_SUCCESS Get Control signals successfully
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialGetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ OUT UINT32 *Control
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_MSR Msr;
+ SERIAL_PORT_MCR Mcr;
+ EFI_TPL Tpl;
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ *Control = 0;
+
+ //
+ // Read the Modem Status Register
+ //
+ Msr.Data = READ_MSR (SerialDevice);
+
+ if (Msr.Bits.Cts == 1) {
+ *Control |= EFI_SERIAL_CLEAR_TO_SEND;
+ }
+
+ if (Msr.Bits.Dsr == 1) {
+ *Control |= EFI_SERIAL_DATA_SET_READY;
+ }
+
+ if (Msr.Bits.Ri == 1) {
+ *Control |= EFI_SERIAL_RING_INDICATE;
+ }
+
+ if (Msr.Bits.Dcd == 1) {
+ *Control |= EFI_SERIAL_CARRIER_DETECT;
+ }
+ //
+ // Read the Modem Control Register
+ //
+ Mcr.Data = READ_MCR (SerialDevice);
+
+ if (Mcr.Bits.DtrC == 1) {
+ *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
+ }
+
+ if (Mcr.Bits.Rts == 1) {
+ *Control |= EFI_SERIAL_REQUEST_TO_SEND;
+ }
+
+ if (Mcr.Bits.Lme == 1) {
+ *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
+ }
+
+ if (SerialDevice->HardwareFlowControl) {
+ *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
+ }
+ //
+ // See if the Transmit FIFO is empty
+ //
+ IohSerialReceiveTransmit (SerialDevice);
+
+ if (IohSerialFifoEmpty (&SerialDevice->Transmit)) {
+ *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ }
+ //
+ // See if the Receive FIFO is empty.
+ //
+ IohSerialReceiveTransmit (SerialDevice);
+
+ if (IohSerialFifoEmpty (&SerialDevice->Receive)) {
+ *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
+ }
+
+ if (SerialDevice->SoftwareLoopbackEnable) {
+ *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write the specified number of bytes to serial device.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param BufferSize On input the size of Buffer, on output the amount of
+ data actually written
+ @param Buffer The buffer of data to write
+
+ @retval EFI_SUCCESS The data were written successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The write operation was stopped due to timeout
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialWrite (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ UINT8 *CharBuffer;
+ UINT32 Index;
+ UINTN Elapsed;
+ UINTN ActualWrite;
+ EFI_TPL Tpl;
+
+ //CpuDeadLoop();
+ //DEBUG((EFI_D_ERROR, "== %s\n", Buffer));
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+ Elapsed = 0;
+ ActualWrite = 0;
+
+ if (*BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (Buffer == NULL) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE,
+ EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
+ SerialDevice->DevicePath
+ );
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ CharBuffer = (UINT8 *) Buffer;
+
+ for (Index = 0; Index < *BufferSize; Index++) {
+ IohSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);
+
+ while (IohSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !IohSerialFifoEmpty (&SerialDevice->Transmit)) {
+ //
+ // Unsuccessful write so check if timeout has expired, if not,
+ // stall for a bit, increment time elapsed, and try again
+ //
+ if (Elapsed >= This->Mode->Timeout) {
+ *BufferSize = ActualWrite;
+ gBS->RestoreTPL (Tpl);
+ return EFI_TIMEOUT;
+ }
+
+ gBS->Stall (TIMEOUT_STALL_INTERVAL);
+
+ Elapsed += TIMEOUT_STALL_INTERVAL;
+ }
+
+ ActualWrite++;
+ //
+ // Successful write so reset timeout
+ //
+ Elapsed = 0;
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read the specified number of bytes from serial device.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param BufferSize On input the size of Buffer, on output the amount of
+ data returned in buffer
+ @param Buffer The buffer to return the data into
+
+ @retval EFI_SUCCESS The data were read successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The read operation was stopped due to timeout
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialRead (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ UINT32 Index;
+ UINT8 *CharBuffer;
+ UINTN Elapsed;
+ EFI_STATUS Status;
+ EFI_TPL Tpl;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+ Elapsed = 0;
+
+ if (*BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = IohSerialReceiveTransmit (SerialDevice);
+
+ if (EFI_ERROR (Status)) {
+ *BufferSize = 0;
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE,
+ EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
+ SerialDevice->DevicePath
+ );
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ CharBuffer = (UINT8 *) Buffer;
+ for (Index = 0; Index < *BufferSize; Index++) {
+ while (IohSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) {
+ //
+ // Unsuccessful read so check if timeout has expired, if not,
+ // stall for a bit, increment time elapsed, and try again
+ // Need this time out to get conspliter to work.
+ //
+ if (Elapsed >= This->Mode->Timeout) {
+ *BufferSize = Index;
+ gBS->RestoreTPL (Tpl);
+ return EFI_TIMEOUT;
+ }
+
+ gBS->Stall (TIMEOUT_STALL_INTERVAL);
+ Elapsed += TIMEOUT_STALL_INTERVAL;
+
+ Status = IohSerialReceiveTransmit (SerialDevice);
+ if (Status == EFI_DEVICE_ERROR) {
+ *BufferSize = Index;
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // Successful read so reset timeout
+ //
+ Elapsed = 0;
+ }
+
+ IohSerialReceiveTransmit (SerialDevice);
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Use scratchpad register to test if this serial port is present.
+
+ @param SerialDevice Pointer to serial device structure
+
+ @return if this serial port is present
+**/
+BOOLEAN
+IohSerialPortPresent (
+ IN SERIAL_DEV *SerialDevice
+ )
+
+{
+ UINT8 Temp;
+ BOOLEAN Status;
+
+ Status = TRUE;
+
+ //
+ // Save SCR reg
+ //
+ Temp = READ_SCR (SerialDevice);
+ WRITE_SCR (SerialDevice, 0xAA);
+
+ if (READ_SCR (SerialDevice) != 0xAA) {
+ Status = FALSE;
+ }
+
+ WRITE_SCR (SerialDevice, 0x55);
+
+ if (READ_SCR (SerialDevice) != 0x55) {
+ Status = FALSE;
+ }
+ //
+ // Restore SCR
+ //
+ WRITE_SCR (SerialDevice, Temp);
+ return Status;
+}
+
+/**
+ Use PciIo protocol to read serial port.
+
+ @param PciIo Pointer to EFI_PCI_IO_PROTOCOL instance
+ @param BaseAddress Serial port register group base address
+ @param Offset Offset in register group
+
+ @return Data read from serial port
+
+**/
+UINT8
+IohSerialReadPort (
+ IN SERIAL_DEV *SerialDevice,
+ IN UINT32 Offset
+ )
+{
+ if (FeaturePcdGet(PcdIohUartUseMmio)) {
+ return MmioRead8 (SerialDevice->BaseAddress + Offset);
+ } else {
+ return IoRead8 (SerialDevice->BaseAddress + Offset);
+ }
+}
+
+/**
+ Use PciIo protocol to write serial port.
+
+ @param PciIo Pointer to EFI_PCI_IO_PROTOCOL instance
+ @param BaseAddress Serial port register group base address
+ @param Offset Offset in register group
+ @param Data data which is to be written to some serial port register
+
+**/
+VOID
+IohSerialWritePort (
+ IN SERIAL_DEV *SerialDevice,
+ IN UINT32 Offset,
+ IN UINT8 Data
+ )
+{
+ if (FeaturePcdGet(PcdIohUartUseMmio)) {
+ MmioWrite8 (SerialDevice->BaseAddress + Offset, Data);
+ } else {
+ IoWrite8 (SerialDevice->BaseAddress + Offset, Data);
+ }
+}
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.h b/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.h
new file mode 100755
index 0000000..65a3576
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.h
@@ -0,0 +1,857 @@
+/** @file
+ Include for Serial Driver
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _SERIAL_H_
+#define _SERIAL_H_
+
+
+#include <FrameworkDxe.h>
+
+#include <Protocol/IsaIo.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DevicePathToText.h>
+
+#include <Guid/GlobalVariable.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+
+#include <IndustryStandard/Pci22.h>
+
+//
+// Driver Binding Externs
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver;
+extern EFI_COMPONENT_NAME_PROTOCOL gIohSerialComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gIohSerialComponentName2;
+
+//
+// Internal Data Structures
+//
+#define SERIAL_DEV_SIGNATURE SIGNATURE_32 ('s', 'e', 'r', 'd')
+#define SERIAL_MAX_BUFFER_SIZE 16
+#define TIMEOUT_STALL_INTERVAL 10
+
+//
+// Name: SERIAL_DEV_FIFO
+// Purpose: To define Receive FIFO and Transmit FIFO
+// Context: Used by serial data transmit and receive
+// Fields:
+// First UINT32: The index of the first data in array Data[]
+// Last UINT32: The index, which you can put a new data into array Data[]
+// Surplus UINT32: Identify how many data you can put into array Data[]
+// Data[] UINT8 : An array, which used to store data
+//
+typedef struct {
+ UINT32 First;
+ UINT32 Last;
+ UINT32 Surplus;
+ UINT8 Data[SERIAL_MAX_BUFFER_SIZE];
+} SERIAL_DEV_FIFO;
+
+typedef enum {
+ Uart8250 = 0,
+ Uart16450 = 1,
+ Uart16550 = 2,
+ Uart16550A= 3
+} EFI_UART_TYPE;
+
+//
+// Name: SERIAL_DEV
+// Purpose: To provide device specific information
+// Context:
+// Fields:
+// Signature UINTN: The identity of the serial device
+// SerialIo SERIAL_IO_PROTOCOL: Serial I/O protocol interface
+// SerialMode SERIAL_IO_MODE:
+// DevicePath EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device
+// Handle EFI_HANDLE: The handle instance attached to serial device
+// BaseAddress UINT16: The base address of specific serial device
+// Receive SERIAL_DEV_FIFO: The FIFO used to store data,
+// which is received by UART
+// Transmit SERIAL_DEV_FIFO: The FIFO used to store data,
+// which you want to transmit by UART
+// SoftwareLoopbackEnable BOOLEAN:
+// Type EFI_UART_TYPE: Specify the UART type of certain serial device
+//
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE Handle;
+ EFI_SERIAL_IO_PROTOCOL SerialIo;
+ EFI_SERIAL_IO_MODE SerialMode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ UART_DEVICE_PATH UartDevicePath;
+
+ UINT32 BaseAddress;
+ SERIAL_DEV_FIFO Receive;
+ SERIAL_DEV_FIFO Transmit;
+ BOOLEAN SoftwareLoopbackEnable;
+ BOOLEAN HardwareFlowControl;
+ EFI_UART_TYPE Type;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} SERIAL_DEV;
+
+#define SERIAL_DEV_FROM_THIS(a) CR (a, SERIAL_DEV, SerialIo, SERIAL_DEV_SIGNATURE)
+
+//
+// Serial Driver Defaults
+//
+#define SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH 1
+#define SERIAL_PORT_DEFAULT_TIMEOUT 1000000
+#define SERIAL_PORT_DEFAULT_CONTROL_MASK 0
+
+#define SYNOPSIS_UART0_DID 0x0936
+
+//
+// 115200 baud with rounding errors
+//
+#define SERIAL_PORT_MAX_BAUD_RATE 115400
+#define SERIAL_PORT_MIN_BAUD_RATE 50
+
+#define SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH 16
+#define SERIAL_PORT_MIN_TIMEOUT 1 // 1 uS
+#define SERIAL_PORT_MAX_TIMEOUT 100000000 // 100 seconds
+//
+// UART Registers
+//
+#define SERIAL_REGISTER_THR 0 // WO Transmit Holding Register
+#define SERIAL_REGISTER_RBR 0 // RO Receive Buffer Register
+#define SERIAL_REGISTER_DLL 0 // R/W Divisor Latch LSB
+#define SERIAL_REGISTER_DLM 4 // R/W Divisor Latch MSB
+#define SERIAL_REGISTER_IER 4 // R/W Interrupt Enable Register
+#define SERIAL_REGISTER_IIR 8 // RO Interrupt Identification Register
+#define SERIAL_REGISTER_FCR 8 // WO FIFO Cotrol Register
+#define SERIAL_REGISTER_LCR 12 // R/W Line Control Register
+#define SERIAL_REGISTER_MCR 16 // R/W Modem Control Register
+#define SERIAL_REGISTER_LSR 20 // R/W Line Status Register
+#define SERIAL_REGISTER_MSR 24 // R/W Modem Status Register
+#define SERIAL_REGISTER_SCR 28 // R/W Scratch Pad Register
+#pragma pack(1)
+//
+// Name: SERIAL_PORT_IER_BITS
+// Purpose: Define each bit in Interrupt Enable Register
+// Context:
+// Fields:
+// Ravie Bit0: Receiver Data Available Interrupt Enable
+// Theie Bit1: Transmistter Holding Register Empty Interrupt Enable
+// Rie Bit2: Receiver Interrupt Enable
+// Mie Bit3: Modem Interrupt Enable
+// Reserved Bit4-Bit7: Reserved
+//
+typedef struct {
+ UINT8 Ravie : 1;
+ UINT8 Theie : 1;
+ UINT8 Rie : 1;
+ UINT8 Mie : 1;
+ UINT8 Reserved : 4;
+} SERIAL_PORT_IER_BITS;
+
+//
+// Name: SERIAL_PORT_IER
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_IER_BITS: Bits of the IER
+// Data UINT8: the value of the IER
+//
+typedef union {
+ SERIAL_PORT_IER_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_IER;
+
+//
+// Name: SERIAL_PORT_FCR_BITS
+// Purpose: Define each bit in FIFO Control Register
+// Context:
+// Fields:
+// TrFIFOE Bit0: Transmit and Receive FIFO Enable
+// ResetRF Bit1: Reset Reciever FIFO
+// ResetTF Bit2: Reset Transmistter FIFO
+// Dms Bit3: DMA Mode Select
+// Reserved Bit4-Bit5: Reserved
+// Rtb Bit6-Bit7: Receive Trigger Bits
+//
+typedef struct {
+ UINT8 TrFIFOE : 1;
+ UINT8 ResetRF : 1;
+ UINT8 ResetTF : 1;
+ UINT8 Dms : 1;
+ UINT8 Reserved : 2;
+ UINT8 Rtb : 2;
+} SERIAL_PORT_FCR_BITS;
+
+//
+// Name: SERIAL_PORT_FCR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_FCR_BITS: Bits of the FCR
+// Data UINT8: the value of the FCR
+//
+typedef union {
+ SERIAL_PORT_FCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_FCR;
+
+//
+// Name: SERIAL_PORT_LCR_BITS
+// Purpose: Define each bit in Line Control Register
+// Context:
+// Fields:
+// SerialDB Bit0-Bit1: Number of Serial Data Bits
+// StopB Bit2: Number of Stop Bits
+// ParEn Bit3: Parity Enable
+// EvenPar Bit4: Even Parity Select
+// SticPar Bit5: Sticky Parity
+// BrCon Bit6: Break Control
+// DLab Bit7: Divisor Latch Access Bit
+//
+typedef struct {
+ UINT8 SerialDB : 2;
+ UINT8 StopB : 1;
+ UINT8 ParEn : 1;
+ UINT8 EvenPar : 1;
+ UINT8 SticPar : 1;
+ UINT8 BrCon : 1;
+ UINT8 DLab : 1;
+} SERIAL_PORT_LCR_BITS;
+
+//
+// Name: SERIAL_PORT_LCR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_LCR_BITS: Bits of the LCR
+// Data UINT8: the value of the LCR
+//
+typedef union {
+ SERIAL_PORT_LCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_LCR;
+
+//
+// Name: SERIAL_PORT_MCR_BITS
+// Purpose: Define each bit in Modem Control Register
+// Context:
+// Fields:
+// DtrC Bit0: Data Terminal Ready Control
+// Rts Bit1: Request To Send Control
+// Out1 Bit2: Output1
+// Out2 Bit3: Output2, used to disable interrupt
+// Lme; Bit4: Loopback Mode Enable
+// Reserved Bit5-Bit7: Reserved
+//
+typedef struct {
+ UINT8 DtrC : 1;
+ UINT8 Rts : 1;
+ UINT8 Out1 : 1;
+ UINT8 Out2 : 1;
+ UINT8 Lme : 1;
+ UINT8 Reserved : 3;
+} SERIAL_PORT_MCR_BITS;
+
+//
+// Name: SERIAL_PORT_MCR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_MCR_BITS: Bits of the MCR
+// Data UINT8: the value of the MCR
+//
+typedef union {
+ SERIAL_PORT_MCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_MCR;
+
+//
+// Name: SERIAL_PORT_LSR_BITS
+// Purpose: Define each bit in Line Status Register
+// Context:
+// Fields:
+// Dr Bit0: Receiver Data Ready Status
+// Oe Bit1: Overrun Error Status
+// Pe Bit2: Parity Error Status
+// Fe Bit3: Framing Error Status
+// Bi Bit4: Break Interrupt Status
+// Thre Bit5: Transmistter Holding Register Status
+// Temt Bit6: Transmitter Empty Status
+// FIFOe Bit7: FIFO Error Status
+//
+typedef struct {
+ UINT8 Dr : 1;
+ UINT8 Oe : 1;
+ UINT8 Pe : 1;
+ UINT8 Fe : 1;
+ UINT8 Bi : 1;
+ UINT8 Thre : 1;
+ UINT8 Temt : 1;
+ UINT8 FIFOe : 1;
+} SERIAL_PORT_LSR_BITS;
+
+//
+// Name: SERIAL_PORT_LSR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_LSR_BITS: Bits of the LSR
+// Data UINT8: the value of the LSR
+//
+typedef union {
+ SERIAL_PORT_LSR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_LSR;
+
+//
+// Name: SERIAL_PORT_MSR_BITS
+// Purpose: Define each bit in Modem Status Register
+// Context:
+// Fields:
+// DeltaCTS Bit0: Delta Clear To Send Status
+// DeltaDSR Bit1: Delta Data Set Ready Status
+// TrailingEdgeRI Bit2: Trailing Edge of Ring Indicator Status
+// DeltaDCD Bit3: Delta Data Carrier Detect Status
+// Cts Bit4: Clear To Send Status
+// Dsr Bit5: Data Set Ready Status
+// Ri Bit6: Ring Indicator Status
+// Dcd Bit7: Data Carrier Detect Status
+//
+typedef struct {
+ UINT8 DeltaCTS : 1;
+ UINT8 DeltaDSR : 1;
+ UINT8 TrailingEdgeRI : 1;
+ UINT8 DeltaDCD : 1;
+ UINT8 Cts : 1;
+ UINT8 Dsr : 1;
+ UINT8 Ri : 1;
+ UINT8 Dcd : 1;
+} SERIAL_PORT_MSR_BITS;
+
+//
+// Name: SERIAL_PORT_MSR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_MSR_BITS: Bits of the MSR
+// Data UINT8: the value of the MSR
+//
+typedef union {
+ SERIAL_PORT_MSR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_MSR;
+
+#pragma pack()
+//
+// Define serial register I/O macros
+//
+#define READ_RBR(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_RBR)
+#define READ_DLL(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_DLL)
+#define READ_DLM(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_DLM)
+#define READ_IER(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_IER)
+#define READ_IIR(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_IIR)
+#define READ_LCR(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_LCR)
+#define READ_MCR(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_MCR)
+#define READ_LSR(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_LSR)
+#define READ_MSR(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_MSR)
+#define READ_SCR(DEV) IohSerialReadPort (DEV, SERIAL_REGISTER_SCR)
+
+#define WRITE_THR(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_THR, D)
+#define WRITE_DLL(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_DLL, D)
+#define WRITE_DLM(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_DLM, D)
+#define WRITE_IER(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_IER, D)
+#define WRITE_FCR(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_FCR, D)
+#define WRITE_LCR(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_LCR, D)
+#define WRITE_MCR(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_MCR, D)
+#define WRITE_LSR(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_LSR, D)
+#define WRITE_MSR(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_MSR, D)
+#define WRITE_SCR(DEV, D) IohSerialWritePort (DEV, SERIAL_REGISTER_SCR, D)
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+/**
+ Check to see if this driver supports the given controller
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @return EFI_SUCCESS This driver can support the given controller
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Start to management the controller passed in
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @return EFI_SUCCESS Driver is started successfully
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Disconnect this driver with the controller, uninstall related protocol instance
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param NumberOfChildren Number of child device.
+ @param ChildHandleBuffer A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Operation successfully
+ @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Serial I/O Protocol Interface
+//
+/**
+ Reset serial device.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+
+ @retval EFI_SUCCESS Reset successfully
+ @retval EFI_DEVICE_ERROR Failed to reset
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialReset (
+ IN EFI_SERIAL_IO_PROTOCOL *This
+ );
+
+/**
+ Set new attributes to a serial device.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param BaudRate The baudrate of the serial device
+ @param ReceiveFifoDepth The depth of receive FIFO buffer
+ @param Timeout The request timeout for a single char
+ @param Parity The type of parity used in serial device
+ @param DataBits Number of databits used in serial device
+ @param StopBits Number of stopbits used in serial device
+
+ @retval EFI_SUCCESS The new attributes were set
+ @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
+ @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialSetAttributes (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT64 BaudRate,
+ IN UINT32 ReceiveFifoDepth,
+ IN UINT32 Timeout,
+ IN EFI_PARITY_TYPE Parity,
+ IN UINT8 DataBits,
+ IN EFI_STOP_BITS_TYPE StopBits
+ );
+
+/**
+ Set Control Bits.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param Control Control bits that can be settable
+
+ @retval EFI_SUCCESS New Control bits were set successfully
+ @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialSetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT32 Control
+ );
+
+/**
+ Get ControlBits.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param Control Control signals of the serial device
+
+ @retval EFI_SUCCESS Get Control signals successfully
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialGetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ OUT UINT32 *Control
+ );
+
+/**
+ Write the specified number of bytes to serial device.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param BufferSize On input the size of Buffer, on output the amount of
+ data actually written
+ @param Buffer The buffer of data to write
+
+ @retval EFI_SUCCESS The data were written successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The write operation was stopped due to timeout
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialWrite (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Read the specified number of bytes from serial device.
+
+ @param This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param BufferSize On input the size of Buffer, on output the amount of
+ data returned in buffer
+ @param Buffer The buffer to return the data into
+
+ @retval EFI_SUCCESS The data were read successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The read operation was stopped due to timeout
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialRead (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+//
+// Internal Functions
+//
+/**
+ Use scratchpad register to test if this serial port is present.
+
+ @param SerialDevice Pointer to serial device structure
+
+ @return if this serial port is present
+**/
+BOOLEAN
+IohSerialPortPresent (
+ IN SERIAL_DEV *SerialDevice
+ );
+
+/**
+ Detect whether specific FIFO is full or not.
+
+ @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @return whether specific FIFO is full or not
+
+**/
+BOOLEAN
+IohSerialFifoFull (
+ IN SERIAL_DEV_FIFO *Fifo
+ );
+
+/**
+ Detect whether specific FIFO is empty or not.
+
+ @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @return whether specific FIFO is empty or not
+
+**/
+BOOLEAN
+IohSerialFifoEmpty (
+ IN SERIAL_DEV_FIFO *Fifo
+ );
+
+/**
+ Add data to specific FIFO.
+
+ @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param Data the data added to FIFO
+
+ @retval EFI_SUCCESS Add data to specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
+
+**/
+EFI_STATUS
+IohSerialFifoAdd (
+ IN SERIAL_DEV_FIFO *Fifo,
+ IN UINT8 Data
+ );
+
+/**
+ Remove data from specific FIFO.
+
+ @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param Data the data removed from FIFO
+
+ @retval EFI_SUCCESS Remove data from specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
+
+**/
+EFI_STATUS
+IohSerialFifoRemove (
+ IN SERIAL_DEV_FIFO *Fifo,
+ OUT UINT8 *Data
+ );
+
+/**
+ Reads and writes all avaliable data.
+
+ @param SerialDevice The device to flush
+
+ @retval EFI_SUCCESS Data was read/written successfully.
+ @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
+ this happens, pending writes are not done.
+
+**/
+EFI_STATUS
+IohSerialReceiveTransmit (
+ IN SERIAL_DEV *SerialDevice
+ );
+
+/**
+ Use IsaIo protocol to read serial port.
+
+ @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
+ @param BaseAddress Serial port register group base address
+ @param Offset Offset in register group
+
+ @return Data read from serial port
+
+**/
+UINT8
+IohSerialReadPort (
+ IN SERIAL_DEV *SerialDevice,
+ IN UINT32 Offset
+ );
+
+/**
+ Use IsaIo protocol to write serial port.
+
+ @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
+ @param BaseAddress Serial port register group base address
+ @param Offset Offset in register group
+ @param Data data which is to be written to some serial port register
+
+**/
+VOID
+IohSerialWritePort (
+ IN SERIAL_DEV *SerialDevice,
+ IN UINT32 Offset,
+ IN UINT8 Data
+ );
+
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+IohSerialComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ Add the component name for the serial io device
+
+ @param SerialDevice A pointer to the SERIAL_DEV instance.
+
+ @param IsaIo A pointer to the EFI_ISA_IO_PROTOCOL instance.
+
+**/
+VOID
+AddName (
+ IN SERIAL_DEV *SerialDevice
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/SerialDxe.inf b/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/SerialDxe.inf
new file mode 100644
index 0000000..4b36802
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/SerialDxe.inf
@@ -0,0 +1,95 @@
+## @file
+# FIX ME!
+#
+# FIX ME!
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IohSerialDxe
+ FILE_GUID = bf40c9d7-c415-41c2-9ec9-da6e07878520
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeIohSerial
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gSerialControllerDriver
+# COMPONENT_NAME = gIsaSerialComponentName
+# COMPONENT_NAME2 = gIsaSerialComponentName2
+#
+
+[Sources]
+ ComponentName.c
+ Serial.h
+ Serial.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ ReportStatusCodeLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ DevicePathLib
+ UefiLib
+ UefiDriverEntryPoint
+ DebugLib
+ IoLib
+
+[Protocols]
+ gEfiIsaIoProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## TO_START
+ gEfiSerialIoProtocolGuid ## BY_START
+ gEfiPciIoProtocolGuid
+
+[FeaturePcd]
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartUseMmio
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartClkFreq
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartFunctionNumber
+
+[Depex]
+ gEfiPciIoProtocolGuid
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c
new file mode 100644
index 0000000..a7b5474
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c
@@ -0,0 +1,344 @@
+/** @file
+ Implementation of Usb Controller PPI.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiPei.h>
+#include <Ppi/UsbController.h>
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/IoLib.h>
+
+#include "UsbPei.h"
+
+//
+// Globals
+//
+//
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiUsbControllerPpiGuid,
+ NULL
+};
+
+UINTN IohOhciPciReg[IOH_MAX_OHCI_USB_CONTROLLERS] = {
+ PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_OHCI_DEVICE_NUMBER, IOH_OHCI_FUNCTION_NUMBER, 0)
+};
+
+UINTN IohEhciPciReg[IOH_MAX_EHCI_USB_CONTROLLERS] = {
+ PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, 0),
+};
+
+/**
+ When EHCI get started in DXE, OHCI couldn't get the ownership
+ of roothub after warm reset because CF@EHCI hasn't been cleared.
+ We should clear that reg before UpdateBootMode. But Reg@EHCI is
+ memory-mapped, so need assume a range of space without conflict
+ in PCI memory space.
+
+ @param[in] PeiServices The pointer of EFI_PEI_SERVICES
+
+**/
+
+VOID
+SwitchConfigFlag (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ UINT32 SavBaseAddr;
+ UINT32 UsbBaseAddr;
+ UINT16 SaveCmdData;
+ UINT8 EhciCapLen;
+ UINT8 Index;
+ UsbBaseAddr = 0;
+
+ for (Index = 0; Index < IOH_MAX_EHCI_USB_CONTROLLERS; Index++) {
+ UsbBaseAddr = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress);
+ //
+ // Manage EHCI on IOH, set UsbBaseAddr
+ //
+ SavBaseAddr = PciRead32 (IohEhciPciReg[Index] | R_IOH_USB_MEMBAR);
+ PciWrite32 (IohEhciPciReg[Index] | R_IOH_USB_MEMBAR, UsbBaseAddr);
+ //
+ // Save Cmd register
+ //
+ SaveCmdData = PciRead16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND);
+ //
+ // Enable EHCI on IOH
+ //
+ PciOr16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND, B_IOH_USB_COMMAND_BME | B_IOH_USB_COMMAND_MSE );
+ //
+ // Clear CF register on EHCI
+ //
+ EhciCapLen = MmioRead8 (UsbBaseAddr + R_IOH_EHCI_CAPLENGTH);
+ MmioWrite32 (UsbBaseAddr + EhciCapLen + R_IOH_EHCI_CONFIGFLAGS, 0);
+
+ DEBUG ((EFI_D_INFO, "CF@EHCI = %x \n", UsbBaseAddr + EhciCapLen + R_IOH_EHCI_CONFIGFLAGS));
+ //
+ // Restore EHCI UsbBaseAddr in PCI space
+ //
+ PciWrite32 (IohEhciPciReg[Index] | R_IOH_USB_MEMBAR, SavBaseAddr);
+ //
+ // Restore EHCI Command register in PCI space
+ //
+ PciWrite16(IohEhciPciReg[Index] | R_IOH_USB_COMMAND, SaveCmdData);
+ }
+}
+/**
+ Retrieved specified the USB controller information.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This This PEI_USB_CONTROLLER_PPI instance.
+ @param UsbControllerId Indicate which usb controller information will be retrieved.
+ @param ControllerType Indicate the controller is Ehci, Ohci, OHCI
+ @param BaseAddress Indicate the memory bar of the controller
+
+ @retval EFI_SUCCESS The reset operation succeeded.
+ @retval EFI_INVALID_PARAMETER Attributes is not valid.
+
+**/
+
+EFI_STATUS
+GetOhciController (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_CONTROLLER_PPI *This,
+ IN UINT8 UsbControllerId,
+ IN UINTN *ControllerType,
+ IN UINTN *BaseAddress
+ )
+{
+ IOH_OHCI_DEVICE *PeiIohOhciDev;
+
+ PeiIohOhciDev = IOH_OHCI_DEVICE_FROM_THIS (This);
+
+ if (UsbControllerId >= IOH_MAX_OHCI_USB_CONTROLLERS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *ControllerType = PEI_OHCI_CONTROLLER;
+ *BaseAddress = PeiIohOhciDev->MmioBase[UsbControllerId];
+
+ return EFI_SUCCESS;
+}
+/**
+ Retrieved specified the USB controller information.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This This PEI_USB_CONTROLLER_PPI instance.
+ @param UsbControllerId Indicate which usb controller information will be retrieved.
+ @param ControllerType Indicate the controller is Ehci, Ohci, OHCI
+ @param BaseAddress Indicate the memory bar of the controller
+
+ @retval EFI_SUCCESS The reset operation succeeded.
+ @retval EFI_INVALID_PARAMETER Attributes is not valid.
+
+**/
+
+EFI_STATUS
+GetEhciController (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_CONTROLLER_PPI *This,
+ IN UINT8 UsbControllerId,
+ IN UINTN *ControllerType,
+ IN UINTN *BaseAddress
+ )
+{
+ IOH_EHCI_DEVICE *PeiIohEhciDev;
+
+ PeiIohEhciDev = IOH_EHCI_DEVICE_FROM_THIS (This);
+
+ if (UsbControllerId >= IOH_MAX_EHCI_USB_CONTROLLERS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *ControllerType = PEI_EHCI_CONTROLLER;
+ *BaseAddress = PeiIohEhciDev->MmioBase[UsbControllerId];
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieved specified the USB controller information.
+
+ @param IohOhciPciReg Ohci device address list.
+ @param OhciCount The count of the OHCI
+ @param IohEhciPciReg Ehci device address list.
+ @param EhciCount The count of the EHCI
+
+**/
+
+VOID
+EnableBusMaster (
+ IN UINTN IohOhciPciReg[],
+ IN UINT8 OhciCount,
+ IN UINTN IohEhciPciReg[],
+ IN UINT8 EhciCount
+ )
+{
+ UINT8 Index;
+ UINT16 CmdReg;
+ for (Index = 0; Index < OhciCount; Index ++) {
+ CmdReg = PciRead16 (IohOhciPciReg[Index] | R_IOH_USB_COMMAND);
+ CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_BME );
+ PciWrite16 (IohOhciPciReg[Index] | R_IOH_USB_COMMAND, CmdReg);
+ }
+ for (Index = 0; Index < EhciCount; Index ++) {
+ CmdReg = PciRead16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND);
+ CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_BME );
+ PciWrite16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND, CmdReg);
+ }
+}
+
+PEI_USB_CONTROLLER_PPI mUsbControllerPpi[2] = { {GetOhciController}, {GetEhciController}};
+
+/**
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS PPI successfully installed
+
+**/
+EFI_STATUS
+PeimInitializeIchUsb (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN i;
+ EFI_PHYSICAL_ADDRESS AllocateAddress;
+ IOH_OHCI_DEVICE *PeiIohOhciDev;
+ IOH_EHCI_DEVICE *PeiIohEhciDev;
+ UINT16 CmdReg;
+
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ 1,
+ &AllocateAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EnableBusMaster (
+ IohOhciPciReg,
+ IOH_MAX_OHCI_USB_CONTROLLERS,
+ IohEhciPciReg,
+ IOH_MAX_EHCI_USB_CONTROLLERS
+ );
+
+ if (FeaturePcdGet (PcdEhciRecoveryEnabled)) {
+ DEBUG ((EFI_D_INFO, "UsbPei:EHCI is used for recovery\n"));
+ //
+ // EHCI recovery is enabled
+ //
+ PeiIohEhciDev = (IOH_EHCI_DEVICE *)((UINTN)AllocateAddress);
+ ZeroMem (PeiIohEhciDev, sizeof(IOH_EHCI_DEVICE));
+
+ PeiIohEhciDev->Signature = PEI_IOH_EHCI_SIGNATURE;
+ CopyMem(&(PeiIohEhciDev->UsbControllerPpi), &mUsbControllerPpi[1], sizeof(PEI_USB_CONTROLLER_PPI));
+ CopyMem(&(PeiIohEhciDev->PpiList), &mPpiList, sizeof(mPpiList));
+ PeiIohEhciDev->PpiList.Ppi = &PeiIohEhciDev->UsbControllerPpi;
+
+ //
+ // Assign resources and enable Ehci controllers
+ //
+ for (i = 0; i < IOH_MAX_EHCI_USB_CONTROLLERS; i++) {
+ DEBUG ((EFI_D_INFO, "UsbPei:Enable the %dth EHCI controller for recovery\n", i));
+ PeiIohEhciDev->MmioBase[i] = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress) + IOH_USB_CONTROLLER_MMIO_RANGE * i;
+ //
+ // Assign base address register, Enable Bus Master and Memory Io
+ //
+ PciWrite32 (IohEhciPciReg[i] | R_IOH_USB_MEMBAR, PeiIohEhciDev->MmioBase[i]);
+ CmdReg = PciRead16 (IohEhciPciReg[i] | R_IOH_USB_COMMAND);
+ CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_MSE | B_IOH_USB_COMMAND_BME );
+ PciWrite16 (IohEhciPciReg[i] | R_IOH_USB_COMMAND, CmdReg);
+ }
+ //
+ // Install USB Controller PPI
+ //
+ Status = (**PeiServices).InstallPpi (
+ PeiServices,
+ &PeiIohEhciDev->PpiList
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ DEBUG ((EFI_D_INFO, "UsbPei:OHCI is used for recovery\n"));
+ //
+ // OHCI recovery is enabled
+ //
+ SwitchConfigFlag ((EFI_PEI_SERVICES**)PeiServices);
+ PeiIohOhciDev = (IOH_OHCI_DEVICE *)((UINTN)AllocateAddress);
+ ZeroMem (PeiIohOhciDev, sizeof(IOH_OHCI_DEVICE));
+
+ PeiIohOhciDev->Signature = PEI_IOH_OHCI_SIGNATURE;
+ CopyMem(&(PeiIohOhciDev->UsbControllerPpi), &mUsbControllerPpi[0], sizeof(PEI_USB_CONTROLLER_PPI));
+ CopyMem(&(PeiIohOhciDev->PpiList), &mPpiList, sizeof(mPpiList));
+ PeiIohOhciDev->PpiList.Ppi = &PeiIohOhciDev->UsbControllerPpi;
+ //
+ // Assign resources and enable OHCI controllers
+ //
+ for (i = 0; i < IOH_MAX_OHCI_USB_CONTROLLERS; i++) {
+ DEBUG ((EFI_D_INFO, "UsbPei:Enable the %dth OHCI controller for recovery\n", i));
+ PeiIohOhciDev->MmioBase[i] = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress) + IOH_USB_CONTROLLER_MMIO_RANGE * i;
+ //
+ // Assign base address register, Enable Bus Master and Memory Io
+ //
+ PciWrite32 (IohOhciPciReg[i] | R_IOH_USB_MEMBAR, PeiIohOhciDev->MmioBase[i]);
+
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ 1,
+ &AllocateAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+ MmioWrite32(PeiIohOhciDev->MmioBase[i] + R_IOH_USB_OHCI_HCCABAR, (UINT32)AllocateAddress);
+
+ CmdReg = PciRead16 (IohOhciPciReg[i] | R_IOH_USB_COMMAND);
+ CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_MSE | B_IOH_USB_COMMAND_BME );
+ PciWrite16 (IohOhciPciReg[i] | R_IOH_USB_COMMAND, CmdReg);
+ }
+ //
+ // Install USB Controller PPI
+ //
+ Status = (**PeiServices).InstallPpi (
+ PeiServices,
+ &PeiIohOhciDev->PpiList
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.h
new file mode 100644
index 0000000..b67e51a
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.h
@@ -0,0 +1,62 @@
+/** @file
+ Define private data structure for UHCI and EHCI.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _USB_PEI_H
+#define _USB_PEI_H
+
+#include "Ioh.h"
+
+#define PEI_IOH_OHCI_SIGNATURE SIGNATURE_32 ('O', 'H', 'C', 'I')
+#define PEI_IOH_EHCI_SIGNATURE SIGNATURE_32 ('E', 'H', 'C', 'I')
+
+typedef struct {
+ UINTN Signature;
+ PEI_USB_CONTROLLER_PPI UsbControllerPpi;
+ EFI_PEI_PPI_DESCRIPTOR PpiList;
+ UINTN MmioBase[IOH_MAX_OHCI_USB_CONTROLLERS];
+} IOH_OHCI_DEVICE;
+
+typedef struct {
+ UINTN Signature;
+ PEI_USB_CONTROLLER_PPI UsbControllerPpi;
+ EFI_PEI_PPI_DESCRIPTOR PpiList;
+ UINTN MmioBase[IOH_MAX_EHCI_USB_CONTROLLERS];
+} IOH_EHCI_DEVICE;
+
+#define IOH_OHCI_DEVICE_FROM_THIS(a) \
+ CR(a, IOH_OHCI_DEVICE, UsbControllerPpi, PEI_IOH_OHCI_SIGNATURE)
+
+#define IOH_EHCI_DEVICE_FROM_THIS(a) \
+ CR (a, IOH_EHCI_DEVICE, UsbControllerPpi, PEI_IOH_EHCI_SIGNATURE)
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf
new file mode 100644
index 0000000..8267077
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf
@@ -0,0 +1,81 @@
+## @file UsbPei.inf
+# Component description file for UsbPei module.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UsbPei
+ FILE_GUID = 73E6F6B4-D029-4e87-8405-6067C8BD02A6
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PeimInitializeIchUsb
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ UsbPei.c
+ UsbPei.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+
+[LibraryClasses]
+ IoLib
+ PciLib
+ PcdLib
+ BaseMemoryLib
+ PeimEntryPoint
+ DebugLib
+
+
+[Ppis]
+ gPeiUsbControllerPpiGuid # PPI ALWAYS_PRODUCED
+
+[FeaturePcd]
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdEhciRecoveryEnabled
+
+[FixedPcd]
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiQNCUsbControllerMemoryBaseAddress
+ gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiP2PMemoryBaseAddress
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.c
new file mode 100644
index 0000000..e985c9d
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.c
@@ -0,0 +1,243 @@
+/** @file
+ UEFI Component Name and Name2 protocol for OHCI driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "Ohci.h"
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gOhciComponentName = {
+ OhciComponentNameGetDriverName,
+ OhciComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) OhciComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) OhciComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mOhciDriverNameTable[] = {
+ { "eng;en", L"Usb Ohci Driver" },
+ { NULL, NULL }
+};
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mOhciDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gOhciComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ USB_OHCI_HC_DEV *OhciDev;
+ EFI_USB_HC_PROTOCOL *UsbHc;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Make sure this driver is currently managing ControllerHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gOhciDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **) &UsbHc,
+ gOhciDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OhciDev = USB_OHCI_HC_DEV_FROM_THIS (UsbHc);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ OhciDev->ControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gOhciComponentName)
+ );
+
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.h
new file mode 100644
index 0000000..d62c6ed
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.h
@@ -0,0 +1,165 @@
+/** @file
+ This file contains the delarations for componet name routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _COMPONENT_NAME_H_
+#define _COMPONENT_NAME_H_
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Descriptor.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Descriptor.h
new file mode 100644
index 0000000..509bb40
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Descriptor.h
@@ -0,0 +1,156 @@
+/** @file
+ This file contains the descriptor definination of OHCI spec
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#ifndef _DESCRIPTOR_H
+#define _DESCRIPTOR_H
+
+#define ED_FUNC_ADD 0x0001
+#define ED_ENDPT_NUM 0x0002
+#define ED_DIR 0x0004
+#define ED_SPEED 0x0008
+#define ED_SKIP 0x0010
+#define ED_FORMAT 0x0020
+#define ED_MAX_PACKET 0x0040
+#define ED_TDTAIL_PTR 0x0080
+#define ED_HALTED 0x0100
+#define ED_DTTOGGLE 0x0200
+#define ED_TDHEAD_PTR 0x0400
+#define ED_NEXT_EDPTR 0x0800
+#define ED_PDATA 0x1000
+#define ED_ZERO 0x2000
+
+#define TD_BUFFER_ROUND 0x0001
+#define TD_DIR_PID 0x0002
+#define TD_DELAY_INT 0x0004
+#define TD_DT_TOGGLE 0x0008
+#define TD_ERROR_CNT 0x0010
+#define TD_COND_CODE 0x0020
+#define TD_CURR_BUFFER_PTR 0x0040
+#define TD_NEXT_PTR 0x0080
+#define TD_BUFFER_END_PTR 0x0100
+#define TD_PDATA 0x0200
+
+#define ED_FROM_TD_DIR 0x0
+#define ED_OUT_DIR 0x1
+#define ED_IN_DIR 0x2
+#define ED_FROM_TD_ALSO_DIR 0x3
+
+#define TD_SETUP_PID 0x00
+#define TD_OUT_PID 0x01
+#define TD_IN_PID 0x02
+#define TD_NODATA_PID 0x03
+
+#define HI_SPEED 0
+#define LO_SPEED 1
+
+#define TD_NO_ERROR 0x00
+#define TD_CRC_ERROR 0x01
+#define TD_BITSTUFFING_ERROR 0x02
+#define TD_TOGGLE_ERROR 0x03
+#define TD_DEVICE_STALL 0x04
+#define TD_NO_RESPONSE 0x05
+#define TD_PIDCHK_FAIL 0x06
+#define TD_PID_UNEXPECTED 0x07
+#define TD_DATA_OVERRUN 0x08
+#define TD_DATA_UNDERRUN 0x09
+#define TD_BUFFER_OVERRUN 0x0C
+#define TD_BUFFER_UNDERRUN 0x0D
+#define TD_TOBE_PROCESSED 0x0E
+#define TD_TOBE_PROCESSED_2 0x0F
+
+#define TD_NO_DELAY 0x7
+
+#define TD_INT 0x1
+#define TD_CTL 0x2
+#define TD_BLK 0x3
+
+typedef struct {
+ UINT32 Reserved:18;
+ UINT32 BufferRounding:1;
+ UINT32 DirPID:2;
+ UINT32 DelayInterrupt:3;
+ UINT32 DataToggle:2;
+ UINT32 ErrorCount:2;
+ UINT32 ConditionCode:4;
+} TD_DESCRIPTOR_WORD0;
+
+typedef struct _TD_DESCRIPTOR {
+ TD_DESCRIPTOR_WORD0 Word0;
+ UINT32 CurrBufferPointer;
+ UINT32 NextTD;
+ UINT32 BufferEndPointer;
+ UINT32 NextTDPointer;
+ UINT32 DataBuffer;
+ UINT32 ActualSendLength;
+ UINT32 Reserved;
+} TD_DESCRIPTOR;
+
+typedef struct {
+ UINT32 FunctionAddress:7;
+ UINT32 EndPointNum:4;
+ UINT32 Direction:2;
+ UINT32 Speed:1;
+ UINT32 Skip:1;
+ UINT32 Format:1;
+ UINT32 MaxPacketSize:11;
+ UINT32 FreeSpace:5;
+} ED_DESCRIPTOR_WORD0;
+
+typedef struct {
+ UINT32 Halted:1;
+ UINT32 ToggleCarry:1;
+ UINT32 Zero:2;
+ UINT32 TdHeadPointer:28;
+} ED_DESCRIPTOR_WORD2;
+
+typedef struct _ED_DESCRIPTOR {
+ ED_DESCRIPTOR_WORD0 Word0;
+ UINT32 TdTailPointer;
+ ED_DESCRIPTOR_WORD2 Word2;
+ UINT32 NextED;
+} ED_DESCRIPTOR;
+
+#define TD_PTR(p) ((TD_DESCRIPTOR *)(UINTN)((p) << 4))
+#define ED_PTR(p) ((ED_DESCRIPTOR *)(UINTN)((p) << 4))
+#define RIGHT_SHIFT_4(p) ((UINT32)(p) >> 4)
+
+typedef enum {
+ CONTROL_LIST,
+ BULK_LIST,
+ INTERRUPT_LIST,
+ ISOCHRONOUS_LIST
+} DESCRIPTOR_LIST_TYPE;
+
+#endif \ No newline at end of file
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.c
new file mode 100644
index 0000000..d78eff0
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.c
@@ -0,0 +1,2515 @@
+/** @file
+ This file contains the implementation of Usb Hc Protocol.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "Ohci.h"
+
+/**
+ Provides software reset for the USB host controller.
+
+ @param This This EFI_USB_HC_PROTOCOL instance.
+ @param Attributes A bit mask of the reset operation to perform.
+
+ @retval EFI_SUCCESS The reset operation succeeded.
+ @retval EFI_INVALID_PARAMETER Attributes is not valid.
+ @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
+ not currently supported by the host controller.
+ @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciReset (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+ )
+{
+ EFI_STATUS Status;
+ USB_OHCI_HC_DEV *Ohc;
+ UINT8 Index;
+ UINT8 NumOfPorts;
+ UINT32 PowerOnGoodTime;
+ UINT32 Data32;
+ BOOLEAN Flag = FALSE;
+
+ if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+
+ if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {
+ gBS->Stall (50 * 1000);
+ Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ gBS->Stall (50 * 1000);
+ //
+ // Wait for host controller reset.
+ //
+ PowerOnGoodTime = 50;
+ do {
+ gBS->Stall (1 * 1000);
+ Data32 = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ if ((Data32 & HC_RESET) == 0) {
+ Flag = TRUE;
+ break;
+ }
+ }while(PowerOnGoodTime--);
+ if (!Flag){
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ OhciFreeIntTransferMemory (Ohc);
+ Status = OhciInitializeInterruptList (Ohc);
+ OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
+ if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {
+ Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ gBS->Stall (50 * 1000);
+ }
+ //
+ // Initialize host controller operational registers
+ //
+ OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778);
+ OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
+ OhciSetPeriodicStart (Ohc, 0x2a2f);
+ OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x3);
+ OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0);
+ OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0);
+ OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1);
+ //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);
+ //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);
+
+ OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0);
+ OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff);
+ OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE);
+ OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER);
+ OhciGetRootHubNumOfPorts (This, &NumOfPorts);
+ for (Index = 0; Index < NumOfPorts; Index++) {
+ if (!EFI_ERROR (OhciSetRootHubPortFeature (This, Index, EfiUsbPortReset))) {
+ gBS->Stall (200 * 1000);
+ OhciClearRootHubPortFeature (This, Index, EfiUsbPortReset);
+ gBS->Stall (1000);
+ OhciSetRootHubPortFeature (This, Index, EfiUsbPortEnable);
+ gBS->Stall (1000);
+ }
+ }
+ OhciSetMemoryPointer (Ohc, HC_HCCA, Ohc->HccaMemoryBlock);
+ OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
+ OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
+ OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | BULK_ENABLE, 1); /*ISOCHRONOUS_ENABLE*/
+ OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
+ gBS->Stall (50*1000);
+ //
+ // Wait till first SOF occurs, and then clear it
+ //
+ while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);
+ OhciClearInterruptStatus (Ohc, START_OF_FRAME);
+ gBS->Stall (1000);
+
+ return Status;
+}
+
+/**
+ Retrieve the current state of the USB host controller.
+
+ @param This This EFI_USB_HC_PROTOCOL instance.
+ @param State Variable to return the current host controller
+ state.
+
+ @retval EFI_SUCCESS Host controller state was returned in State.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+ @retval EFI_DEVICE_ERROR An error was encountered while attempting to
+ retrieve the host controller's current state.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciGetState (
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ UINT32 FuncState;
+
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+
+ FuncState = OhciGetHcControl (Ohc, HC_FUNCTIONAL_STATE);
+
+ switch (FuncState) {
+ case HC_STATE_RESET:
+ case HC_STATE_RESUME:
+ *State = EfiUsbHcStateHalt;
+ break;
+
+ case HC_STATE_OPERATIONAL:
+ *State = EfiUsbHcStateOperational;
+ break;
+
+ case HC_STATE_SUSPEND:
+ *State = EfiUsbHcStateSuspend;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets the USB host controller to a specific state.
+
+ @param This This EFI_USB_HC_PROTOCOL instance.
+ @param State The state of the host controller that will be set.
+
+ @retval EFI_SUCCESS The USB host controller was successfully placed
+ in the state specified by State.
+ @retval EFI_INVALID_PARAMETER State is invalid.
+ @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciSetState(
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+ )
+{
+ EFI_STATUS Status;
+ USB_OHCI_HC_DEV *Ohc;
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);
+
+ switch (State) {
+ case EfiUsbHcStateHalt:
+ Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
+ break;
+
+ case EfiUsbHcStateOperational:
+ Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
+ break;
+
+ case EfiUsbHcStateSuspend:
+ Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_SUSPEND);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ gBS->Stall (1000);
+
+ return Status;
+}
+
+/**
+
+ Submits control transfer to a target USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+ @param MaxPaketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ @param Request A pointer to the USB device request that will be sent
+ to the USB device.
+ @param TransferDirection Specifies the data direction for the transfer.
+ There are three values available, DataIn, DataOut
+ and NoData.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param DataLength Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ @param TimeOut Indicates the maximum time, in microseconds,
+ which the transfer is allowed to complete.
+ @param TransferResult A pointer to the detailed result information generated
+ by this control transfer.
+
+ @retval EFI_SUCCESS The control transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT The control transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+
+
+EFI_STATUS
+EFIAPI
+OhciControlTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ ED_DESCRIPTOR *HeadEd;
+ ED_DESCRIPTOR *Ed;
+ TD_DESCRIPTOR *HeadTd;
+ TD_DESCRIPTOR *SetupTd;
+ TD_DESCRIPTOR *DataTd;
+ TD_DESCRIPTOR *StatusTd;
+ TD_DESCRIPTOR *EmptyTd;
+ EFI_STATUS Status;
+ UINT32 DataPidDir;
+ UINT32 StatusPidDir;
+ UINTN TimeCount;
+ OHCI_ED_RESULT EdResult;
+
+ EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
+
+ UINTN ActualSendLength;
+ UINTN LeftLength;
+ UINT8 DataToggle;
+
+ VOID *ReqMapping = NULL;
+ UINTN ReqMapLength = 0;
+ EFI_PHYSICAL_ADDRESS ReqMapPhyAddr = 0;
+
+ VOID *DataMapping = NULL;
+ UINTN DataMapLength = 0;
+ EFI_PHYSICAL_ADDRESS DataMapPhyAddr = 0;
+
+ HeadTd = NULL;
+ DataTd = NULL;
+
+ if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&
+ TransferDirection != EfiUsbNoData) ||
+ Request == NULL || DataLength == NULL || TransferResult == NULL ||
+ (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||
+ (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||
+ (IsSlowDevice && MaxPacketLength != 8) ||
+ (MaxPacketLength != 8 && MaxPacketLength != 16 &&
+ MaxPacketLength != 32 && MaxPacketLength != 64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*DataLength > MAX_BYTES_PER_TD) {
+ DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\r\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);
+
+ if (TransferDirection == EfiUsbDataIn) {
+ DataPidDir = TD_IN_PID;
+ StatusPidDir = TD_OUT_PID;
+ } else {
+ DataPidDir = TD_OUT_PID;
+ StatusPidDir = TD_IN_PID;
+ }
+
+ Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_ENABLE\r\n"));
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+ Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 0);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_LIST_FILLED\r\n"));
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+ gBS->Stall(20 * 1000);
+
+ OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
+ Ed = OhciCreateED (Ohc);
+ if (Ed == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\r\n"));
+ goto CTRL_EXIT;
+ }
+ OhciSetEDField (Ed, ED_SKIP, 1);
+ OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
+ OhciSetEDField (Ed, ED_ENDPT_NUM, 0);
+ OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
+ OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
+ OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
+ OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
+ OhciSetEDField (Ed, ED_PDATA, 0);
+ OhciSetEDField (Ed, ED_ZERO, 0);
+ OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
+ OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
+ OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
+ HeadEd = OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);
+ //
+ // Setup Stage
+ //
+ if(Request != NULL) {
+ ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);
+ MapOp = EfiPciOperationBusMasterRead;
+ Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Request, &ReqMapLength, &ReqMapPhyAddr, &ReqMapping);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to Map Request Buffer\r\n"));
+ goto FREE_ED_BUFF;
+ }
+ }
+ SetupTd = OhciCreateTD (Ohc);
+ if (SetupTd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\r\n"));
+ goto UNMAP_SETUP_BUFF;
+ }
+ HeadTd = SetupTd;
+ OhciSetTDField (SetupTd, TD_PDATA, 0);
+ OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);
+ OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);
+ OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);
+ OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINT32)ReqMapPhyAddr);
+ OhciSetTDField (SetupTd, TD_NEXT_PTR, 0);
+ OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINT32)(ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1));
+ SetupTd->ActualSendLength = sizeof (EFI_USB_DEVICE_REQUEST);
+ SetupTd->DataBuffer = (UINT32)(UINTN)ReqMapPhyAddr;
+ SetupTd->NextTDPointer = 0;
+
+ if (TransferDirection == EfiUsbDataIn) {
+ MapOp = EfiPciIoOperationBusMasterWrite;
+ } else {
+ MapOp = EfiPciIoOperationBusMasterRead;
+ }
+ DataMapLength = *DataLength;
+ if ((Data != NULL) && (DataMapLength != 0)) {
+ Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, Data, &DataMapLength, &DataMapPhyAddr, &DataMapping);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail To Map Data Buffer\r\n"));
+ goto FREE_TD_BUFF;
+ }
+ }
+ //
+ //Data Stage
+ //
+ LeftLength = DataMapLength;
+ ActualSendLength = DataMapLength;
+ DataToggle = 1;
+ while (LeftLength > 0) {
+ ActualSendLength = LeftLength;
+ if (LeftLength > MaxPacketLength) {
+ ActualSendLength = MaxPacketLength;
+ }
+ DataTd = OhciCreateTD (Ohc);
+ if (DataTd == NULL) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UNMAP_DATA_BUFF;
+ }
+ OhciSetTDField (DataTd, TD_PDATA, 0);
+ OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
+ OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
+ OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);
+ OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);
+ OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(DataMapPhyAddr + ActualSendLength - 1));
+ OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
+ DataTd->ActualSendLength = (UINT32)ActualSendLength;
+ DataTd->DataBuffer = (UINT32)(UINTN)DataMapPhyAddr;
+ DataTd->NextTDPointer = 0;
+ OhciLinkTD (HeadTd, DataTd);
+ DataToggle ^= 1;
+ DataMapPhyAddr += ActualSendLength;
+ LeftLength -= ActualSendLength;
+ }
+ //
+ // Status Stage
+ //
+ StatusTd = OhciCreateTD (Ohc);
+ if (StatusTd == NULL) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Status Stage TD\r\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UNMAP_DATA_BUFF;
+ }
+ OhciSetTDField (StatusTd, TD_PDATA, 0);
+ OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);
+ OhciSetTDField (StatusTd, TD_DELAY_INT, 7);
+ OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);
+ OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, 0);
+ OhciSetTDField (StatusTd, TD_NEXT_PTR, 0);
+ OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, 0);
+ StatusTd->ActualSendLength = 0;
+ StatusTd->DataBuffer = 0;
+ StatusTd->NextTDPointer = 0;
+ OhciLinkTD (HeadTd, StatusTd);
+ //
+ // Empty Stage
+ //
+ EmptyTd = OhciCreateTD (Ohc);
+ if (EmptyTd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UNMAP_DATA_BUFF;
+ }
+ OhciSetTDField (EmptyTd, TD_PDATA, 0);
+ OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
+ OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
+ OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
+ //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
+ EmptyTd->Word0.DataToggle = 0;
+ OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
+ OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
+ OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
+ OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
+ EmptyTd->ActualSendLength = 0;
+ EmptyTd->DataBuffer = 0;
+ EmptyTd->NextTDPointer = 0;
+ OhciLinkTD (HeadTd, EmptyTd);
+ Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
+ OhciAttachTDListToED (Ed, HeadTd);
+ //
+ // For debugging, dump ED & TD buffer befor transferring
+ //
+ //
+ //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, TRUE);
+ //
+ OhciSetEDField (Ed, ED_SKIP, 0);
+ Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_ENABLE\r\n"));
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto UNMAP_DATA_BUFF;
+ }
+ Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_LIST_FILLED\r\n"));
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ goto UNMAP_DATA_BUFF;
+ }
+ gBS->Stall(20 * 1000);
+
+
+ TimeCount = 0;
+ Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);
+
+ while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
+ gBS->Stall (1000);
+ TimeCount++;
+ Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);
+ }
+ //
+ // For debugging, dump ED & TD buffer after transferring
+ //
+ //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, FALSE);
+ //
+ *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
+
+ if (EdResult.ErrorCode != TD_NO_ERROR) {
+ if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
+ DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));
+ } else {
+ DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
+ }
+ *DataLength = 0;
+ } else {
+ DEBUG ((EFI_D_INFO, "Control transfer successed\r\n"));
+ }
+
+UNMAP_DATA_BUFF:
+ OhciSetEDField (Ed, ED_SKIP, 1);
+ if (HeadEd == Ed) {
+ OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
+ } else {
+ HeadEd->NextED = Ed->NextED;
+ }
+ if(DataMapping != NULL) {
+ Ohc->PciIo->Unmap(Ohc->PciIo, DataMapping);
+ }
+
+FREE_TD_BUFF:
+ while (HeadTd) {
+ DataTd = HeadTd;
+ HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
+ UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
+ }
+
+UNMAP_SETUP_BUFF:
+ if(ReqMapping != NULL) {
+ Ohc->PciIo->Unmap(Ohc->PciIo, ReqMapping);
+ }
+
+FREE_ED_BUFF:
+ UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
+
+CTRL_EXIT:
+ return Status;
+}
+
+/**
+
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress The combination of an endpoint number and an
+ endpoint direction of the target USB device.
+ Each endpoint address supports data transfer in
+ one direction except the control endpoint
+ (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents a bulk endpoint.
+ @param MaximumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param DataLength When input, indicates the size, in bytes, of the data buffer
+ specified by Data. When output, indicates the actually
+ transferred data size.
+ @param DataToggle A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the bulk transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent bulk transfer.
+ @param TimeOut Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ TransferResult A pointer to the detailed result information of the
+ bulk transfer.
+
+ @retval EFI_SUCCESS The bulk transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted due to lack of resource.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT The bulk transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciBulkTransfer(
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaxPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ ED_DESCRIPTOR *HeadEd;
+ ED_DESCRIPTOR *Ed;
+ UINT8 EdDir;
+ UINT32 DataPidDir;
+ TD_DESCRIPTOR *HeadTd;
+ TD_DESCRIPTOR *DataTd;
+ TD_DESCRIPTOR *EmptyTd;
+ EFI_STATUS Status;
+ EFI_USB_DATA_DIRECTION TransferDirection;
+ UINT8 EndPointNum;
+ UINTN TimeCount;
+ OHCI_ED_RESULT EdResult;
+
+ EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
+ VOID *Mapping;
+ UINTN MapLength;
+ EFI_PHYSICAL_ADDRESS MapPyhAddr;
+ UINTN LeftLength;
+ UINTN ActualSendLength;
+ BOOLEAN FirstTD;
+
+ Mapping = NULL;
+ MapLength = 0;
+ MapPyhAddr = 0;
+ LeftLength = 0;
+ Status = EFI_SUCCESS;
+
+ if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||
+ *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||
+ (MaxPacketLength != 8 && MaxPacketLength != 16 &&
+ MaxPacketLength != 32 && MaxPacketLength != 64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+
+ if ((EndPointAddress & 0x80) != 0) {
+ TransferDirection = EfiUsbDataIn;
+ EdDir = ED_IN_DIR;
+ DataPidDir = TD_IN_PID;
+ MapOp = EfiPciIoOperationBusMasterWrite;
+ } else {
+ TransferDirection = EfiUsbDataOut;
+ EdDir = ED_OUT_DIR;
+ DataPidDir = TD_OUT_PID;
+ MapOp = EfiPciIoOperationBusMasterRead;
+ }
+
+ EndPointNum = (EndPointAddress & 0xF);
+ EdResult.NextToggle = *DataToggle;
+
+ Status = OhciSetHcControl (Ohc, BULK_ENABLE, 0);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+ Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 0);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+ gBS->Stall(20 * 1000);
+
+ OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
+
+ Ed = OhciCreateED (Ohc);
+ if (Ed == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ OhciSetEDField (Ed, ED_SKIP, 1);
+ OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
+ OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
+ OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
+ OhciSetEDField (Ed, ED_SPEED, HI_SPEED);
+ OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
+ OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
+ OhciSetEDField (Ed, ED_PDATA, 0);
+ OhciSetEDField (Ed, ED_ZERO, 0);
+ OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
+ OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
+ OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
+ HeadEd = OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);
+
+ if(Data != NULL) {
+ MapLength = *DataLength;
+ Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Data, &MapLength, &MapPyhAddr, &Mapping);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));
+ goto FREE_ED_BUFF;
+ }
+ }
+ //
+ //Data Stage
+ //
+ LeftLength = MapLength;
+ ActualSendLength = MapLength;
+ HeadTd = NULL;
+ FirstTD = TRUE;
+ while (LeftLength > 0) {
+ ActualSendLength = LeftLength;
+ if (LeftLength > MaxPacketLength) {
+ ActualSendLength = MaxPacketLength;
+ }
+ DataTd = OhciCreateTD (Ohc);
+ if (DataTd == NULL) {
+ DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_OHCI_TDBUFF;
+ }
+ OhciSetTDField (DataTd, TD_PDATA, 0);
+ OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
+ OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
+ OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
+ OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
+ OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
+ OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
+ DataTd->ActualSendLength = (UINT32)ActualSendLength;
+ DataTd->DataBuffer = (UINT32)(UINTN)MapPyhAddr;
+ DataTd->NextTDPointer = 0;
+ if (FirstTD) {
+ HeadTd = DataTd;
+ FirstTD = FALSE;
+ } else {
+ OhciLinkTD (HeadTd, DataTd);
+ }
+ *DataToggle ^= 1;
+ MapPyhAddr += ActualSendLength;
+ LeftLength -= ActualSendLength;
+ }
+ //
+ // Empty Stage
+ //
+ EmptyTd = OhciCreateTD (Ohc);
+ if (EmptyTd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));
+ goto FREE_OHCI_TDBUFF;
+ }
+ OhciSetTDField (EmptyTd, TD_PDATA, 0);
+ OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
+ OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
+ OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
+ //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
+ EmptyTd->Word0.DataToggle = 0;
+ OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
+ OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
+ OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
+ OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
+ EmptyTd->ActualSendLength = 0;
+ EmptyTd->DataBuffer = 0;
+ EmptyTd->NextTDPointer = 0;
+ OhciLinkTD (HeadTd, EmptyTd);
+ Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
+ OhciAttachTDListToED (Ed, HeadTd);
+
+ OhciSetEDField (Ed, ED_SKIP, 0);
+ Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);
+ if (EFI_ERROR(Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));
+ goto FREE_OHCI_TDBUFF;
+ }
+ Status = OhciSetHcControl (Ohc, BULK_ENABLE, 1);
+ if (EFI_ERROR(Status)) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));
+ goto FREE_OHCI_TDBUFF;
+ }
+ gBS->Stall(20 * 1000);
+
+ TimeCount = 0;
+ Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
+ while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
+ gBS->Stall (1000);
+ TimeCount++;
+ Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
+ }
+
+ *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
+
+ if (EdResult.ErrorCode != TD_NO_ERROR) {
+ if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
+ DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));
+ } else {
+ DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
+ *DataToggle = EdResult.NextToggle;
+ }
+ *DataLength = 0;
+ } else {
+ DEBUG ((EFI_D_INFO, "Bulk transfer successed\r\n"));
+ }
+ //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
+
+FREE_OHCI_TDBUFF:
+ OhciSetEDField (Ed, ED_SKIP, 1);
+ if (HeadEd == Ed) {
+ OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
+ }else {
+ HeadEd->NextED = Ed->NextED;
+ }
+ while (HeadTd) {
+ DataTd = HeadTd;
+ HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
+ UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
+ }
+
+ if(Mapping != NULL) {
+ Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
+ }
+
+FREE_ED_BUFF:
+ UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
+
+ return Status;
+}
+/**
+
+ Submits an interrupt transfer to an interrupt endpoint of a USB device.
+
+ @param Ohc Device private data
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+ @param IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+ @param MaxPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+ @param DataToggle A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+ @param PollingInterval Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+ @param UCBuffer Uncacheable buffer
+ @param DataLength Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+ @param CallBackFunction The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+ @param Context The context that is passed to the CallBackFunction.
+ This is an optional parameter and may be NULL.
+ @param IsPeriodic Periodic interrupt or not
+ @param OutputED The correspoding ED carried out
+ @param OutputTD The correspoding TD carried out
+
+
+ @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+
+EFI_STATUS
+OhciInterruptTransfer (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle OPTIONAL,
+ IN UINTN PollingInterval OPTIONAL,
+ IN VOID *UCBuffer OPTIONAL,
+ IN UINTN DataLength OPTIONAL,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,
+ IN VOID *Context OPTIONAL,
+ IN BOOLEAN IsPeriodic OPTIONAL,
+ OUT ED_DESCRIPTOR **OutputED OPTIONAL,
+ OUT TD_DESCRIPTOR **OutputTD OPTIONAL
+ )
+{
+ ED_DESCRIPTOR *Ed;
+ UINT8 EdDir;
+ ED_DESCRIPTOR *HeadEd;
+ TD_DESCRIPTOR *HeadTd;
+ TD_DESCRIPTOR *DataTd;
+ TD_DESCRIPTOR *EmptTd;
+ UINTN Depth;
+ UINTN Index;
+ EFI_STATUS Status;
+ UINT8 EndPointNum;
+ UINT32 DataPidDir;
+ EFI_USB_DATA_DIRECTION TransferDirection;
+ INTERRUPT_CONTEXT_ENTRY *Entry;
+ EFI_TPL OldTpl;
+ BOOLEAN FirstTD;
+
+ VOID *Mapping;
+ UINTN MapLength;
+ EFI_PHYSICAL_ADDRESS MapPyhAddr;
+ UINTN LeftLength;
+ UINTN ActualSendLength;
+
+
+ if (DataLength > MAX_BYTES_PER_TD) {
+ DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Error param\r\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EndPointAddress & 0x80) != 0) {
+ TransferDirection = EfiUsbDataIn;
+ EdDir = ED_IN_DIR;
+ DataPidDir = TD_IN_PID;
+ } else {
+ TransferDirection = EfiUsbDataOut;
+ EdDir = ED_OUT_DIR;
+ DataPidDir = TD_OUT_PID;
+ }
+
+ EndPointNum = (EndPointAddress & 0xF);
+
+ if (!IsNewTransfer) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ OhciSetHcControl (Ohc, PERIODIC_ENABLE, 0);
+ OhciFreeInterruptContext (Ohc, DeviceAddress, EndPointAddress, DataToggle);
+ Status = OhciFreeInterruptEdByAddr (Ohc, DeviceAddress, EndPointNum);
+ OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+ MapLength = DataLength;
+ Status = Ohc->PciIo->Map(
+ Ohc->PciIo,
+ EfiPciOperationBusMasterWrite,
+ UCBuffer,
+ &MapLength,
+ &MapPyhAddr,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));
+ goto EXIT;
+ }
+ Depth = 5;
+ Index = 1;
+ while (PollingInterval >= Index * 2 && Depth > 0) {
+ Index *= 2;
+ Depth--;
+ }
+ //
+ //ED Stage
+ //
+ HeadEd = OhciFindMinInterruptEDList (Ohc, (UINT32)Depth);
+ if ((Ed = OhciFindWorkingEd (HeadEd, DeviceAddress, EndPointNum, EdDir)) != NULL) {
+ OhciSetEDField (Ed, ED_SKIP, 1);
+ } else {
+ Ed = OhciCreateED (Ohc);
+ if (Ed == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));
+ goto UNMAP_OHCI_XBUFF;
+ }
+ OhciSetEDField (Ed, ED_SKIP, 1);
+ OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
+ OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
+ OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
+ OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
+ OhciSetEDField (Ed, ED_FORMAT, 0);
+ OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
+ OhciSetEDField (Ed, ED_PDATA | ED_ZERO | ED_HALTED | ED_DTTOGGLE, 0);
+ OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
+ OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
+ OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
+ OhciAttachEDToList (Ohc, INTERRUPT_LIST, Ed, HeadEd);
+ }
+ //
+ //Data Stage
+ //
+ LeftLength = MapLength;
+ ActualSendLength = MapLength;
+ HeadTd = NULL;
+ FirstTD = TRUE;
+ while (LeftLength > 0) {
+ ActualSendLength = LeftLength;
+ if (LeftLength > MaxPacketLength) {
+ ActualSendLength = MaxPacketLength;
+ }
+ DataTd = OhciCreateTD (Ohc);
+ if (DataTd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
+ goto FREE_OHCI_TDBUFF;
+ }
+ OhciSetTDField (DataTd, TD_PDATA, 0);
+ OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
+ OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
+ OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
+ OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
+ OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
+ OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
+ DataTd->ActualSendLength = (UINT32)ActualSendLength;
+ DataTd->DataBuffer = (UINT32)(UINTN)MapPyhAddr;
+ DataTd->NextTDPointer = 0;
+ if (FirstTD) {
+ HeadTd = DataTd;
+ FirstTD = FALSE;
+ } else {
+ OhciLinkTD (HeadTd, DataTd);
+ }
+ *DataToggle ^= 1;
+ MapPyhAddr += ActualSendLength;
+ LeftLength -= ActualSendLength;
+ }
+
+ EmptTd = OhciCreateTD (Ohc);
+ if (EmptTd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));
+ goto FREE_OHCI_TDBUFF;
+ }
+ OhciSetTDField (EmptTd, TD_PDATA, 0);
+ OhciSetTDField (EmptTd, TD_BUFFER_ROUND, 0);
+ OhciSetTDField (EmptTd, TD_DIR_PID, 0);
+ OhciSetTDField (EmptTd, TD_DELAY_INT, 0);
+ //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);
+ EmptTd->Word0.DataToggle = 0;
+ OhciSetTDField (EmptTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (EmptTd, TD_COND_CODE, 0);
+ OhciSetTDField (EmptTd, TD_CURR_BUFFER_PTR, 0);
+ OhciSetTDField (EmptTd, TD_BUFFER_END_PTR, 0);
+ OhciSetTDField (EmptTd, TD_NEXT_PTR, 0);
+ EmptTd->ActualSendLength = 0;
+ EmptTd->DataBuffer = 0;
+ EmptTd->NextTDPointer = 0;
+ OhciLinkTD (HeadTd, EmptTd);
+ Ed->TdTailPointer = (UINT32)(UINTN)EmptTd;
+ OhciAttachTDListToED (Ed, HeadTd);
+
+ if (OutputED != NULL) {
+ *OutputED = Ed;
+ }
+ if (OutputTD != NULL) {
+ *OutputTD = HeadTd;
+ }
+
+ if (CallBackFunction != NULL) {
+ Entry = AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY));
+ if (Entry == NULL) {
+ goto FREE_OHCI_TDBUFF;
+ }
+
+ Entry->DeviceAddress = DeviceAddress;
+ Entry->EndPointAddress = EndPointAddress;
+ Entry->Ed = Ed;
+ Entry->DataTd = HeadTd;
+ Entry->IsSlowDevice = IsSlowDevice;
+ Entry->MaxPacketLength = MaxPacketLength;
+ Entry->PollingInterval = PollingInterval;
+ Entry->CallBackFunction = CallBackFunction;
+ Entry->Context = Context;
+ Entry->IsPeriodic = IsPeriodic;
+ Entry->UCBuffer = UCBuffer;
+ Entry->UCBufferMapping = Mapping;
+ Entry->DataLength = DataLength;
+ Entry->Toggle = DataToggle;
+ Entry->NextEntry = NULL;
+ OhciAddInterruptContextEntry (Ohc, Entry);
+ }
+ OhciSetEDField (Ed, ED_SKIP, 0);
+
+ if (OhciGetHcControl (Ohc, PERIODIC_ENABLE) == 0) {
+ Status = OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
+ gBS->Stall (1000);
+ }
+
+ return EFI_SUCCESS;
+
+FREE_OHCI_TDBUFF:
+ while (HeadTd) {
+ DataTd = HeadTd;
+ HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
+ UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
+ }
+
+//FREE_OHCI_EDBUFF:
+ if ((HeadEd != Ed) && HeadEd && Ed) {
+ while(HeadEd->NextED != (UINT32)(UINTN)Ed) {
+ HeadEd = (ED_DESCRIPTOR *)(UINTN)(HeadEd->NextED);
+ }
+ HeadEd->NextED = Ed->NextED;
+ UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
+ }
+
+UNMAP_OHCI_XBUFF:
+ Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
+
+EXIT:
+ return Status;
+}
+
+/**
+
+ Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+ @param IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+ @param MaxiumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+ @param DataToggle A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+ @param PollingInterval Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+ @param DataLength Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+ @param CallBackFunction The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+ @param Context The context that is passed to the CallBackFunction.
+ This is an optional parameter and may be NULL.
+
+ @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciAsyncInterruptTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle OPTIONAL,
+ IN UINTN PollingInterval OPTIONAL,
+ IN UINTN DataLength OPTIONAL,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,
+ IN VOID *Context OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ USB_OHCI_HC_DEV *Ohc;
+ VOID *UCBuffer;
+
+ if (DataToggle == NULL || (EndPointAddress & 0x80) == 0 ||
+ (IsNewTransfer && (DataLength == 0 ||
+ (*DataToggle != 0 && *DataToggle != 1) || (PollingInterval < 1 || PollingInterval > 255)))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+ if ( IsNewTransfer ) {
+ UCBuffer = AllocatePool(DataLength);
+ if (UCBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ UCBuffer = NULL;
+ }
+ Status = OhciInterruptTransfer (
+ Ohc,
+ DeviceAddress,
+ EndPointAddress,
+ IsSlowDevice,
+ MaxPacketLength,
+ IsNewTransfer,
+ DataToggle,
+ PollingInterval,
+ UCBuffer,
+ DataLength,
+ CallBackFunction,
+ Context,
+ TRUE,
+ NULL,
+ NULL
+ );
+ if ( IsNewTransfer ) {
+ if (EFI_ERROR(Status)) {
+ gBS->FreePool (UCBuffer);
+ }
+ }
+ return Status;
+}
+
+
+/**
+
+ Submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint
+ address supports data transfer in one direction
+ except the control endpoint (whose default
+ endpoint address is 0). It is the caller's responsibility
+ to make sure that the EndPointAddress represents
+ an interrupt endpoint.
+ @param IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+ @param MaxPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param DataLength On input, the size, in bytes, of the data buffer specified
+ by Data. On output, the number of bytes transferred.
+ @param DataToggle A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the synchronous interrupt
+ transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent synchronous interrupt transfer.
+ @param TimeOut Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ @param TransferResult A pointer to the detailed result information from
+ the synchronous interrupt transfer.
+
+ @retval EFI_UNSUPPORTED This interface not available.
+ @retval EFI_INVALID_PARAMETER Parameters not follow spec
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciSyncInterruptTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ EFI_STATUS Status;
+ ED_DESCRIPTOR *Ed;
+ TD_DESCRIPTOR *HeadTd;
+ OHCI_ED_RESULT EdResult;
+ VOID *UCBuffer;
+
+ if ((EndPointAddress & 0x80) == 0 || Data == NULL || DataLength == NULL || *DataLength == 0 ||
+ (IsSlowDevice && MaxPacketLength > 8) || (!IsSlowDevice && MaxPacketLength > 64) ||
+ DataToggle == NULL || (*DataToggle != 0 && *DataToggle != 1) || TransferResult == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+ UCBuffer = AllocatePool (*DataLength);
+ if (UCBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = OhciInterruptTransfer (
+ Ohc,
+ DeviceAddress,
+ EndPointAddress,
+ IsSlowDevice,
+ MaxPacketLength,
+ TRUE,
+ DataToggle,
+ 1,
+ UCBuffer,
+ *DataLength,
+ NULL,
+ NULL,
+ FALSE,
+ &Ed,
+ &HeadTd
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
+ while (Status == EFI_NOT_READY && TimeOut > 0) {
+ gBS->Stall (1000);
+ TimeOut--;
+ Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
+ }
+
+ *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
+ }
+ CopyMem(Data, UCBuffer, *DataLength);
+ Status = OhciInterruptTransfer (
+ Ohc,
+ DeviceAddress,
+ EndPointAddress,
+ IsSlowDevice,
+ MaxPacketLength,
+ FALSE,
+ DataToggle,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ FALSE,
+ NULL,
+ NULL
+ );
+
+ return Status;
+}
+/**
+
+ Submits isochronous transfer to a target USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress End point address
+ @param MaximumPacketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param DataLength Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ @param TransferResult A pointer to the detailed result information generated
+ by this control transfer.
+
+ @retval EFI_UNSUPPORTED This interface not available
+ @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciIsochronousTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN DataLength,
+ OUT UINT32 *TransferResult
+ )
+{
+ if (Data == NULL || DataLength == 0 || TransferResult == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+
+ Submits Async isochronous transfer to a target USB device.
+
+ @param his A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress End point address
+ @param MaximumPacketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param IsochronousCallBack When the transfer complete, the call back function will be called
+ @param Context Pass to the call back function as parameter
+
+ @retval EFI_UNSUPPORTED This interface not available
+ @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciAsyncIsochronousTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context OPTIONAL
+ )
+{
+
+ if (Data == NULL || DataLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+
+ Retrieves the number of root hub ports.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param NumOfPorts A pointer to the number of the root hub ports.
+
+ @retval EFI_SUCCESS The port number was retrieved successfully.
+**/
+EFI_STATUS
+EFIAPI
+OhciGetRootHubNumOfPorts (
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT UINT8 *NumOfPorts
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+
+ if (NumOfPorts == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
+
+ return EFI_SUCCESS;
+}
+/**
+
+ Retrieves the current status of a USB root hub port.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL.
+ @param PortNumber Specifies the root hub port from which the status
+ is to be retrieved. This value is zero-based. For example,
+ if a root hub has two ports, then the first port is numbered 0,
+ and the second port is numbered 1.
+ @param PortStatus A pointer to the current port status bits and
+ port status change bits.
+
+ @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber
+ was returned in PortStatus.
+ @retval EFI_INVALID_PARAMETER Port number not valid
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciGetRootHubPortStatus (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ UINT8 NumOfPorts;
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+
+ OhciGetRootHubNumOfPorts (This, &NumOfPorts);
+ if (PortNumber >= NumOfPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_POWER;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+
+ Sets a feature for the specified root hub port.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL.
+ @param PortNumber Specifies the root hub port whose feature
+ is requested to be set.
+ @param PortFeature Indicates the feature selector associated
+ with the feature set request.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was set for the
+ USB root hub port specified by PortNumber.
+ @retval EFI_DEVICE_ERROR Set feature failed because of hardware issue
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+**/
+EFI_STATUS
+EFIAPI
+OhciSetRootHubPortFeature (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ EFI_STATUS Status;
+ UINT8 NumOfPorts;
+ UINTN RetryTimes;
+
+ OhciGetRootHubNumOfPorts (This, &NumOfPorts);
+ if (PortNumber >= NumOfPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+
+ Status = EFI_SUCCESS;
+
+
+ switch (PortFeature) {
+ case EfiUsbPortPower:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortReset:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||
+ OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
+ break;
+
+ case EfiUsbPortEnable:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+
+ case EfiUsbPortSuspend:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/**
+
+ Clears a feature for the specified root hub port.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param PortNumber Specifies the root hub port whose feature
+ is requested to be cleared.
+ @param PortFeature Indicates the feature selector associated with the
+ feature clear request.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the
+ USB root hub port specified by PortNumber.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+ @retval EFI_DEVICE_ERROR Some error happened when clearing feature
+**/
+EFI_STATUS
+EFIAPI
+OhciClearRootHubPortFeature (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ EFI_STATUS Status;
+ UINT8 NumOfPorts;
+ UINTN RetryTimes;
+
+
+ OhciGetRootHubNumOfPorts (This, &NumOfPorts);
+ if (PortNumber >= NumOfPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+
+ Status = EFI_SUCCESS;
+
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortSuspend:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortReset:
+ break;
+
+ case EfiUsbPortPower:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortConnectChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortResetChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+
+ case EfiUsbPortEnableChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortSuspendChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortOverCurrentChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ gBS->Stall (1000);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {
+ OHCIDriverBindingSupported,
+ OHCIDriverBindingStart,
+ OHCIDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+
+/**
+ Entry point for EFI drivers.
+
+ @param ImageHandle EFI_HANDLE.
+ @param SystemTable EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS Driver is successfully loaded.
+ @return Others Failed.
+
+**/
+EFI_STATUS
+EFIAPI
+OHCIDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gOhciDriverBinding,
+ ImageHandle,
+ &gOhciComponentName,
+ &gOhciComponentName2
+ );
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has UsbHcProtocol installed will be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OHCIDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_CLASSC UsbClassCReg;
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &UsbClassCReg
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+ //
+ // Test whether the controller belongs to OHCI type
+ //
+ if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
+ (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
+ (UsbClassCReg.ProgInterface != PCI_IF_OHCI)
+ ) {
+
+ Status = EFI_UNSUPPORTED;
+ }
+ON_EXIT:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+
+}
+
+/**
+
+ Allocate and initialize the empty OHCI device.
+
+ @param PciIo The PCIIO to use.
+ @param OriginalPciAttributes The original PCI attributes.
+
+ @return Allocated OHCI device If err, return NULL.
+
+**/
+
+USB_OHCI_HC_DEV *
+OhciAllocateDev (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT64 OriginalPciAttributes
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ EFI_STATUS Status;
+ VOID *Buf;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ VOID *Map;
+ UINTN Pages;
+ UINTN Bytes;
+
+ Ohc = AllocateZeroPool (sizeof (USB_OHCI_HC_DEV));
+ if (Ohc == NULL) {
+ return NULL;
+ }
+
+ Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE;
+ Ohc->PciIo = PciIo;
+
+ Ohc->UsbHc.Reset = OhciReset;
+ Ohc->UsbHc.GetState = OhciGetState;
+ Ohc->UsbHc.SetState = OhciSetState;
+ Ohc->UsbHc.ControlTransfer = OhciControlTransfer;
+ Ohc->UsbHc.BulkTransfer = OhciBulkTransfer;
+ Ohc->UsbHc.AsyncInterruptTransfer = OhciAsyncInterruptTransfer;
+ Ohc->UsbHc.SyncInterruptTransfer = OhciSyncInterruptTransfer;
+ Ohc->UsbHc.IsochronousTransfer = OhciIsochronousTransfer;
+ Ohc->UsbHc.AsyncIsochronousTransfer = OhciAsyncIsochronousTransfer;
+ Ohc->UsbHc.GetRootHubPortNumber = OhciGetRootHubNumOfPorts;
+ Ohc->UsbHc.GetRootHubPortStatus = OhciGetRootHubPortStatus;
+ Ohc->UsbHc.SetRootHubPortFeature = OhciSetRootHubPortFeature;
+ Ohc->UsbHc.ClearRootHubPortFeature = OhciClearRootHubPortFeature;
+ Ohc->UsbHc.MajorRevision = 0x1;
+ Ohc->UsbHc.MinorRevision = 0x1;
+
+ Ohc->OriginalPciAttributes = OriginalPciAttributes;
+
+ Ohc->HccaMemoryBlock = NULL;
+ Ohc->HccaMemoryMapping = NULL;
+ Ohc->HccaMemoryBuf = NULL;
+ Ohc->HccaMemoryPages = 0;
+ Ohc->InterruptContextList = NULL;
+ Ohc->ControllerNameTable = NULL;
+ Ohc->HouseKeeperTimer = NULL;
+
+ Ohc->MemPool = UsbHcInitMemPool(PciIo, TRUE, 0);
+ if(Ohc->MemPool == NULL) {
+ goto FREE_DEV_BUFFER;
+ }
+
+ Bytes = 4096;
+ Pages = EFI_SIZE_TO_PAGES (Bytes);
+
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ &Buf,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto FREE_MEM_POOL;
+ }
+
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ Buf,
+ &Bytes,
+ &PhyAddr,
+ &Map
+ );
+
+ if (EFI_ERROR (Status) || (Bytes != 4096)) {
+ goto FREE_MEM_PAGE;
+ }
+
+ Ohc->HccaMemoryBlock = (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr;
+ Ohc->HccaMemoryMapping = Map;
+ Ohc->HccaMemoryBuf = (VOID *)(UINTN)Buf;
+ Ohc->HccaMemoryPages = Pages;
+
+ return Ohc;
+
+FREE_MEM_PAGE:
+ PciIo->FreeBuffer (PciIo, Pages, Buf);
+FREE_MEM_POOL:
+ UsbHcFreeMemPool (Ohc->MemPool);
+FREE_DEV_BUFFER:
+ FreePool(Ohc);
+
+ return NULL;
+}
+/**
+
+ Free the OHCI device and release its associated resources.
+
+ @param Ohc The OHCI device to release.
+
+**/
+VOID
+OhciFreeDev (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ OhciFreeFixedIntMemory (Ohc);
+
+ if (Ohc->ExitBootServiceEvent != NULL) {
+ gBS->CloseEvent (Ohc->ExitBootServiceEvent);
+ }
+
+ if (Ohc->HouseKeeperTimer != NULL) {
+ gBS->CloseEvent (Ohc->HouseKeeperTimer);
+ }
+
+ if (Ohc->MemPool != NULL) {
+ UsbHcFreeMemPool (Ohc->MemPool);
+ }
+
+ if (Ohc->HccaMemoryMapping != NULL ) {
+ Ohc->PciIo->FreeBuffer (Ohc->PciIo, Ohc->HccaMemoryPages, Ohc->HccaMemoryBuf);
+ }
+
+ if (Ohc->ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (Ohc->ControllerNameTable);
+ }
+
+ FreePool (Ohc);
+}
+/**
+
+ Uninstall all Ohci Interface.
+
+ @param Controller Controller handle.
+ @param This Protocol instance pointer.
+
+**/
+VOID
+OhciCleanDevUp (
+ IN EFI_HANDLE Controller,
+ IN EFI_USB_HC_PROTOCOL *This
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+
+ //
+ // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
+ //
+ Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
+
+ OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
+ This->Reset (This, EFI_USB_HC_RESET_GLOBAL);
+ This->SetState (This, EfiUsbHcStateHalt);
+
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ &Ohc->UsbHc
+ );
+
+ OhciFreeDynamicIntMemory(Ohc);
+ //
+ // Restore original PCI attributes
+ //
+ Ohc->PciIo->Attributes (
+ Ohc->PciIo,
+ EfiPciIoAttributeOperationSet,
+ Ohc->OriginalPciAttributes,
+ NULL
+ );
+
+ OhciFreeDev (Ohc);
+
+ return;
+}
+
+/**
+
+ One notified function to stop the Host Controller when gBS->ExitBootServices() called.
+
+ @param Event Pointer to this event
+ @param Context Event hanlder private data
+**/
+VOID
+EFIAPI
+OhcExitBootService (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ EFI_USB_HC_PROTOCOL *UsbHc;
+ Ohc = (USB_OHCI_HC_DEV *) Context;
+
+ UsbHc = &Ohc->UsbHc;
+ //
+ // Stop the Host Controller
+ //
+ //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
+ OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
+ UsbHc->Reset (UsbHc, EFI_USB_HC_RESET_GLOBAL);
+ UsbHc->SetState (UsbHc, EfiUsbHcStateHalt);
+
+ return;
+}
+
+
+/**
+ Starting the Usb OHCI Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+OHCIDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_OHCI_HC_DEV *Ohc;
+ UINT64 Supports;
+ UINT64 OriginalPciAttributes;
+ BOOLEAN PciAttributesSaved;
+ UINTN OhciSegmentNumber;
+ UINTN OhciBusNumber;
+ UINTN OhciDeviceNumber;
+ UINTN OhciFunctionNumber;
+ UINTN NumberOfControllers;
+ UINTN Index;
+
+ //
+ // Open PCIIO, then enable the HC device and turn off emulation
+ //
+ Ohc = NULL;
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciAttributesSaved = FALSE;
+ //
+ // Save original PCI attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &OriginalPciAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto CLOSE_PCIIO;
+ }
+ PciAttributesSaved = TRUE;
+
+ //
+ // Robustnesss improvement such as for UoL
+ // Default is not required.
+ //
+ //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
+ // OhciTurnOffUsbEmulation (PciIo);
+ //}
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto CLOSE_PCIIO;
+ }
+ //
+ //Allocate memory for OHC private data structure
+ //
+ Ohc = OhciAllocateDev(PciIo, OriginalPciAttributes);
+ if (Ohc == NULL){
+ Status = EFI_OUT_OF_RESOURCES;
+ goto CLOSE_PCIIO;
+ }
+
+ //Status = OhciInitializeInterruptList ( Uhc );
+ //if (EFI_ERROR (Status)) {
+ // goto FREE_OHC;
+ //}
+
+ //
+ // Set 0.1 s timer
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ OhciHouseKeeper,
+ Ohc,
+ &Ohc->HouseKeeperTimer
+ );
+ if (EFI_ERROR (Status)) {
+ goto FREE_OHC;
+ }
+
+ Status = gBS->SetTimer (Ohc->HouseKeeperTimer, TimerPeriodic, 100 * 1000 * 10);
+ if (EFI_ERROR (Status)) {
+ goto FREE_OHC;
+ }
+ //
+ // Before initialization on the ohci, for QuarkSCSocId, all the companion controllers
+ // should have bus master , memory space and io space bits enabled
+ //
+ NumberOfControllers = 4;
+
+ PciIo->GetLocation (
+ PciIo,
+ &OhciSegmentNumber,
+ &OhciBusNumber,
+ &OhciDeviceNumber,
+ &OhciFunctionNumber
+ );
+
+ for (Index = 0; Index < NumberOfControllers; Index++) {
+ PciOr16 (
+ PCI_LIB_ADDRESS (OhciBusNumber, OhciDeviceNumber, Index, PCI_COMMAND_OFFSET),
+ (EFI_PCI_COMMAND_IO_SPACE + EFI_PCI_COMMAND_MEMORY_SPACE + EFI_PCI_COMMAND_BUS_MASTER)
+ );
+ }
+ //
+ //Install Host Controller Protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiUsbHcProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Ohc->UsbHc
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Install protocol error"));
+ goto FREE_OHC;
+ }
+ //
+ // Create event to stop the HC when exit boot service.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ OhcExitBootService,
+ Ohc,
+ &gEfiEventExitBootServicesGuid,
+ &Ohc->ExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Create exit boot event error"));
+ goto UNINSTALL_USBHC;
+ }
+ AddUnicodeString2 (
+ "eng",
+ gOhciComponentName.SupportedLanguages,
+ &Ohc->ControllerNameTable,
+ L"Usb Universal Host Controller",
+ TRUE
+ );
+ AddUnicodeString2 (
+ "en",
+ gOhciComponentName2.SupportedLanguages,
+ &Ohc->ControllerNameTable,
+ L"Usb Universal Host Controller",
+ FALSE
+ );
+
+ return EFI_SUCCESS;
+
+UNINSTALL_USBHC:
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ &Ohc->UsbHc,
+ NULL
+ );
+
+FREE_OHC:
+ OhciFreeDev (Ohc);
+
+CLOSE_PCIIO:
+ if (PciAttributesSaved) {
+ //
+ // Restore original PCI attributes
+ //
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSet,
+ OriginalPciAttributes,
+ NULL
+ );
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+}
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+OHCIDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_HC_PROTOCOL *UsbHc;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **)&UsbHc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OhciCleanDevUp(Controller, UsbHc);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
+}
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.h
new file mode 100644
index 0000000..4379139
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.h
@@ -0,0 +1,695 @@
+/** @file
+ Provides the definition of Usb Hc Protocol and OHCI controller
+ private data structure.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#ifndef _OHCI_H
+#define _OHCI_H
+
+
+#include <Uefi.h>
+
+#include <Protocol/Usb2HostController.h>
+#include <Protocol/UsbHostController.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+
+typedef struct _USB_OHCI_HC_DEV USB_OHCI_HC_DEV;
+
+#include "UsbHcMem.h"
+#include "OhciReg.h"
+#include "OhciSched.h"
+#include "OhciUrb.h"
+#include "Descriptor.h"
+#include "ComponentName.h"
+#include "OhciDebug.h"
+
+extern EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gOhciComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentName2;
+
+#define USB_OHCI_HC_DEV_SIGNATURE SIGNATURE_32('o','h','c','i')
+
+typedef struct _HCCA_MEMORY_BLOCK{
+ ED_DESCRIPTOR *HccaInterruptTable[32];
+ UINT16 HccaFrameNumber;
+ UINT16 HccaPad;
+ TD_DESCRIPTOR *HccaDoneHead;
+ UINT8 Reserved[116];
+} HCCA_MEMORY_BLOCK;
+
+
+struct _USB_OHCI_HC_DEV {
+ UINTN Signature;
+ EFI_USB_HC_PROTOCOL UsbHc;
+ EFI_USB2_HC_PROTOCOL Usb2Hc;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 OriginalPciAttributes;
+
+ HCCA_MEMORY_BLOCK *HccaMemoryBlock;
+ VOID *HccaMemoryBuf;
+ VOID *HccaMemoryMapping;
+ UINTN HccaMemoryPages;
+
+ ED_DESCRIPTOR *IntervalList[6][32];
+ INTERRUPT_CONTEXT_ENTRY *InterruptContextList;
+ VOID *MemPool;
+
+ UINT32 ToggleFlag;
+
+ EFI_EVENT HouseKeeperTimer;
+ //
+ // ExitBootServicesEvent is used to stop the OHC DMA operation
+ // after exit boot service.
+ //
+ EFI_EVENT ExitBootServiceEvent;
+
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+};
+
+#define USB_OHCI_HC_DEV_FROM_THIS(a) CR(a, USB_OHCI_HC_DEV, UsbHc, USB_OHCI_HC_DEV_SIGNATURE)
+#define USB2_OHCI_HC_DEV_FROM_THIS(a) CR(a, USB_OHCI_HC_DEV, Usb2Hc, USB_OHCI_HC_DEV_SIGNATURE)
+
+//
+// Func List
+//
+
+/**
+ Provides software reset for the USB host controller.
+
+ @param This This EFI_USB_HC_PROTOCOL instance.
+ @param Attributes A bit mask of the reset operation to perform.
+
+ @retval EFI_SUCCESS The reset operation succeeded.
+ @retval EFI_INVALID_PARAMETER Attributes is not valid.
+ @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
+ not currently supported by the host controller.
+ @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciReset (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+ );
+/**
+ Retrieve the current state of the USB host controller.
+
+ @param This This EFI_USB_HC_PROTOCOL instance.
+ @param State Variable to return the current host controller
+ state.
+
+ @retval EFI_SUCCESS Host controller state was returned in State.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+ @retval EFI_DEVICE_ERROR An error was encountered while attempting to
+ retrieve the host controller's current state.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciGetState (
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+ );
+/**
+ Sets the USB host controller to a specific state.
+
+ @param This This EFI_USB_HC_PROTOCOL instance.
+ @param State The state of the host controller that will be set.
+
+ @retval EFI_SUCCESS The USB host controller was successfully placed
+ in the state specified by State.
+ @retval EFI_INVALID_PARAMETER State is invalid.
+ @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciSetState(
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+ );
+/**
+
+ Submits control transfer to a target USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+ @param MaxPaketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ @param Request A pointer to the USB device request that will be sent
+ to the USB device.
+ @param TransferDirection Specifies the data direction for the transfer.
+ There are three values available, DataIn, DataOut
+ and NoData.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param DataLength Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ @param TimeOut Indicates the maximum time, in microseconds,
+ which the transfer is allowed to complete.
+ @param TransferResult A pointer to the detailed result information generated
+ by this control transfer.
+
+ @retval EFI_SUCCESS The control transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT The control transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+
+
+EFI_STATUS
+EFIAPI
+OhciControlTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+/**
+
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress The combination of an endpoint number and an
+ endpoint direction of the target USB device.
+ Each endpoint address supports data transfer in
+ one direction except the control endpoint
+ (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents a bulk endpoint.
+ @param MaximumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param DataLength When input, indicates the size, in bytes, of the data buffer
+ specified by Data. When output, indicates the actually
+ transferred data size.
+ @param DataToggle A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the bulk transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent bulk transfer.
+ @param TimeOut Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ TransferResult A pointer to the detailed result information of the
+ bulk transfer.
+
+ @retval EFI_SUCCESS The bulk transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted due to lack of resource.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT The bulk transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciBulkTransfer(
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaxPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+/**
+
+ Submits an interrupt transfer to an interrupt endpoint of a USB device.
+
+ @param Ohc Device private data
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+ @param IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+ @param MaxPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+ @param DataToggle A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+ @param PollingInterval Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+ @param UCBuffer Uncacheable buffer
+ @param DataLength Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+ @param CallBackFunction The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+ @param Context The context that is passed to the CallBackFunction.
+ This is an optional parameter and may be NULL.
+ @param IsPeriodic Periodic interrupt or not
+ @param OutputED The correspoding ED carried out
+ @param OutputTD The correspoding TD carried out
+
+
+ @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+
+EFI_STATUS
+OhciInterruptTransfer (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle OPTIONAL,
+ IN UINTN PollingInterval OPTIONAL,
+ IN VOID *UCBuffer OPTIONAL,
+ IN UINTN DataLength OPTIONAL,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,
+ IN VOID *Context OPTIONAL,
+ IN BOOLEAN IsPeriodic OPTIONAL,
+ OUT ED_DESCRIPTOR **OutputED OPTIONAL,
+ OUT TD_DESCRIPTOR **OutputTD OPTIONAL
+ );
+/**
+
+ Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+ @param IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+ @param MaxiumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+ @param DataToggle A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+ @param PollingInterval Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+ @param DataLength Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+ @param CallBackFunction The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+ @param Context The context that is passed to the CallBackFunction.
+ This is an optional parameter and may be NULL.
+
+ @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciAsyncInterruptTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle OPTIONAL,
+ IN UINTN PollingInterval OPTIONAL,
+ IN UINTN DataLength OPTIONAL,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,
+ IN VOID *Context OPTIONAL
+ );
+/**
+
+ Submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint
+ address supports data transfer in one direction
+ except the control endpoint (whose default
+ endpoint address is 0). It is the caller's responsibility
+ to make sure that the EndPointAddress represents
+ an interrupt endpoint.
+ @param IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+ @param MaxPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param DataLength On input, the size, in bytes, of the data buffer specified
+ by Data. On output, the number of bytes transferred.
+ @param DataToggle A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the synchronous interrupt
+ transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent synchronous interrupt transfer.
+ @param TimeOut Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+ @param TransferResult A pointer to the detailed result information from
+ the synchronous interrupt transfer.
+
+ @retval EFI_UNSUPPORTED This interface not available.
+ @retval EFI_INVALID_PARAMETER Parameters not follow spec
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciSyncInterruptTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+/**
+
+ Submits isochronous transfer to a target USB device.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress End point address
+ @param MaximumPacketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param DataLength Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ @param TransferResult A pointer to the detailed result information generated
+ by this control transfer.
+
+ @retval EFI_UNSUPPORTED This interface not available
+ @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciIsochronousTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN DataLength,
+ OUT UINT32 *TransferResult
+ );
+/**
+
+ Submits Async isochronous transfer to a target USB device.
+
+ @param his A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ @param EndPointAddress End point address
+ @param MaximumPacketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ @param Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ @param IsochronousCallBack When the transfer complete, the call back function will be called
+ @param Context Pass to the call back function as parameter
+
+ @retval EFI_UNSUPPORTED This interface not available
+ @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciAsyncIsochronousTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context OPTIONAL
+ );
+
+/**
+
+ Retrieves the number of root hub ports.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param NumOfPorts A pointer to the number of the root hub ports.
+
+ @retval EFI_SUCCESS The port number was retrieved successfully.
+**/
+EFI_STATUS
+EFIAPI
+OhciGetRootHubNumOfPorts (
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT UINT8 *NumOfPorts
+ );
+/**
+
+ Retrieves the current status of a USB root hub port.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL.
+ @param PortNumber Specifies the root hub port from which the status
+ is to be retrieved. This value is zero-based. For example,
+ if a root hub has two ports, then the first port is numbered 0,
+ and the second port is numbered 1.
+ @param PortStatus A pointer to the current port status bits and
+ port status change bits.
+
+ @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber
+ was returned in PortStatus.
+ @retval EFI_INVALID_PARAMETER Port number not valid
+**/
+
+
+EFI_STATUS
+EFIAPI
+OhciGetRootHubPortStatus (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ );
+
+/**
+
+ Sets a feature for the specified root hub port.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL.
+ @param PortNumber Specifies the root hub port whose feature
+ is requested to be set.
+ @param PortFeature Indicates the feature selector associated
+ with the feature set request.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was set for the
+ USB root hub port specified by PortNumber.
+ @retval EFI_DEVICE_ERROR Set feature failed because of hardware issue
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+**/
+EFI_STATUS
+EFIAPI
+OhciSetRootHubPortFeature (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+/**
+
+ Clears a feature for the specified root hub port.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
+ @param PortNumber Specifies the root hub port whose feature
+ is requested to be cleared.
+ @param PortFeature Indicates the feature selector associated with the
+ feature clear request.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the
+ USB root hub port specified by PortNumber.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+ @retval EFI_DEVICE_ERROR Some error happened when clearing feature
+**/
+EFI_STATUS
+EFIAPI
+OhciClearRootHubPortFeature (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has UsbHcProtocol installed will be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+
+OHCIDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starting the Usb OHCI Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+OHCIDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+OHCIDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.c
new file mode 100644
index 0000000..4df4635
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.c
@@ -0,0 +1,102 @@
+/** @file
+ This file provides the information dump support for OHCI when in debug mode.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "Ohci.h"
+
+
+/*++
+
+ Print the data of ED and the TDs attached to the ED
+
+ @param Uhc Pointer to OHCI private data
+ @param Ed Pointer to a ED to free
+ @param Td Pointer to the Td head
+
+ @retval EFI_SUCCESS ED
+
+**/
+EFI_STATUS
+OhciDumpEdTdInfo (
+ IN USB_OHCI_HC_DEV *Uhc,
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *Td,
+ BOOLEAN Stage
+ )
+{
+ UINT32 Index;
+
+ if (Stage) {
+ DEBUG ((EFI_D_INFO, "\n Before executing command\n"));
+ }else{
+ DEBUG ((EFI_D_INFO, "\n after executing command\n"));
+ }
+ if (Ed != NULL) {
+ DEBUG ((EFI_D_INFO, "\nED Address:%x, ED buffer:\n", (UINT32)(UINTN)Ed));
+ DEBUG ((EFI_D_INFO, "DWord0 :TD Tail :TD Head :Next ED\n"));
+ for (Index = 0; Index < sizeof (ED_DESCRIPTOR)/4; Index ++) {
+ DEBUG ((EFI_D_INFO, "%8x ", *((UINT32*)(Ed) + Index) ));
+ }
+ DEBUG ((EFI_D_INFO, "\nNext TD buffer:\n", (UINT32)(UINTN)Td));
+ }
+ while (Td != NULL) {
+ if (Td->Word0.DirPID == TD_SETUP_PID) {
+ DEBUG ((EFI_D_INFO, "\nSetup PID "));
+ }else if (Td->Word0.DirPID == TD_OUT_PID) {
+ DEBUG ((EFI_D_INFO, "\nOut PID "));
+ }else if (Td->Word0.DirPID == TD_IN_PID) {
+ DEBUG ((EFI_D_INFO, "\nIn PID "));
+ }else if (Td->Word0.DirPID == TD_NODATA_PID) {
+ DEBUG ((EFI_D_INFO, "\nNo data PID "));
+ }
+ DEBUG ((EFI_D_INFO, "TD Address:%x, TD buffer:\n", (UINT32)(UINTN)Td));
+ DEBUG ((EFI_D_INFO, "DWord0 :CuBuffer:Next TD :Buff End:Next TD :DataBuff:ActLength\n"));
+ for (Index = 0; Index < sizeof (TD_DESCRIPTOR)/4; Index ++) {
+ DEBUG ((EFI_D_INFO, "%8x ", *((UINT32*)(Td) + Index) ));
+ }
+ DEBUG ((EFI_D_INFO, "\nCurrent TD Data buffer(size%d)\n", (UINT32)Td->ActualSendLength));
+ for (Index = 0; Index < Td->ActualSendLength; Index ++) {
+ DEBUG ((EFI_D_INFO, "%2x ", *(UINT8 *)(UINTN)(Td->DataBuffer+Index) ));
+ }
+ Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);
+ }
+ DEBUG ((EFI_D_INFO, "\n TD buffer End\n", (UINT32)(UINTN)Td));
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.h
new file mode 100644
index 0000000..60eda6e
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.h
@@ -0,0 +1,66 @@
+/** @file
+ This file contains the definination for host controller
+ debug support routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+/*++
+
+Routine Description:
+
+ Print the data of ED and the TDs attached to the ED
+
+ @param Uhc Pointer to OHCI private data
+ @param Ed Pointer to a ED to free
+ @param Td Pointer to the Td head
+
+ @retval EFI_SUCCESS ED
+
+**/
+EFI_STATUS
+OhciDumpEdTdInfo (
+ IN USB_OHCI_HC_DEV *Uhc,
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *Td,
+ BOOLEAN Stage
+ );
+
+
+
+
+
+
+
+
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf
new file mode 100644
index 0000000..2bc7639
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf
@@ -0,0 +1,101 @@
+## @file
+# FIX ME!
+#
+# FIX ME!
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = OhciDxe
+ FILE_GUID = 4ACA697E-F883-446f-98F7-096416FFFFFF
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = OHCIDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gOhciDriverBinding
+# COMPONENT_NAME = gOhciComponentName
+# COMPONENT_NAME2 = gOhciComponentName2
+#
+[Sources]
+ Descriptor.h
+ Ohci.c
+ Ohci.h
+ OhciSched.c
+ OhciSched.h
+ OhciReg.c
+ OhciReg.h
+ OhciUrb.c
+ OhciUrb.h
+ OhciDebug.c
+ OhciDebug.h
+ ComponentName.c
+ ComponentName.h
+ UsbHcMem.c
+ UsbHcMem.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ PciLib
+
+[Guids]
+ gEfiEventExitBootServicesGuid ## PRODUCES ## Event
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiUsbHcProtocolGuid ## BY_START
+
+
+# [Event]
+# ##
+# # Periodic timer event for checking the result of interrupt transfer execution.
+# #
+# EVENT_TYPE_PERIODIC_TIMER ## PRODUCES
+#
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.c
new file mode 100644
index 0000000..b083586
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.c
@@ -0,0 +1,1417 @@
+/** @file
+ The OHCI register operation routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "Ohci.h"
+
+/**
+
+ Get OHCI operational reg value
+
+ @param PciIo PciIo protocol instance
+ @param Offset Offset of the operational reg
+
+ @retval Value of the register
+
+**/
+UINT32
+OhciGetOperationalReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset
+ )
+{
+ UINT32 Value;
+ EFI_STATUS Status;
+
+ Status = PciIo->Mem.Read(PciIo, EfiPciIoWidthUint32, OHC_BAR_INDEX, Offset, 1, &Value);
+
+ return Value;
+}
+/**
+
+ Set OHCI operational reg value
+
+ @param PciIo PCI Bus Io protocol instance
+ @param Offset Offset of the operational reg
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set to the reg
+
+**/
+
+
+EFI_STATUS
+OhciSetOperationalReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset,
+ IN VOID *Value
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint32, OHC_BAR_INDEX, Offset, 1, Value);
+
+ return Status;
+}
+/**
+
+ Get HcRevision reg value
+
+ @param PciIo PCI Bus Io protocol instance
+
+ @retval Value of the register
+
+**/
+
+
+UINT32
+OhciGetHcRevision (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+{
+ return OhciGetOperationalReg (PciIo, HC_REVISION);
+}
+/**
+
+ Set HcReset reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcReset (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcRESET Reset;
+
+ Status = EFI_SUCCESS;
+ *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR);
+
+ if (Field & RESET_SYSTEM_BUS) {
+ Reset.FSBIR = Value;
+ }
+
+ if (Field & RESET_HOST_CONTROLLER) {
+ Reset.FHR = Value;
+ }
+
+ if (Field & RESET_CLOCK_GENERATION) {
+ Reset.CGR = Value;
+ }
+
+ if (Field & RESET_SSE_GLOBAL) {
+ Reset.SSE = Value;
+ }
+
+ if (Field & RESET_PSPL) {
+ Reset.PSPL = Value;
+ }
+
+ if (Field & RESET_PCPL) {
+ Reset.PCPL = Value;
+ }
+
+ if (Field & RESET_SSEP1) {
+ Reset.SSEP1 = Value;
+ }
+
+ if (Field & RESET_SSEP2) {
+ Reset.SSEP2 = Value;
+ }
+
+ if (Field & RESET_SSEP3) {
+ Reset.SSEP3 = Value;
+ }
+
+ OhciSetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR, &Reset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Get specific field of HcReset reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcReset (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Field
+ )
+{
+ HcRESET Reset;
+ UINT32 Value;
+
+
+ *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR);
+ Value = 0;
+
+ switch (Field) {
+ case RESET_SYSTEM_BUS:
+ Value = Reset.FSBIR;
+ break;
+
+ case RESET_HOST_CONTROLLER:
+ Value = Reset.FHR;
+ break;
+
+ case RESET_CLOCK_GENERATION:
+ Value = Reset.CGR;
+ break;
+
+ case RESET_SSE_GLOBAL:
+ Value = Reset.SSE;
+ break;
+
+ case RESET_PSPL:
+ Value = Reset.PSPL;
+ break;
+
+ case RESET_PCPL:
+ Value = Reset.PCPL;
+ break;
+
+ case RESET_SSEP1:
+ Value = Reset.SSEP1;
+ break;
+
+ case RESET_SSEP2:
+ Value = Reset.SSEP2;
+ break;
+
+ case RESET_SSEP3:
+ Value = Reset.SSEP3;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+
+ return Value;
+}
+
+/**
+
+ Set HcControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcCONTROL Control;
+
+
+
+ *(UINT32 *) &Control = OhciGetOperationalReg (Ohc->PciIo, HC_CONTROL);
+
+ if (Field & CONTROL_BULK_RATIO) {
+ Control.ControlBulkRatio = Value;
+ }
+
+ if (Field & HC_FUNCTIONAL_STATE) {
+ Control.FunctionalState = Value;
+ }
+
+ if (Field & PERIODIC_ENABLE) {
+ Control.PeriodicEnable = Value;
+ }
+
+ if (Field & CONTROL_ENABLE) {
+ Control.ControlEnable = Value;
+ }
+
+ if (Field & ISOCHRONOUS_ENABLE) {
+ Control.IsochronousEnable = Value;
+ }
+
+ if (Field & BULK_ENABLE) {
+ Control.BulkEnable = Value;
+ }
+
+ if (Field & INTERRUPT_ROUTING) {
+ Control.InterruptRouting = Value;
+ }
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_CONTROL, &Control);
+
+ return Status;
+}
+
+
+/**
+
+ Get specific field of HcControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+
+UINT32
+OhciGetHcControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcCONTROL Control;
+
+ *(UINT32 *) &Control = OhciGetOperationalReg (Ohc->PciIo, HC_CONTROL);
+
+ switch (Field) {
+ case CONTROL_BULK_RATIO:
+ return Control.ControlBulkRatio;
+ break;
+ case PERIODIC_ENABLE:
+ return Control.PeriodicEnable;
+ break;
+ case CONTROL_ENABLE:
+ return Control.ControlEnable;
+ break;
+ case BULK_ENABLE:
+ return Control.BulkEnable;
+ break;
+ case ISOCHRONOUS_ENABLE:
+ return Control.IsochronousEnable;
+ break;
+ case HC_FUNCTIONAL_STATE:
+ return Control.FunctionalState;
+ break;
+ case INTERRUPT_ROUTING:
+ return Control.InterruptRouting;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set HcCommand reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcCommandStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcCOMMAND_STATUS CommandStatus;
+
+ ZeroMem (&CommandStatus, sizeof (HcCOMMAND_STATUS));
+
+ if(Field & HC_RESET){
+ CommandStatus.HcReset = Value;
+ }
+
+ if(Field & CONTROL_LIST_FILLED){
+ CommandStatus.ControlListFilled = Value;
+ }
+
+ if(Field & BULK_LIST_FILLED){
+ CommandStatus.BulkListFilled = Value;
+ }
+
+ if(Field & CHANGE_OWNER_REQUEST){
+ CommandStatus.ChangeOwnerRequest = Value;
+ }
+
+ if(Field & SCHEDULE_OVERRUN_COUNT){
+ CommandStatus.ScheduleOverrunCount = Value;
+ }
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS, &CommandStatus);
+
+ return Status;
+}
+
+/**
+
+ Get specific field of HcCommand reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcCommandStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcCOMMAND_STATUS CommandStatus;
+
+ *(UINT32 *) &CommandStatus = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS);
+
+ switch (Field){
+ case HC_RESET:
+ return CommandStatus.HcReset;
+ break;
+ case CONTROL_LIST_FILLED:
+ return CommandStatus.ControlListFilled;
+ break;
+ case BULK_LIST_FILLED:
+ return CommandStatus.BulkListFilled;
+ break;
+ case CHANGE_OWNER_REQUEST:
+ return CommandStatus.ChangeOwnerRequest;
+ break;
+ case SCHEDULE_OVERRUN_COUNT:
+ return CommandStatus.ScheduleOverrunCount;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Clear specific fields of Interrupt Status
+
+ @param Ohc UHC private data
+ @param Field Field to clear
+
+ @retval EFI_SUCCESS Fields cleared
+
+**/
+
+EFI_STATUS
+OhciClearInterruptStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ EFI_STATUS Status;
+ HcINTERRUPT_STATUS InterruptStatus;
+
+ ZeroMem (&InterruptStatus, sizeof (HcINTERRUPT_STATUS));
+
+ if(Field & SCHEDULE_OVERRUN){
+ InterruptStatus.SchedulingOverrun = 1;
+ }
+
+ if(Field & WRITEBACK_DONE_HEAD){
+ InterruptStatus.WriteBackDone = 1;
+ }
+ if(Field & START_OF_FRAME){
+ InterruptStatus.Sof = 1;
+ }
+
+ if(Field & RESUME_DETECT){
+ InterruptStatus.ResumeDetected = 1;
+ }
+
+ if(Field & UNRECOVERABLE_ERROR){
+ InterruptStatus.UnrecoverableError = 1;
+ }
+
+ if(Field & FRAME_NUMBER_OVERFLOW){
+ InterruptStatus.FrameNumOverflow = 1;
+ }
+
+ if(Field & ROOTHUB_STATUS_CHANGE){
+ InterruptStatus.RHStatusChange = 1;
+ }
+
+ if(Field & OWNERSHIP_CHANGE){
+ InterruptStatus.OwnerChange = 1;
+ }
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_STATUS, &InterruptStatus);
+
+ return Status;
+}
+
+/**
+
+ Get fields of HcInterrupt reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcInterruptStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcINTERRUPT_STATUS InterruptStatus;
+
+ *(UINT32 *) &InterruptStatus = OhciGetOperationalReg (Ohc->PciIo, HC_INTERRUPT_STATUS);
+
+ switch (Field){
+ case SCHEDULE_OVERRUN:
+ return InterruptStatus.SchedulingOverrun;
+ break;
+
+ case WRITEBACK_DONE_HEAD:
+ return InterruptStatus.WriteBackDone;
+ break;
+
+ case START_OF_FRAME:
+ return InterruptStatus.Sof;
+ break;
+
+ case RESUME_DETECT:
+ return InterruptStatus.ResumeDetected;
+ break;
+
+ case UNRECOVERABLE_ERROR:
+ return InterruptStatus.UnrecoverableError;
+ break;
+
+ case FRAME_NUMBER_OVERFLOW:
+ return InterruptStatus.FrameNumOverflow;
+ break;
+
+ case ROOTHUB_STATUS_CHANGE:
+ return InterruptStatus.RHStatusChange;
+ break;
+
+ case OWNERSHIP_CHANGE:
+ return InterruptStatus.OwnerChange;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set Interrupt Control reg value
+
+ @param Ohc UHC private data
+ @param StatEnable Enable or Disable
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetInterruptControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN BOOLEAN StatEnable,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcINTERRUPT_CONTROL InterruptState;
+
+
+ ZeroMem (&InterruptState, sizeof (HcINTERRUPT_CONTROL));
+
+ if(Field & SCHEDULE_OVERRUN) {
+ InterruptState.SchedulingOverrunInt = Value;
+ }
+
+ if(Field & WRITEBACK_DONE_HEAD) {
+ InterruptState.WriteBackDoneInt = Value;
+ }
+ if(Field & START_OF_FRAME) {
+ InterruptState.SofInt = Value;
+ }
+
+ if(Field & RESUME_DETECT) {
+ InterruptState.ResumeDetectedInt = Value;
+ }
+
+ if(Field & UNRECOVERABLE_ERROR) {
+ InterruptState.UnrecoverableErrorInt = Value;
+ }
+
+ if(Field & FRAME_NUMBER_OVERFLOW) {
+ InterruptState.FrameNumOverflowInt = Value;
+ }
+
+ if(Field & ROOTHUB_STATUS_CHANGE) {
+ InterruptState.RHStatusChangeInt = Value;
+ }
+
+ if(Field & OWNERSHIP_CHANGE) {
+ InterruptState.OwnerChangedInt = Value;
+ }
+
+ if(Field & MASTER_INTERRUPT) {
+ InterruptState.MasterInterruptEnable = Value;
+ }
+
+ if (StatEnable) {
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_ENABLE, &InterruptState);
+ } else {
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_DISABLE, &InterruptState);
+ }
+
+ return Status;
+}
+
+/**
+
+ Get field of HcInterruptControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcInterruptControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcINTERRUPT_CONTROL InterruptState;
+
+ *(UINT32 *) &InterruptState = OhciGetOperationalReg (Ohc->PciIo, HC_INTERRUPT_ENABLE);
+
+ switch (Field){
+ case SCHEDULE_OVERRUN:
+ return InterruptState.SchedulingOverrunInt;
+ break;
+
+ case WRITEBACK_DONE_HEAD:
+ return InterruptState.WriteBackDoneInt;
+ break;
+
+ case START_OF_FRAME:
+ return InterruptState.SofInt;
+ break;
+
+ case RESUME_DETECT:
+ return InterruptState.ResumeDetectedInt;
+ break;
+
+ case UNRECOVERABLE_ERROR:
+ return InterruptState.UnrecoverableErrorInt;
+ break;
+
+ case FRAME_NUMBER_OVERFLOW:
+ return InterruptState.FrameNumOverflowInt;
+ break;
+
+ case ROOTHUB_STATUS_CHANGE:
+ return InterruptState.RHStatusChangeInt;
+ break;
+
+ case OWNERSHIP_CHANGE:
+ return InterruptState.OwnerChangedInt;
+ break;
+
+ case MASTER_INTERRUPT:
+ return InterruptState.MasterInterruptEnable;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set memory pointer of specific type
+
+ @param Ohc UHC private data
+ @param PointerType Type of the pointer to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Memory pointer set
+
+**/
+
+EFI_STATUS
+OhciSetMemoryPointer(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN PointerType,
+ IN VOID *Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Verify;
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, (UINT32)PointerType, &Value);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Verify = OhciGetOperationalReg (Ohc->PciIo, (UINT32)PointerType);
+
+ while (Verify != (UINT32)(UINTN)Value) {
+ gBS->Stall(1000);
+ Verify = OhciGetOperationalReg (Ohc->PciIo, (UINT32)PointerType);
+ };
+
+
+ return Status;
+}
+
+/**
+
+ Get memory pointer of specific type
+
+ @param Ohc UHC private data
+ @param PointerType Type of pointer
+
+ @retval Memory pointer of the specific type
+
+**/
+
+VOID *
+OhciGetMemoryPointer (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN PointerType
+ )
+{
+
+ return (VOID *)(UINTN)OhciGetOperationalReg (Ohc->PciIo, (UINT32)PointerType);
+}
+
+
+/**
+
+ Set Frame Interval value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameInterval (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcFRM_INTERVAL FrameInterval;
+
+
+ *(UINT32 *) &FrameInterval = OhciGetOperationalReg(Ohc->PciIo, HC_FRM_INTERVAL);
+
+ if (Field & FRAME_INTERVAL) {
+ FrameInterval.FrmIntervalToggle = !FrameInterval.FrmIntervalToggle;
+ FrameInterval.FrameInterval = Value;
+ }
+
+ if (Field & FS_LARGEST_DATA_PACKET) {
+ FrameInterval.FSMaxDataPacket = Value;
+ }
+
+ if (Field & FRMINT_TOGGLE) {
+ FrameInterval.FrmIntervalToggle = Value;
+ }
+
+ Status = OhciSetOperationalReg (
+ Ohc->PciIo,
+ HC_FRM_INTERVAL,
+ &FrameInterval
+ );
+
+ return Status;
+}
+
+
+/**
+
+ Get field of frame interval reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetFrameInterval (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcFRM_INTERVAL FrameInterval;
+
+ *(UINT32 *) &FrameInterval = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_INTERVAL);
+
+ switch (Field){
+ case FRAME_INTERVAL:
+ return FrameInterval.FrameInterval;
+ break;
+
+ case FS_LARGEST_DATA_PACKET:
+ return FrameInterval.FSMaxDataPacket;
+ break;
+
+ case FRMINT_TOGGLE:
+ return FrameInterval.FrmIntervalToggle;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set Frame Remaining reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameRemaining (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcFRAME_REMAINING FrameRemaining;
+
+
+ *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING);
+
+ FrameRemaining.FrameRemaining = Value;
+ FrameRemaining.FrameRemainingToggle = !FrameRemaining.FrameRemainingToggle;
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING, &FrameRemaining);
+
+ return Status;
+}
+/**
+
+ Get value of frame remaining reg
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of frame remaining reg
+
+**/
+UINT32
+OhciGetFrameRemaining (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+
+{
+ HcFRAME_REMAINING FrameRemaining;
+
+
+ *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING);
+
+ switch (Field){
+ case FRAME_REMAINING:
+ return FrameRemaining.FrameRemaining;
+ break;
+
+ case FRAME_REMAIN_TOGGLE:
+ return FrameRemaining.FrameRemainingToggle;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set frame number reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameNumber(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_FRM_NUMBER, &Value);
+
+ return Status;
+}
+
+/**
+
+ Get frame number reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of frame number reg
+
+**/
+
+UINT32
+OhciGetFrameNumber (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ return OhciGetOperationalReg(Ohc->PciIo, HC_FRM_NUMBER);
+}
+
+/**
+
+ Set period start reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetPeriodicStart (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_PERIODIC_START, &Value);
+
+ return Status;
+}
+
+
+/**
+
+ Get periodic start reg value
+
+ @param Ohc UHC private data
+
+ @param Value of periodic start reg
+
+**/
+
+UINT32
+OhciGetPeriodicStart (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ return OhciGetOperationalReg(Ohc->PciIo, HC_PERIODIC_START);
+}
+
+
+/**
+
+ Set Ls Threshold reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetLsThreshold (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_PERIODIC_START, &Value);
+
+ return Status;
+}
+
+
+/**
+
+ Get Ls Threshold reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of Ls Threshold reg
+
+**/
+
+UINT32
+OhciGetLsThreshold (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ return OhciGetOperationalReg(Ohc->PciIo, HC_PERIODIC_START);
+}
+
+/**
+
+ Set Root Hub Descriptor reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetRootHubDescriptor (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcRH_DESC_A DescriptorA;
+ HcRH_DESC_B DescriptorB;
+
+
+ if (Field & (RH_DEV_REMOVABLE || RH_PORT_PWR_CTRL_MASK)) {
+ *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_B);
+
+ if(Field & RH_DEV_REMOVABLE) {
+ DescriptorB.DeviceRemovable = Value;
+ }
+ if(Field & RH_PORT_PWR_CTRL_MASK) {
+ DescriptorB.PortPowerControlMask = Value;
+ }
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_DESC_B, &DescriptorB);
+
+ return Status;
+ }
+
+ *(UINT32 *)&DescriptorA = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_A);
+
+ if(Field & RH_NUM_DS_PORTS) {
+ DescriptorA.NumDownStrmPorts = Value;
+ }
+ if(Field & RH_NO_PSWITCH) {
+ DescriptorA.NoPowerSwitch = Value;
+ }
+ if(Field & RH_PSWITCH_MODE) {
+ DescriptorA.PowerSwitchMode = Value;
+ }
+ if(Field & RH_DEVICE_TYPE) {
+ DescriptorA.DeviceType = Value;
+ }
+ if(Field & RH_OC_PROT_MODE) {
+ DescriptorA.OverCurrentProtMode = Value;
+ }
+ if(Field & RH_NOC_PROT) {
+ DescriptorA.NoOverCurrentProtMode = Value;
+ }
+ if(Field & RH_NO_POTPGT) {
+ DescriptorA.PowerOnToPowerGoodTime = Value;
+ }
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_DESC_A, &DescriptorA);
+
+ return Status;
+}
+
+
+/**
+
+ Get Root Hub Descriptor reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetRootHubDescriptor (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcRH_DESC_A DescriptorA;
+ HcRH_DESC_B DescriptorB;
+
+
+ *(UINT32 *) &DescriptorA = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_A);
+ *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_B);
+
+ switch (Field){
+ case RH_DEV_REMOVABLE:
+ return DescriptorB.DeviceRemovable;
+ break;
+
+ case RH_PORT_PWR_CTRL_MASK:
+ return DescriptorB.PortPowerControlMask;
+ break;
+
+ case RH_NUM_DS_PORTS:
+ return DescriptorA.NumDownStrmPorts;
+ break;
+
+ case RH_NO_PSWITCH:
+ return DescriptorA.NoPowerSwitch;
+ break;
+
+ case RH_PSWITCH_MODE:
+ return DescriptorA.PowerSwitchMode;
+ break;
+
+ case RH_DEVICE_TYPE:
+ return DescriptorA.DeviceType;
+ break;
+
+ case RH_OC_PROT_MODE:
+ return DescriptorA.OverCurrentProtMode;
+ break;
+
+ case RH_NOC_PROT:
+ return DescriptorA.NoOverCurrentProtMode;
+ break;
+
+ case RH_NO_POTPGT:
+ return DescriptorA.PowerOnToPowerGoodTime;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+
+/**
+
+ Set Root Hub Status reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetRootHubStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ EFI_STATUS Status;
+ HcRH_STATUS RootHubStatus;
+
+
+ ZeroMem (&RootHubStatus, sizeof(HcRH_STATUS));
+
+ if(Field & RH_LOCAL_PSTAT){
+ RootHubStatus.LocalPowerStat = 1;
+ }
+ if(Field & RH_OC_ID){
+ RootHubStatus.OverCurrentIndicator = 1;
+ }
+ if(Field & RH_REMOTE_WK_ENABLE){
+ RootHubStatus.DevRemoteWakeupEnable = 1;
+ }
+ if(Field & RH_LOCAL_PSTAT_CHANGE){
+ RootHubStatus.LocalPowerStatChange = 1;
+ }
+ if(Field & RH_OC_ID_CHANGE){
+ RootHubStatus.OverCurrentIndicatorChange = 1;
+ }
+ if(Field & RH_CLR_RMT_WK_ENABLE){
+ RootHubStatus.ClearRemoteWakeupEnable = 1;
+ }
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_STATUS, &RootHubStatus);
+
+ return Status;
+}
+
+
+/**
+
+ Get Root Hub Status reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetRootHubStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcRH_STATUS RootHubStatus;
+
+
+ *(UINT32 *) &RootHubStatus = OhciGetOperationalReg (Ohc->PciIo, HC_RH_STATUS);
+
+ switch (Field) {
+ case RH_LOCAL_PSTAT:
+ return RootHubStatus.LocalPowerStat;
+ break;
+ case RH_OC_ID:
+ return RootHubStatus.OverCurrentIndicator;
+ break;
+ case RH_REMOTE_WK_ENABLE:
+ return RootHubStatus.DevRemoteWakeupEnable;
+ break;
+ case RH_LOCAL_PSTAT_CHANGE:
+ return RootHubStatus.LocalPowerStatChange;
+ break;
+ case RH_OC_ID_CHANGE:
+ return RootHubStatus.OverCurrentIndicatorChange;
+ break;
+ case RH_CLR_RMT_WK_ENABLE:
+ return RootHubStatus.ClearRemoteWakeupEnable;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+
+/**
+
+ Set Root Hub Port Status reg value
+
+ @param Ohc UHC private data
+ @param Index Index of the port
+ @param Field Field to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetRootHubPortStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Index,
+ IN UINTN Field
+ )
+{
+ EFI_STATUS Status;
+ HcRHPORT_STATUS PortStatus;
+
+
+ ZeroMem (&PortStatus, sizeof(HcRHPORT_STATUS));
+
+ if (Field & RH_CLEAR_PORT_ENABLE) {
+ PortStatus.CurrentConnectStat = 1;
+ }
+ if (Field & RH_SET_PORT_ENABLE) {
+ PortStatus.EnableStat = 1;
+ }
+ if (Field & RH_SET_PORT_SUSPEND) {
+ PortStatus.SuspendStat = 1;
+ }
+ if (Field & RH_CLEAR_SUSPEND_STATUS) {
+ PortStatus.OCIndicator = 1;
+ }
+ if (Field & RH_SET_PORT_RESET) {
+ PortStatus.ResetStat = 1;
+ }
+ if (Field & RH_SET_PORT_POWER) {
+ PortStatus.PowerStat = 1;
+ }
+ if (Field & RH_CLEAR_PORT_POWER) {
+ PortStatus.LsDeviceAttached = 1;
+ }
+ if (Field & RH_CONNECT_STATUS_CHANGE) {
+ PortStatus.ConnectStatChange = 1;
+ }
+ if (Field & RH_PORT_ENABLE_STAT_CHANGE) {
+ PortStatus.EnableStatChange = 1;
+ }
+ if (Field & RH_PORT_SUSPEND_STAT_CHANGE) {
+ PortStatus.SuspendStatChange = 1;
+ }
+ if (Field & RH_OC_INDICATOR_CHANGE) {
+ PortStatus.OCIndicatorChange = 1;
+ }
+ if (Field & RH_PORT_RESET_STAT_CHANGE ) {
+ PortStatus.ResetStatChange = 1;
+ }
+
+ Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_PORT_STATUS + (Index * 4), &PortStatus);
+
+ return Status;
+}
+
+
+/**
+
+ Get Root Hub Port Status reg value
+
+ @param Ohc UHC private data
+ @param Index Index of the port
+ @param Field Field to get
+
+ @retval Value of the field and index
+
+**/
+
+UINT32
+OhciReadRootHubPortStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Index,
+ IN UINTN Field
+ )
+{
+ HcRHPORT_STATUS PortStatus;
+
+ *(UINT32 *) &PortStatus = OhciGetOperationalReg (
+ Ohc->PciIo,
+ HC_RH_PORT_STATUS + (Index * 4)
+ );
+
+ switch (Field){
+ case RH_CURR_CONNECT_STAT:
+ return PortStatus.CurrentConnectStat;
+ break;
+ case RH_PORT_ENABLE_STAT:
+ return PortStatus.EnableStat;
+ break;
+ case RH_PORT_SUSPEND_STAT:
+ return PortStatus.SuspendStat;
+ break;
+ case RH_PORT_OC_INDICATOR:
+ return PortStatus.OCIndicator;
+ break;
+ case RH_PORT_RESET_STAT:
+ return PortStatus.ResetStat;
+ break;
+ case RH_PORT_POWER_STAT:
+ return PortStatus.PowerStat;
+ break;
+ case RH_LSDEVICE_ATTACHED:
+ return PortStatus.LsDeviceAttached;
+ break;
+ case RH_CONNECT_STATUS_CHANGE:
+ return PortStatus.ConnectStatChange;
+ break;
+ case RH_PORT_ENABLE_STAT_CHANGE:
+ return PortStatus.EnableStatChange;
+ break;
+ case RH_PORT_SUSPEND_STAT_CHANGE:
+ return PortStatus.SuspendStatChange;
+ break;
+ case RH_OC_INDICATOR_CHANGE:
+ return PortStatus.OCIndicatorChange;
+ break;
+ case RH_PORT_RESET_STAT_CHANGE:
+ return PortStatus.ResetStatChange;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.h
new file mode 100644
index 0000000..617ae86
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.h
@@ -0,0 +1,944 @@
+/** @file
+ This file contains the definination for host controller
+ register operation routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#ifndef _OHCI_REG_H
+#define _OHCI_REG_H
+
+#define HC_STATE_RESET 0x0
+#define HC_STATE_RESUME 0x1
+#define HC_STATE_OPERATIONAL 0x2
+#define HC_STATE_SUSPEND 0x3
+
+#define PERIODIC_ENABLE 0x01
+#define ISOCHRONOUS_ENABLE 0x02
+#define CONTROL_ENABLE 0x04
+#define BULK_ENABLE 0x08
+#define CONTROL_BULK_RATIO 0x10
+
+#define HC_FUNCTIONAL_STATE 0x20
+#define INTERRUPT_ROUTING 0x40
+
+#define HC_RESET 0x01
+#define CONTROL_LIST_FILLED 0x02
+#define BULK_LIST_FILLED 0x04
+#define CHANGE_OWNER_REQUEST 0x08
+
+#define SCHEDULE_OVERRUN_COUNT 0x10
+
+#define SCHEDULE_OVERRUN 0x00001
+#define WRITEBACK_DONE_HEAD 0x00002
+#define START_OF_FRAME 0x00004
+#define RESUME_DETECT 0x00008
+#define UNRECOVERABLE_ERROR 0x00010
+#define FRAME_NUMBER_OVERFLOW 0x00020
+#define ROOTHUB_STATUS_CHANGE 0x00040
+#define OWNERSHIP_CHANGE 0x00080
+
+#define MASTER_INTERRUPT 0x00400
+
+#define CONTROL_HEAD 0x001
+#define BULK_HEAD 0x002
+#define DONE_HEAD 0x004
+
+#define Hc_HCCA 0x001
+#define Hc_PERIODIC_CURRENT 0x002
+#define Hc_CONTOL_HEAD 0x004
+#define Hc_CONTROL_CURRENT_PTR 0x008
+#define Hc_BULK_HEAD 0x010
+#define Hc_BULK_CURRENT_PTR 0x020
+#define Hc_DONE_HEAD 0x040
+
+#define FRAME_INTERVAL 0x008
+#define FS_LARGEST_DATA_PACKET 0x010
+#define FRMINT_TOGGLE 0x020
+#define FRAME_REMAINING 0x040
+#define FRAME_REMAIN_TOGGLE 0x080
+
+#define RH_DESC_A 0x00001
+#define RH_DESC_B 0x00002
+#define RH_NUM_DS_PORTS 0x00004
+#define RH_NO_PSWITCH 0x00008
+#define RH_PSWITCH_MODE 0x00010
+#define RH_DEVICE_TYPE 0x00020
+#define RH_OC_PROT_MODE 0x00040
+#define RH_NOC_PROT 0x00080
+#define RH_POTPGT 0x00100
+#define RH_NO_POTPGT 0x00200
+#define RH_DEV_REMOVABLE 0x00400
+#define RH_PORT_PWR_CTRL_MASK 0x00800
+
+#define RH_LOCAL_PSTAT 0x00001
+#define RH_OC_ID 0x00002
+#define RH_REMOTE_WK_ENABLE 0x00004
+#define RH_LOCAL_PSTAT_CHANGE 0x00008
+#define RH_OC_ID_CHANGE 0x00010
+#define RH_CLR_RMT_WK_ENABLE 0x00020
+
+#define RH_CLEAR_PORT_ENABLE 0x0001
+#define RH_SET_PORT_ENABLE 0x0002
+#define RH_SET_PORT_SUSPEND 0x0004
+#define RH_CLEAR_SUSPEND_STATUS 0x0008
+#define RH_SET_PORT_RESET 0x0010
+#define RH_SET_PORT_POWER 0x0020
+#define RH_CLEAR_PORT_POWER 0x0040
+#define RH_CONNECT_STATUS_CHANGE 0x10000
+#define RH_PORT_ENABLE_STAT_CHANGE 0x20000
+#define RH_PORT_SUSPEND_STAT_CHANGE 0x40000
+#define RH_OC_INDICATOR_CHANGE 0x80000
+#define RH_PORT_RESET_STAT_CHANGE 0x100000
+
+#define RH_CURR_CONNECT_STAT 0x0001
+#define RH_PORT_ENABLE_STAT 0x0002
+#define RH_PORT_SUSPEND_STAT 0x0004
+#define RH_PORT_OC_INDICATOR 0x0008
+#define RH_PORT_RESET_STAT 0x0010
+#define RH_PORT_POWER_STAT 0x0020
+#define RH_LSDEVICE_ATTACHED 0x0040
+
+#define RESET_SYSTEM_BUS (1 << 0)
+#define RESET_HOST_CONTROLLER (1 << 1)
+#define RESET_CLOCK_GENERATION (1 << 2)
+#define RESET_SSE_GLOBAL (1 << 5)
+#define RESET_PSPL (1 << 6)
+#define RESET_PCPL (1 << 7)
+#define RESET_SSEP1 (1 << 9)
+#define RESET_SSEP2 (1 << 10)
+#define RESET_SSEP3 (1 << 11)
+
+#define ONE_SECOND 1000000
+#define ONE_MILLI_SEC 1000
+#define MAX_BYTES_PER_TD 0x1000
+#define MAX_RETRY_TIMES 100
+#define PORT_NUMBER_ON_MAINSTONE2 1
+
+
+//
+// Operational Register Offsets
+//
+
+//
+// Command & Status Registers Offsets
+//
+#define HC_REVISION 0x00
+#define HC_CONTROL 0x04
+#define HC_COMMAND_STATUS 0x08
+#define HC_INTERRUPT_STATUS 0x0C
+#define HC_INTERRUPT_ENABLE 0x10
+#define HC_INTERRUPT_DISABLE 0x14
+
+//
+// Memory Pointer Offsets
+//
+#define HC_HCCA 0x18
+#define HC_PERIODIC_CURRENT 0x1C
+#define HC_CONTROL_HEAD 0x20
+#define HC_CONTROL_CURRENT_PTR 0x24
+#define HC_BULK_HEAD 0x28
+#define HC_BULK_CURRENT_PTR 0x2C
+#define HC_DONE_HEAD 0x30
+
+//
+// Frame Register Offsets
+//
+#define HC_FRM_INTERVAL 0x34
+#define HC_FRM_REMAINING 0x38
+#define HC_FRM_NUMBER 0x3C
+#define HC_PERIODIC_START 0x40
+#define HC_LS_THREASHOLD 0x44
+
+//
+// Root Hub Register Offsets
+//
+#define HC_RH_DESC_A 0x48
+#define HC_RH_DESC_B 0x4C
+#define HC_RH_STATUS 0x50
+#define HC_RH_PORT_STATUS 0x54
+
+#define USBHOST_OFFSET_UHCHR 0x64 // Usb Host reset register
+
+#define OHC_BAR_INDEX 0
+
+//
+// Usb Host controller register offset
+//
+#define USBHOST_OFFSET_UHCREV 0x0 // Usb Host revision register
+#define USBHOST_OFFSET_UHCHCON 0x4 // Usb Host control register
+#define USBHOST_OFFSET_UHCCOMS 0x8 // Usb Host Command Status register
+#define USBHOST_OFFSET_UHCINTS 0xC // Usb Host Interrupt Status register
+#define USBHOST_OFFSET_UHCINTE 0x10 // Usb Host Interrupt Enable register
+#define USBHOST_OFFSET_UHCINTD 0x14 // Usb Host Interrupt Disable register
+#define USBHOST_OFFSET_UHCHCCA 0x18 // Usb Host Controller Communication Area
+#define USBHOST_OFFSET_UHCPCED 0x1C // Usb Host Period Current Endpoint Descriptor
+#define USBHOST_OFFSET_UHCCHED 0x20 // Usb Host Control Head Endpoint Descriptor
+#define USBHOST_OFFSET_UHCCCED 0x24 // Usb Host Control Current Endpoint Descriptor
+#define USBHOST_OFFSET_UHCBHED 0x28 // Usb Host Bulk Head Endpoint Descriptor
+#define USBHOST_OFFSET_UHCBCED 0x2C // Usb Host Bulk Current Endpoint Descriptor
+#define USBHOST_OFFSET_UHCDHEAD 0x30 // Usb Host Done Head register
+#define USBHOST_OFFSET_UHCFMI 0x34 // Usb Host Frame Interval register
+#define USBHOST_OFFSET_UHCFMR 0x38 // Usb Host Frame Remaining register
+#define USBHOST_OFFSET_UHCFMN 0x3C // Usb Host Frame Number register
+#define USBHOST_OFFSET_UHCPERS 0x40 // Usb Host Periodic Start register
+#define USBHOST_OFFSET_UHCLST 0x44 // Usb Host Low-Speed Threshold register
+#define USBHOST_OFFSET_UHCRHDA 0x48 // Usb Host Root Hub Descriptor A register
+#define USBHOST_OFFSET_UHCRHDB 0x4C // Usb Host Root Hub Descriptor B register
+#define USBHOST_OFFSET_UHCRHS 0x50 // Usb Host Root Hub Status register
+#define USBHOST_OFFSET_UHCRHPS1 0x54 // Usb Host Root Hub Port Status 1 register
+
+//
+// Usb Host controller register bit fields
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 ProgInterface;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} USB_CLASSC;
+
+typedef struct {
+ UINT32 Revision:8;
+ UINT32 Rsvd:24;
+} HcREVISION;
+
+typedef struct {
+ UINT32 ControlBulkRatio:2;
+ UINT32 PeriodicEnable:1;
+ UINT32 IsochronousEnable:1;
+ UINT32 ControlEnable:1;
+ UINT32 BulkEnable:1;
+ UINT32 FunctionalState:2;
+ UINT32 InterruptRouting:1;
+ UINT32 RemoteWakeup:1;
+ UINT32 RemoteWakeupEnable:1;
+ UINT32 Reserved:21;
+} HcCONTROL;
+
+typedef struct {
+ UINT32 HcReset:1;
+ UINT32 ControlListFilled:1;
+ UINT32 BulkListFilled:1;
+ UINT32 ChangeOwnerRequest:1;
+ UINT32 Reserved1:12;
+ UINT32 ScheduleOverrunCount:2;
+ UINT32 Reserved:14;
+} HcCOMMAND_STATUS;
+
+typedef struct {
+ UINT32 SchedulingOverrun:1;
+ UINT32 WriteBackDone:1;
+ UINT32 Sof:1;
+ UINT32 ResumeDetected:1;
+ UINT32 UnrecoverableError:1;
+ UINT32 FrameNumOverflow:1;
+ UINT32 RHStatusChange:1;
+ UINT32 Reserved1:23;
+ UINT32 OwnerChange:1;
+ UINT32 Reserved2:1;
+} HcINTERRUPT_STATUS;
+
+typedef struct {
+ UINT32 SchedulingOverrunInt:1;
+ UINT32 WriteBackDoneInt:1;
+ UINT32 SofInt:1;
+ UINT32 ResumeDetectedInt:1;
+ UINT32 UnrecoverableErrorInt:1;
+ UINT32 FrameNumOverflowInt:1;
+ UINT32 RHStatusChangeInt:1;
+ UINT32 Reserved:23;
+ UINT32 OwnerChangedInt:1;
+ UINT32 MasterInterruptEnable:1;
+} HcINTERRUPT_CONTROL;
+
+typedef struct {
+ UINT32 Rerserved:8;
+ UINT32 Hcca:24;
+} HcHCCA;
+
+typedef struct {
+ UINT32 Reserved:4;
+ UINT32 MemoryPtr:28;
+} HcMEMORY_PTR;
+
+typedef struct {
+ UINT32 FrameInterval:14;
+ UINT32 Reserved:2;
+ UINT32 FSMaxDataPacket:15;
+ UINT32 FrmIntervalToggle:1;
+} HcFRM_INTERVAL;
+
+typedef struct {
+ UINT32 FrameRemaining:14;
+ UINT32 Reserved:17;
+ UINT32 FrameRemainingToggle:1;
+} HcFRAME_REMAINING;
+
+typedef struct {
+ UINT32 FrameNumber:16;
+ UINT32 Reserved:16;
+} HcFRAME_NUMBER;
+
+typedef struct {
+ UINT32 PeriodicStart:14;
+ UINT32 Reserved:18;
+} HcPERIODIC_START;
+
+typedef struct {
+ UINT32 LsThreshold:12;
+ UINT32 Reserved:20;
+} HcLS_THRESHOLD;
+
+typedef struct {
+ UINT32 NumDownStrmPorts:8;
+ UINT32 PowerSwitchMode:1;
+ UINT32 NoPowerSwitch:1;
+ UINT32 DeviceType:1;
+ UINT32 OverCurrentProtMode:1;
+ UINT32 NoOverCurrentProtMode:1;
+ UINT32 Reserved:11;
+ UINT32 PowerOnToPowerGoodTime:8;
+} HcRH_DESC_A;
+
+typedef struct {
+ UINT32 DeviceRemovable:16;
+ UINT32 PortPowerControlMask:16;
+} HcRH_DESC_B;
+
+typedef struct {
+ UINT32 LocalPowerStat:1;
+ UINT32 OverCurrentIndicator:1;
+ UINT32 Reserved1:13;
+ UINT32 DevRemoteWakeupEnable:1;
+ UINT32 LocalPowerStatChange:1;
+ UINT32 OverCurrentIndicatorChange:1;
+ UINT32 Reserved2:13;
+ UINT32 ClearRemoteWakeupEnable:1;
+} HcRH_STATUS;
+
+typedef struct {
+ UINT32 CurrentConnectStat:1;
+ UINT32 EnableStat:1;
+ UINT32 SuspendStat:1;
+ UINT32 OCIndicator:1;
+ UINT32 ResetStat:1;
+ UINT32 Reserved1:3;
+ UINT32 PowerStat:1;
+ UINT32 LsDeviceAttached:1;
+ UINT32 Reserved2:6;
+ UINT32 ConnectStatChange:1;
+ UINT32 EnableStatChange:1;
+ UINT32 SuspendStatChange:1;
+ UINT32 OCIndicatorChange:1;
+ UINT32 ResetStatChange:1;
+ UINT32 Reserved3:11;
+} HcRHPORT_STATUS;
+
+typedef struct {
+ UINT32 FSBIR:1;
+ UINT32 FHR:1;
+ UINT32 CGR:1;
+ UINT32 SSDC:1;
+ UINT32 UIT:1;
+ UINT32 SSE:1;
+ UINT32 PSPL:1;
+ UINT32 PCPL:1;
+ UINT32 Reserved0:1;
+ UINT32 SSEP1:1;
+ UINT32 SSEP2:1;
+ UINT32 SSEP3:1;
+ UINT32 Reserved1:20;
+} HcRESET;
+
+
+#pragma pack()
+
+//
+// Func List
+//
+
+
+/**
+
+ Get OHCI operational reg value
+
+ @param PciIo PciIo protocol instance
+ @param Offset Offset of the operational reg
+
+ @retval Value of the register
+
+**/
+UINT32
+OhciGetOperationalReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset
+ );
+
+/**
+
+ Set OHCI operational reg value
+
+ @param PciIo PCI Bus Io protocol instance
+ @param Offset Offset of the operational reg
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set to the reg
+
+**/
+
+
+EFI_STATUS
+OhciSetOperationalReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset,
+ IN VOID *Value
+ );
+
+
+/**
+
+ Get HcRevision reg value
+
+ @param PciIo PCI Bus Io protocol instance
+
+ @retval Value of the register
+
+**/
+
+
+UINT32
+OhciGetHcRevision (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ );
+
+/**
+
+ Set HcReset reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcReset (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Field,
+ IN UINT32 Value
+ );
+/**
+
+ Get specific field of HcReset reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcReset (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Field
+ );
+/**
+
+ Set HcControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+
+
+/**
+
+ Get specific field of HcControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+
+UINT32
+OhciGetHcControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+
+/**
+
+ Set HcCommand reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcCommandStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+
+/**
+
+ Get specific field of HcCommand reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcCommandStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+/**
+
+ Clear specific fields of Interrupt Status
+
+ @param Ohc UHC private data
+ @param Field Field to clear
+
+ @retval EFI_SUCCESS Fields cleared
+
+**/
+
+EFI_STATUS
+OhciClearInterruptStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+/**
+
+ Get fields of HcInterrupt reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcInterruptStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+/**
+
+ Set Interrupt Control reg value
+
+ @param Ohc UHC private data
+ @param StatEnable Enable or Disable
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetInterruptControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN BOOLEAN StatEnable,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+
+/**
+
+ Get field of HcInterruptControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcInterruptControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+
+/**
+
+ Set memory pointer of specific type
+
+ @param Ohc UHC private data
+ @param PointerType Type of the pointer to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Memory pointer set
+
+**/
+
+EFI_STATUS
+OhciSetMemoryPointer(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN PointerType,
+ IN VOID *Value
+ );
+
+/**
+
+ Get memory pointer of specific type
+
+ @param Ohc UHC private data
+ @param PointerType Type of pointer
+
+ @retval Memory pointer of the specific type
+
+**/
+
+VOID *
+OhciGetMemoryPointer (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN PointerType
+ );
+
+/**
+
+ Set Frame Interval value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameInterval (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+
+
+/**
+
+ Get field of frame interval reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetFrameInterval (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+
+/**
+
+ Set Frame Remaining reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameRemaining (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ );
+
+/**
+
+ Get value of frame remaining reg
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of frame remaining reg
+
+**/
+UINT32
+OhciGetFrameRemaining (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+/**
+
+ Set frame number reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameNumber(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ );
+
+/**
+
+ Get frame number reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of frame number reg
+
+**/
+
+UINT32
+OhciGetFrameNumber (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+
+
+/**
+
+ Set period start reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetPeriodicStart (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ );
+
+
+/**
+
+ Get periodic start reg value
+
+ @param Ohc UHC private data
+
+ @param Value of periodic start reg
+
+**/
+
+UINT32
+OhciGetPeriodicStart (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+
+
+/**
+
+ Set Ls Threshold reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetLsThreshold (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ );
+
+/**
+
+ Get Ls Threshold reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of Ls Threshold reg
+
+**/
+
+UINT32
+OhciGetLsThreshold (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+
+/**
+
+ Set Root Hub Descriptor reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetRootHubDescriptor (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+
+
+/**
+
+ Get Root Hub Descriptor reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetRootHubDescriptor (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+/**
+
+ Set Root Hub Status reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetRootHubStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+
+/**
+
+ Get Root Hub Status reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetRootHubStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+
+
+/**
+
+ Set Root Hub Port Status reg value
+
+ @param Ohc UHC private data
+ @param Index Index of the port
+ @param Field Field to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetRootHubPortStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Index,
+ IN UINTN Field
+ );
+
+
+/**
+
+ Get Root Hub Port Status reg value
+
+ @param Ohc UHC private data
+ @param Index Index of the port
+ @param Field Field to get
+
+ @retval Value of the field and index
+
+**/
+
+UINT32
+OhciReadRootHubPortStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Index,
+ IN UINTN Field
+ );
+
+#endif \ No newline at end of file
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.c
new file mode 100644
index 0000000..5f2d016
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.c
@@ -0,0 +1,548 @@
+/** @file
+ OHCI transfer scheduling routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "Ohci.h"
+
+/**
+
+ Add an item of interrupt context
+
+ @param Ohc UHC private data
+ @param NewEntry New entry to add
+
+ @retval EFI_SUCCESS Item successfully added
+
+**/
+EFI_STATUS
+OhciAddInterruptContextEntry (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN INTERRUPT_CONTEXT_ENTRY *NewEntry
+ )
+{
+ INTERRUPT_CONTEXT_ENTRY *Entry;
+ EFI_TPL OriginalTPL;
+
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+ if (Ohc->InterruptContextList == NULL) {
+ Ohc->InterruptContextList = NewEntry;
+ } else {
+ Entry = Ohc->InterruptContextList;
+ while (Entry->NextEntry != NULL) {
+ Entry = Entry->NextEntry;
+ }
+ Entry->NextEntry = NewEntry;
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Free a interrupt context entry
+
+ @param Ohc UHC private data
+ @param Entry Pointer to an interrupt context entry
+
+ @retval EFI_SUCCESS Entry freed
+ @retval EFI_INVALID_PARAMETER Entry is NULL
+
+**/
+EFI_STATUS
+OhciFreeInterruptContextEntry (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN INTERRUPT_CONTEXT_ENTRY *Entry
+ )
+{
+ TD_DESCRIPTOR *Td;
+ if (Entry == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Entry->UCBufferMapping != NULL) {
+ Ohc->PciIo->Unmap(Ohc->PciIo, Entry->UCBufferMapping);
+ }
+ if (Entry->UCBuffer != NULL) {
+ FreePool(Entry->UCBuffer);
+ }
+ while (Entry->DataTd) {
+ Td = Entry->DataTd;
+ Entry->DataTd = (TD_DESCRIPTOR *)(UINTN)(Entry->DataTd->NextTDPointer);
+ UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
+ }
+ FreePool(Entry);
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Free entries match the device address and endpoint address
+
+ @Param Ohc UHC private date
+ @Param DeviceAddress Item to free must match this device address
+ @Param EndPointAddress Item to free must match this end point address
+ @Param DataToggle DataToggle for output
+
+ @retval EFI_SUCCESS Items match the requirement removed
+
+**/
+EFI_STATUS
+OhciFreeInterruptContext(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ OUT UINT8 *DataToggle
+ )
+{
+ INTERRUPT_CONTEXT_ENTRY *Entry;
+ INTERRUPT_CONTEXT_ENTRY *TempEntry;
+ EFI_TPL OriginalTPL;
+
+
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+ while (Ohc->InterruptContextList != NULL &&
+ Ohc->InterruptContextList->DeviceAddress == DeviceAddress &&
+ Ohc->InterruptContextList->EndPointAddress == EndPointAddress) {
+ TempEntry = Ohc->InterruptContextList;
+ Ohc->InterruptContextList = Ohc->InterruptContextList->NextEntry;
+ if (DataToggle != NULL) {
+ *DataToggle = (UINT8) (TempEntry->DataTd->Word0.DataToggle & 0x1);
+ }
+ OhciFreeInterruptContextEntry (Ohc, TempEntry);
+ }
+
+ Entry = Ohc->InterruptContextList;
+ if (Entry == NULL) {
+ gBS->RestoreTPL (OriginalTPL);
+ return EFI_SUCCESS;
+ }
+ while (Entry->NextEntry != NULL) {
+ if (Entry->NextEntry->DeviceAddress == DeviceAddress &&
+ Entry->NextEntry->EndPointAddress == EndPointAddress) {
+ TempEntry = Entry->NextEntry;
+ Entry->NextEntry = Entry->NextEntry->NextEntry;
+ if (DataToggle != NULL) {
+ *DataToggle = (UINT8) (TempEntry->DataTd->Word0.DataToggle & 0x1);
+ }
+ OhciFreeInterruptContextEntry (Ohc, TempEntry);
+ } else {
+ Entry = Entry->NextEntry;
+ }
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Convert Error code from OHCI format to EFI format
+
+ @Param ErrorCode ErrorCode in OHCI format
+
+ @retval ErrorCode in EFI format
+
+**/
+UINT32
+ConvertErrorCode (
+ IN UINT32 ErrorCode
+ )
+{
+ UINT32 TransferResult;
+
+ switch (ErrorCode) {
+ case TD_NO_ERROR:
+ TransferResult = EFI_USB_NOERROR;
+ break;
+
+ case TD_TOBE_PROCESSED:
+ case TD_TOBE_PROCESSED_2:
+ TransferResult = EFI_USB_ERR_NOTEXECUTE;
+ break;
+
+ case TD_DEVICE_STALL:
+ TransferResult = EFI_USB_ERR_STALL;
+ break;
+
+ case TD_BUFFER_OVERRUN:
+ case TD_BUFFER_UNDERRUN:
+ TransferResult = EFI_USB_ERR_BUFFER;
+ break;
+
+ case TD_CRC_ERROR:
+ TransferResult = EFI_USB_ERR_CRC;
+ break;
+
+ case TD_NO_RESPONSE:
+ TransferResult = EFI_USB_ERR_TIMEOUT;
+ break;
+
+ case TD_BITSTUFFING_ERROR:
+ TransferResult = EFI_USB_ERR_BITSTUFF;
+ break;
+
+ default:
+ TransferResult = EFI_USB_ERR_SYSTEM;
+ }
+
+ return TransferResult;
+}
+
+
+/**
+
+ Check TDs Results
+
+ @Param Ohc UHC private data
+ @Param Td TD_DESCRIPTOR
+ @Param Result Result to return
+
+ @retval TRUE means OK
+ @retval FLASE means Error or Short packet
+
+**/
+BOOLEAN
+OhciCheckTDsResults (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN TD_DESCRIPTOR *Td,
+ OUT UINT32 *Result
+ )
+{
+ UINT32 TdCompletionCode;
+
+ *Result = EFI_USB_NOERROR;
+
+ while (Td) {
+ TdCompletionCode = Td->Word0.ConditionCode;
+
+ *Result |= ConvertErrorCode(TdCompletionCode);
+ //
+ // if any error encountered, stop processing the left TDs.
+ //
+ if (*Result) {
+ return FALSE;
+ }
+
+ Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);
+ }
+ return TRUE;
+
+}
+
+
+/**
+
+ Check the task status on an ED
+
+ @Param Ed Pointer to the ED task that TD hooked on
+ @Param HeadTd TD header for current transaction
+
+ @retval Task Status Code
+
+**/
+
+UINT32
+CheckEDStatus (
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd,
+ OUT OHCI_ED_RESULT *EdResult
+ )
+{
+ while(HeadTd != NULL) {
+ if (HeadTd->NextTDPointer == 0) {
+ return TD_NO_ERROR;
+ }
+ if (HeadTd->Word0.ConditionCode != 0) {
+ return HeadTd->Word0.ConditionCode;
+ }
+ EdResult->NextToggle = ((UINT8)(HeadTd->Word0.DataToggle) & BIT0) ^ BIT0;
+ HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
+ }
+ if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {
+ return TD_TOBE_PROCESSED;
+ }
+ return TD_NO_ERROR;
+}
+
+/**
+
+ Check the task status
+
+ @Param Ohc UHC private data
+ @Param ListType Pipe type
+ @Param Ed Pointer to the ED task hooked on
+ @Param HeadTd Head of TD corresponding to the task
+ @Param ErrorCode return the ErrorCode
+
+ @retval EFI_SUCCESS Task done
+ @retval EFI_NOT_READY Task on processing
+ @retval EFI_DEVICE_ERROR Some error occured
+
+**/
+EFI_STATUS
+CheckIfDone (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN DESCRIPTOR_LIST_TYPE ListType,
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd,
+ OUT OHCI_ED_RESULT *EdResult
+ )
+{
+ EdResult->ErrorCode = TD_TOBE_PROCESSED;
+
+ switch (ListType) {
+ case CONTROL_LIST:
+ if (OhciGetHcCommandStatus (Ohc, CONTROL_LIST_FILLED) != 0) {
+ return EFI_NOT_READY;
+ }
+ break;
+ case BULK_LIST:
+ if (OhciGetHcCommandStatus (Ohc, BULK_LIST_FILLED) != 0) {
+ return EFI_NOT_READY;
+ }
+ break;
+ default:
+ break;
+ }
+
+ EdResult->ErrorCode = CheckEDStatus (Ed, HeadTd, EdResult);
+
+ if (EdResult->ErrorCode == TD_NO_ERROR) {
+ return EFI_SUCCESS;
+ } else if (EdResult->ErrorCode == TD_TOBE_PROCESSED) {
+ return EFI_NOT_READY;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+
+/**
+
+ Convert TD condition code to Efi Status
+
+ @Param ConditionCode Condition code to convert
+
+ @retval EFI_SUCCESS No error occured
+ @retval EFI_NOT_READY TD still on processing
+ @retval EFI_DEVICE_ERROR Error occured in processing TD
+
+**/
+
+EFI_STATUS
+OhciTDConditionCodeToStatus (
+ IN UINT32 ConditionCode
+ )
+{
+ if (ConditionCode == TD_NO_ERROR) {
+ return EFI_SUCCESS;
+ }
+
+ if (ConditionCode == TD_TOBE_PROCESSED) {
+ return EFI_NOT_READY;
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+/**
+
+ Invoke callbacks hooked on done TDs
+
+ @Param Entry Interrupt transfer transaction information data structure
+ @Param Context Ohc private data
+
+**/
+
+VOID
+OhciInvokeInterruptCallBack(
+ IN INTERRUPT_CONTEXT_ENTRY *Entry,
+ IN UINT32 Result
+)
+{
+ //Generally speaking, Keyboard driver should not
+ //check the Keyboard buffer if an error happens, it will be robust
+ //if we NULLed the buffer once error happens
+ if (Result) {
+ Entry->CallBackFunction (
+ NULL,
+ 0,
+ Entry->Context,
+ Result
+ );
+ }else{
+ Entry->CallBackFunction (
+ (UINT8 *)(UINTN)(Entry->DataTd->DataBuffer),
+ Entry->DataTd->ActualSendLength,
+ Entry->Context,
+ Result
+ );
+ }
+}
+
+
+/**
+
+ Timer to submit periodic interrupt transfer, and invoke callbacks hooked on done TDs
+
+ @param Event Event handle
+ @param Context Device private data
+
+**/
+
+VOID
+EFIAPI
+OhciHouseKeeper (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+
+ USB_OHCI_HC_DEV *Ohc;
+ INTERRUPT_CONTEXT_ENTRY *Entry;
+ INTERRUPT_CONTEXT_ENTRY *PreEntry;
+ ED_DESCRIPTOR *Ed;
+ TD_DESCRIPTOR *DataTd;
+ TD_DESCRIPTOR *HeadTd;
+
+ UINT8 Toggle;
+ EFI_TPL OriginalTPL;
+ UINT32 Result;
+
+ Ohc = (USB_OHCI_HC_DEV *) Context;
+ OriginalTPL = gBS->RaiseTPL(TPL_NOTIFY);
+
+ Entry = Ohc->InterruptContextList;
+ PreEntry = NULL;
+
+ while(Entry != NULL) {
+
+ OhciCheckTDsResults(Ohc, Entry->DataTd, &Result );
+ if (((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) ||
+ ((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) {
+ return ;
+ }
+
+ if (Entry->CallBackFunction != NULL) {
+ OhciInvokeInterruptCallBack (Entry, Result);
+ }
+ if (Entry->IsPeriodic) {
+
+ Ed = Entry->Ed;
+ HeadTd = Entry->DataTd;
+ DataTd = HeadTd;
+ Toggle = 0;
+ if (Result == EFI_USB_NOERROR) {
+ //
+ // Update toggle if there is no error, and re-submit the interrupt Ed&Tds
+ //
+ if ((Ed != NULL) && (DataTd != NULL)) {
+ Ed->Word0.Skip = 1;
+ }
+ //
+ // From hcir1_0a.pdf 4.2.2
+ // ToggleCarry:This bit is the data toggle carry bit,
+ // Whenever a TD is retired, this bit is written to
+ // contain the last data toggle value(LSb of data Toggel
+ // file) from the retired TD.
+ // This field is not used for Isochronous Endpoints
+ //
+ if (Ed == NULL)
+ {
+ return;
+ }
+ Toggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
+ while(DataTd != NULL) {
+ if (DataTd->NextTDPointer == 0) {
+ DataTd->Word0.DataToggle = 0;
+ break;
+ } else {
+ OhciSetTDField (DataTd, TD_DT_TOGGLE, Toggle);
+ }
+ DataTd = (TD_DESCRIPTOR *)(UINTN)(DataTd->NextTDPointer);
+ Toggle ^= 1;
+ }
+ //
+ // HC will only update DataToggle, ErrorCount, ConditionCode
+ // CurrentBufferPointer & NextTD, so we only need to update
+ // them once we want to active them again
+ //
+ DataTd = HeadTd;
+ while (DataTd != NULL) {
+ if (DataTd->NextTDPointer == 0) {
+ OhciSetTDField (DataTd, TD_ERROR_CNT | TD_COND_CODE | TD_CURR_BUFFER_PTR | TD_NEXT_PTR, 0);
+ break;
+ }
+ OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ DataTd->NextTD = DataTd->NextTDPointer;
+ DataTd->CurrBufferPointer = DataTd->DataBuffer;
+ DataTd = (TD_DESCRIPTOR *)(UINTN)(DataTd->NextTDPointer);
+ }
+ //
+ // Active current Ed,Td
+ //
+ // HC will only update Halted, ToggleCarry & TDQueueHeadPointer,
+ // So we only need to update them once we want to active them again.
+ //
+ if ((Ed != NULL) && (DataTd != NULL)) {
+ Ed->Word2.TdHeadPointer = (UINT32)((UINTN)HeadTd>>4);
+ OhciSetEDField (Ed, ED_HALTED | ED_DTTOGGLE, 0);
+ Ed->Word0.Skip = 0;
+ }
+ }
+ } else {
+ if (PreEntry == NULL) {
+ Ohc->InterruptContextList = Entry->NextEntry;
+ }else{
+ PreEntry = Entry;
+ PreEntry->NextEntry = Entry->NextEntry;
+ }
+ OhciFreeInterruptContextEntry (Ohc, PreEntry);
+ gBS->RestoreTPL (OriginalTPL);
+ return ;
+ }
+ PreEntry = Entry;
+ Entry = Entry->NextEntry;
+ }
+ gBS->RestoreTPL (OriginalTPL);
+ return;
+}
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.h
new file mode 100644
index 0000000..3689407
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.h
@@ -0,0 +1,246 @@
+/** @file
+ This file contains the definination for host controller schedule routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#ifndef _OHCI_SCHED_H
+#define _OHCI_SCHED_H
+
+#include "Descriptor.h"
+
+#define HCCA_MEM_SIZE 256
+#define GRID_SIZE 16
+#define GRID_SHIFT 4
+
+typedef struct _INTERRUPT_CONTEXT_ENTRY {
+ UINT8 DeviceAddress;
+ UINT8 EndPointAddress;
+ ED_DESCRIPTOR *Ed;
+ TD_DESCRIPTOR *DataTd;
+ BOOLEAN IsSlowDevice;
+ UINT8 MaxPacketLength;
+ UINTN PollingInterval;
+ EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction;
+ VOID *Context;
+ BOOLEAN IsPeriodic;
+ VOID *Buffer;
+ UINTN DataLength;
+ VOID *UCBuffer;
+ VOID *UCBufferMapping;
+ UINT8 *Toggle;
+ struct _INTERRUPT_CONTEXT_ENTRY *NextEntry;
+} INTERRUPT_CONTEXT_ENTRY;
+
+typedef struct {
+ UINT32 ErrorCode;
+ UINT8 NextToggle;
+} OHCI_ED_RESULT;
+
+/**
+
+ Add an item of interrupt context
+
+ @param Ohc UHC private data
+ @param NewEntry New entry to add
+
+ @retval EFI_SUCCESS Item successfully added
+
+**/
+EFI_STATUS
+OhciAddInterruptContextEntry (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN INTERRUPT_CONTEXT_ENTRY *NewEntry
+ );
+
+/**
+
+ Free a interrupt context entry
+
+ @param Ohc UHC private data
+ @param Entry Pointer to an interrupt context entry
+
+ @retval EFI_SUCCESS Entry freed
+ @retval EFI_INVALID_PARAMETER Entry is NULL
+
+**/
+EFI_STATUS
+OhciFreeInterruptContextEntry (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN INTERRUPT_CONTEXT_ENTRY *Entry
+ );
+
+/**
+
+ Free entries match the device address and endpoint address
+
+ @Param Ohc UHC private date
+ @Param DeviceAddress Item to free must match this device address
+ @Param EndPointAddress Item to free must match this end point address
+ @Param DataToggle DataToggle for output
+
+ @retval EFI_SUCCESS Items match the requirement removed
+
+**/
+EFI_STATUS
+OhciFreeInterruptContext(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ OUT UINT8 *DataToggle
+ );
+
+
+/**
+
+ Convert Error code from OHCI format to EFI format
+
+ @Param ErrorCode ErrorCode in OHCI format
+
+ @retval ErrorCode in EFI format
+
+**/
+UINT32
+ConvertErrorCode (
+ IN UINT32 ErrorCode
+ );
+
+
+/**
+
+ Check TDs Results
+
+ @Param Ohc UHC private data
+ @Param Td TD_DESCRIPTOR
+ @Param Result Result to return
+
+ @retval TRUE means OK
+ @retval FLASE means Error or Short packet
+
+**/
+BOOLEAN
+OhciCheckTDsResults (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN TD_DESCRIPTOR *Td,
+ OUT UINT32 *Result
+ );
+/**
+
+ Check the task status on an ED
+
+ @Param Ed Pointer to the ED task that TD hooked on
+ @Param HeadTd TD header for current transaction
+
+ @retval Task Status Code
+
+**/
+
+UINT32
+CheckEDStatus (
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd,
+ OUT OHCI_ED_RESULT *EdResult
+ );
+/**
+
+ Check the task status
+
+ @Param Ohc UHC private data
+ @Param ListType Pipe type
+ @Param Ed Pointer to the ED task hooked on
+ @Param HeadTd Head of TD corresponding to the task
+ @Param ErrorCode return the ErrorCode
+
+ @retval EFI_SUCCESS Task done
+ @retval EFI_NOT_READY Task on processing
+ @retval EFI_DEVICE_ERROR Some error occured
+
+**/
+EFI_STATUS
+CheckIfDone (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN DESCRIPTOR_LIST_TYPE ListType,
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd,
+ OUT OHCI_ED_RESULT *EdResult
+ );
+
+/**
+
+ Convert TD condition code to Efi Status
+
+ @Param ConditionCode Condition code to convert
+
+ @retval EFI_SUCCESS No error occured
+ @retval EFI_NOT_READY TD still on processing
+ @retval EFI_DEVICE_ERROR Error occured in processing TD
+
+**/
+
+EFI_STATUS
+OhciTDConditionCodeToStatus (
+ IN UINT32 ConditionCode
+ );
+
+/**
+
+ Invoke callbacks hooked on done TDs
+
+ @Param Entry Interrupt transfer transaction information data structure
+ @Param Context Ohc private data
+
+**/
+
+VOID
+OhciInvokeInterruptCallBack(
+ IN INTERRUPT_CONTEXT_ENTRY *Entry,
+ IN UINT32 Result
+);
+
+
+/**
+
+ Timer to submit periodic interrupt transfer, and invoke callbacks hooked on done TDs
+
+ @param Event Event handle
+ @param Context Device private data
+
+**/
+
+VOID
+EFIAPI
+OhciHouseKeeper (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.c
new file mode 100644
index 0000000..592c2ee
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.c
@@ -0,0 +1,913 @@
+/** @file
+ This file contains URB request, each request is warpped in a
+ URB (Usb Request Block).
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#include "Ohci.h"
+
+
+/**
+
+ Create a TD
+
+ @Param Ohc UHC private data
+
+ @retval TD structure pointer
+
+**/
+TD_DESCRIPTOR *
+OhciCreateTD (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ TD_DESCRIPTOR *Td;
+
+ Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR));
+ if (Td == NULL) {
+ DEBUG ((EFI_D_INFO, "STV allocate TD fail !\r\n"));
+ return NULL;
+ }
+ Td->CurrBufferPointer = 0;
+ Td->NextTD = 0;
+ Td->BufferEndPointer = 0;
+ Td->NextTDPointer = 0;
+
+ return Td;
+}
+
+
+/**
+
+ Free a TD
+
+ @Param Ohc UHC private data
+ @Param Td Pointer to a TD to free
+
+ @retval EFI_SUCCESS TD freed
+
+**/
+EFI_STATUS
+OhciFreeTD (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN TD_DESCRIPTOR *Td
+ )
+{
+ if (Td == NULL) {
+ return EFI_SUCCESS;
+ }
+ UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Create a ED
+
+ @Param Ohc Device private data
+
+ @retval ED descriptor pointer
+
+**/
+ED_DESCRIPTOR *
+OhciCreateED (
+ USB_OHCI_HC_DEV *Ohc
+ )
+{
+ ED_DESCRIPTOR *Ed;
+ Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));
+ if (Ed == NULL) {
+ DEBUG ((EFI_D_INFO, "STV allocate ED fail !\r\n"));
+ return NULL;
+ }
+ Ed->Word0.Skip = 1;
+ Ed->TdTailPointer = 0;
+ Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (0);
+ Ed->NextED = 0;
+
+ return Ed;
+}
+
+/**
+
+ Free a ED
+
+ @Param Ohc UHC private data
+ @Param Ed Pointer to a ED to free
+
+ @retval EFI_SUCCESS ED freed
+
+**/
+
+EFI_STATUS
+OhciFreeED (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *Ed
+ )
+{
+ if (Ed == NULL) {
+ return EFI_SUCCESS;
+ }
+ UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Free ED
+
+ @Param Ohc Device private data
+ @Param Ed Pointer to a ED to free
+
+ @retval EFI_SUCCESS ED freed
+
+**/
+EFI_STATUS
+OhciFreeAllTDFromED (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *Ed
+ )
+{
+ TD_DESCRIPTOR *HeadTd;
+ TD_DESCRIPTOR *TailTd;
+ TD_DESCRIPTOR *Td;
+ TD_DESCRIPTOR *TempTd;
+
+ if (Ed == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);
+ TailTd = (TD_DESCRIPTOR *)(UINTN)(Ed->TdTailPointer);
+
+ Td = HeadTd;
+ while (Td != TailTd) {
+ TempTd = Td;
+ Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);
+ OhciFreeTD (Ohc, TempTd);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Find a working ED match the requirement
+
+ @Param EdHead Head of the ED list
+ @Param DeviceAddress Device address to search
+ @Param EndPointNum End point num to search
+ @Param EdDir ED Direction to search
+
+ @retval ED descriptor searched
+
+**/
+
+ED_DESCRIPTOR *
+OhciFindWorkingEd (
+ IN ED_DESCRIPTOR *EdHead,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointNum,
+ IN UINT8 EdDir
+ )
+{
+ ED_DESCRIPTOR *Ed;
+
+ for (Ed = EdHead; Ed != NULL; Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED)) {
+ if (Ed->Word2.Halted == 0 && Ed->Word0.Skip == 0 &&
+ Ed->Word0.FunctionAddress == DeviceAddress && Ed->Word0.EndPointNum == EndPointNum &&
+ Ed->Word0.Direction == EdDir) {
+ break;
+ }
+ }
+
+ return Ed;
+}
+
+
+/**
+
+ Initialize interrupt list.
+
+ @Param Ohc Device private data
+
+ @retval EFI_SUCCESS Initialization done
+
+**/
+EFI_STATUS
+OhciInitializeInterruptList (
+ USB_OHCI_HC_DEV *Ohc
+ )
+{
+ static UINT32 Leaf[32] = {0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17,
+ 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31};
+ ED_DESCRIPTOR **HccaInterruptTable;
+ UINTN Index;
+ UINTN Level;
+ UINTN Count;
+
+ HccaInterruptTable = Ohc->HccaMemoryBlock->HccaInterruptTable;
+
+ for (Index = 0; Index < 32; Index++) {
+ HccaInterruptTable[Index] = OhciCreateED (Ohc);
+ if (HccaInterruptTable[Index] == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ for (Index = 0; Index < 32; Index++) {
+ Ohc->IntervalList[0][Index] = HccaInterruptTable[Leaf[Index]];
+ }
+
+ Count = 32;
+ for (Level = 1; Level <= 5; Level++) {
+ Count = Count >> 1;
+
+ for (Index = 0; Index < Count; Index++) {
+ Ohc->IntervalList[Level][Index] = OhciCreateED (Ohc);
+ if (HccaInterruptTable[Index] == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Ohc->IntervalList[Level - 1][Index * 2]->NextED =
+ (UINT32)(UINTN)(Ohc->IntervalList[Level][Index]);
+ Ohc->IntervalList[Level - 1][Index * 2 + 1]->NextED =
+ (UINT32)(UINTN)(Ohc->IntervalList[Level][Index]);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Attach an ED
+
+ @Param Ed Ed to be attached
+ @Param NewEd Ed to attach
+
+ @retval EFI_SUCCESS NewEd attached to Ed
+ @retval EFI_INVALID_PARAMETER Ed is NULL
+
+**/
+EFI_STATUS
+OhciAttachED (
+ IN ED_DESCRIPTOR *Ed,
+ IN ED_DESCRIPTOR *NewEd
+ )
+{
+ ED_DESCRIPTOR *Temp;
+
+ if (Ed == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Ed->NextED == 0){
+ Ed->NextED = (UINT32)(UINTN)NewEd;
+ } else {
+ Temp = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
+ Ed->NextED = (UINT32)(UINTN)NewEd;
+ NewEd->NextED = (UINT32)(UINTN)Temp;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Count ED number on a ED chain
+
+ @Param Ed Head of the ED chain
+
+ @retval ED number on the chain
+
+**/
+
+UINTN
+CountEdNum (
+ IN ED_DESCRIPTOR *Ed
+ )
+{
+ UINTN Count;
+
+ Count = 0;
+
+ while (Ed) {
+ Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
+ Count++;
+ }
+
+ return Count;
+}
+
+/**
+
+ Find the minimal burn ED list on a specific depth level
+
+ @Param Ohc Device private data
+ @Param Depth Depth level
+
+ @retval ED list found
+
+**/
+
+ED_DESCRIPTOR *
+OhciFindMinInterruptEDList (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Depth
+ )
+{
+ UINTN EdNum;
+ UINTN MinEdNum;
+ ED_DESCRIPTOR *TempEd;
+ ED_DESCRIPTOR *HeadEd;
+ UINTN Index;
+
+ if (Depth > 5) {
+ return NULL;
+ }
+
+ MinEdNum = 0xFFFFFFFF;
+ TempEd = NULL;
+ for (Index = 0; Index < (UINTN)(32 >> Depth); Index++) {
+ HeadEd = Ohc->IntervalList[Depth][Index];
+ EdNum = CountEdNum (HeadEd);
+ if (EdNum < MinEdNum) {
+ MinEdNum = EdNum;
+ TempEd = HeadEd;
+ }
+ }
+
+ ASSERT (TempEd != NULL);
+
+ return TempEd;
+}
+
+
+/**
+
+ Attach an ED to an ED list
+
+ @Param OHC UHC private data
+ @Param ListType Type of the ED list
+ @Param Ed ED to attach
+ @Param EdList ED list to be attached
+
+ @retval EFI_SUCCESS ED attached to ED list
+
+**/
+ED_DESCRIPTOR *
+OhciAttachEDToList (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN DESCRIPTOR_LIST_TYPE ListType,
+ IN ED_DESCRIPTOR *Ed,
+ IN ED_DESCRIPTOR *EdList
+ )
+{
+ ED_DESCRIPTOR *HeadEd;
+
+ HeadEd = NULL;
+ switch(ListType) {
+ case CONTROL_LIST:
+ HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);
+ if (HeadEd == NULL) {
+ OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);
+ HeadEd = Ed;
+ } else {
+ OhciAttachED (HeadEd, Ed);
+ }
+ break;
+
+ case BULK_LIST:
+ HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);
+ if (HeadEd == NULL) {
+ OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);
+ HeadEd = Ed;
+ } else {
+ OhciAttachED (HeadEd, Ed);
+ }
+ break;
+
+ case INTERRUPT_LIST:
+ OhciAttachED (EdList, Ed);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return HeadEd;
+}
+
+/**
+
+ Remove interrupt EDs that match requirement
+
+ @Param Ohc UHC private data
+ @Param IntEd The address of Interrupt endpoint
+
+ @retval EFI_SUCCESS EDs match requirement removed
+
+**/
+
+EFI_STATUS
+OhciFreeInterruptEdByEd (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *IntEd
+ )
+{
+ ED_DESCRIPTOR *Ed;
+ ED_DESCRIPTOR *TempEd;
+ UINTN Index;
+
+ if (IntEd == NULL)
+ return EFI_SUCCESS;
+
+ for (Index = 0; Index < 32; Index++) {
+ Ed = Ohc->HccaMemoryBlock->HccaInterruptTable[Index];
+ if (Ed == NULL) {
+ continue;
+ }
+ while (Ed->NextED != 0) {
+ if (Ed->NextED == (UINT32)(UINTN)IntEd ) {
+ TempEd = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
+ Ed->NextED = ((ED_DESCRIPTOR *)(UINTN)(Ed->NextED))->NextED;
+ OhciFreeED (Ohc, TempEd);
+ } else {
+ Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Remove interrupt EDs that match requirement
+
+ @Param Ohc UHC private data
+ @Param FunctionAddress Requirement on function address
+ @Param EndPointNum Requirement on end point number
+
+ @retval EFI_SUCCESS EDs match requirement removed
+
+**/
+EFI_STATUS
+OhciFreeInterruptEdByAddr (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT8 FunctionAddress,
+ IN UINT8 EndPointNum
+ )
+{
+ ED_DESCRIPTOR *Ed;
+ ED_DESCRIPTOR *TempEd;
+ UINTN Index;
+
+ for (Index = 0; Index < 32; Index++) {
+ Ed = Ohc->HccaMemoryBlock->HccaInterruptTable[Index];
+ if (Ed == NULL) {
+ continue;
+ }
+
+ while (Ed->NextED != 0) {
+ if (((ED_DESCRIPTOR *)(UINTN)(Ed->NextED))->Word0.FunctionAddress == FunctionAddress &&
+ ((ED_DESCRIPTOR *)(UINTN)(Ed->NextED))->Word0.EndPointNum == EndPointNum) {
+ TempEd = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
+ Ed->NextED = ((ED_DESCRIPTOR *)(UINTN)(Ed->NextED))->NextED;
+ OhciFreeED (Ohc, TempEd);
+ } else {
+ Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Link Td2 to the end of Td1
+
+ @Param Td1 TD to be linked
+ @Param Td2 TD to link
+
+ @retval EFI_SUCCESS TD successfully linked
+ @retval EFI_INVALID_PARAMETER Td1 is NULL
+
+**/
+EFI_STATUS
+OhciLinkTD (
+ IN TD_DESCRIPTOR *Td1,
+ IN TD_DESCRIPTOR *Td2
+ )
+{
+ TD_DESCRIPTOR *TempTd;
+
+ if (Td1 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Td1 == Td2) {
+ return EFI_SUCCESS;
+ }
+
+ TempTd = Td1;
+ while (TempTd->NextTD != 0) {
+ TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD);
+ }
+
+ TempTd->NextTD = (UINT32)(UINTN)Td2;
+ TempTd->NextTDPointer = (UINT32)(UINTN)Td2;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Attach TD list to ED
+
+ @Param Ed ED which TD list attach on
+ @Param HeadTd Head of the TD list to attach
+
+ @retval EFI_SUCCESS TD list attached on the ED
+
+**/
+EFI_STATUS
+OhciAttachTDListToED (
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd
+ )
+{
+ TD_DESCRIPTOR *TempTd;
+
+ TempTd = TD_PTR (Ed->Word2.TdHeadPointer);
+
+ if (TempTd != NULL) {
+ while (TempTd->NextTD != 0) {
+ TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD);
+ }
+ TempTd->NextTD = (UINT32)(UINTN)HeadTd;
+ TempTd->NextTDPointer = (UINT32)(UINTN)HeadTd;
+ } else {
+ Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32)(UINTN)HeadTd);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Set value to ED specific field
+
+ @Param Ed ED to be set
+ @Param Field Field to be set
+ @Param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetEDField (
+ IN ED_DESCRIPTOR *Ed,
+ IN UINT32 Field,
+ IN UINT32 Value
+ )
+{
+ if (Field & ED_FUNC_ADD) {
+ Ed->Word0.FunctionAddress = Value;
+ }
+ if (Field & ED_ENDPT_NUM) {
+ Ed->Word0.EndPointNum = Value;
+ }
+ if (Field & ED_DIR) {
+ Ed->Word0.Direction = Value;
+ }
+ if (Field & ED_SPEED) {
+ Ed->Word0.Speed = Value;
+ }
+ if (Field & ED_SKIP) {
+ Ed->Word0.Skip = Value;
+ }
+ if (Field & ED_FORMAT) {
+ Ed->Word0.Format = Value;
+ }
+ if (Field & ED_MAX_PACKET) {
+ Ed->Word0.MaxPacketSize = Value;
+ }
+ if (Field & ED_PDATA) {
+ Ed->Word0.FreeSpace = Value;
+ }
+ if (Field & ED_ZERO) {
+ Ed->Word2.Zero = Value;
+ }
+ if (Field & ED_TDTAIL_PTR) {
+ Ed->TdTailPointer = (UINT32)(UINTN) Value;
+ }
+
+ if (Field & ED_HALTED) {
+ Ed->Word2.Halted = Value;
+ }
+ if (Field & ED_DTTOGGLE) {
+ Ed->Word2.ToggleCarry = Value;
+ }
+ if (Field & ED_TDHEAD_PTR) {
+ Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);
+ }
+
+ if (Field & ED_NEXT_EDPTR) {
+ Ed->NextED = (UINT32)(UINTN) Value;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Get value from an ED's specific field
+
+ @Param Ed ED pointer
+ @Param Field Field to get value from
+
+ @retval Value of the field
+
+**/
+UINT32
+OhciGetEDField (
+ IN ED_DESCRIPTOR *Ed,
+ IN UINT32 Field
+ )
+{
+ switch (Field) {
+ case ED_FUNC_ADD:
+ return Ed->Word0.FunctionAddress;
+ break;
+ case ED_ENDPT_NUM:
+ return Ed->Word0.EndPointNum;
+ break;
+ case ED_DIR:
+ return Ed->Word0.Direction;
+ break;
+ case ED_SPEED:
+ return Ed->Word0.Speed;
+ break;
+ case ED_SKIP:
+ return Ed->Word0.Skip;
+ break;
+ case ED_FORMAT:
+ return Ed->Word0.Format;
+ break;
+ case ED_MAX_PACKET:
+ return Ed->Word0.MaxPacketSize;
+ break;
+
+ case ED_TDTAIL_PTR:
+ return (UINT32)(UINTN) Ed->TdTailPointer;
+ break;
+
+ case ED_HALTED:
+ return Ed->Word2.Halted;
+ break;
+
+ case ED_DTTOGGLE:
+ return Ed->Word2.ToggleCarry;
+ break;
+
+ case ED_TDHEAD_PTR:
+ return Ed->Word2.TdHeadPointer << 4;
+ break;
+
+ case ED_NEXT_EDPTR:
+ return (UINT32)(UINTN) Ed->NextED;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+
+/**
+
+ Set value to TD specific field
+
+ @Param Td TD to be set
+ @Param Field Field to be set
+ @Param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetTDField (
+ IN TD_DESCRIPTOR *Td,
+ IN UINT32 Field,
+ IN UINT32 Value
+ )
+{
+ if (Field & TD_PDATA) {
+ Td->Word0.Reserved = Value;
+ }
+ if (Field & TD_BUFFER_ROUND) {
+ Td->Word0.BufferRounding = Value;
+ }
+ if (Field & TD_DIR_PID) {
+ Td->Word0.DirPID = Value;
+ }
+ if (Field & TD_DELAY_INT) {
+ Td->Word0.DelayInterrupt = Value;
+ }
+ if (Field & TD_DT_TOGGLE) {
+ Td->Word0.DataToggle = Value | 0x2;
+ }
+ if (Field & TD_ERROR_CNT) {
+ Td->Word0.ErrorCount = Value;
+ }
+ if (Field & TD_COND_CODE) {
+ Td->Word0.ConditionCode = Value;
+ }
+
+ if (Field & TD_CURR_BUFFER_PTR) {
+ Td->CurrBufferPointer = (UINT32)(UINTN) Value;
+ }
+
+
+ if (Field & TD_NEXT_PTR) {
+ Td->NextTD = (UINT32)(UINTN) Value;
+ }
+
+ if (Field & TD_BUFFER_END_PTR) {
+ Td->BufferEndPointer = (UINT32)(UINTN) Value;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Get value from ED specific field
+
+ @Param Td TD pointer
+ @Param Field Field to get value from
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetTDField (
+ IN TD_DESCRIPTOR *Td,
+ IN UINT32 Field
+ )
+{
+ switch (Field){
+ case TD_BUFFER_ROUND:
+ return Td->Word0.BufferRounding;
+ break;
+ case TD_DIR_PID:
+ return Td->Word0.DirPID;
+ break;
+ case TD_DELAY_INT:
+ return Td->Word0.DelayInterrupt;
+ break;
+ case TD_DT_TOGGLE:
+ return Td->Word0.DataToggle;
+ break;
+ case TD_ERROR_CNT:
+ return Td->Word0.ErrorCount;
+ break;
+ case TD_COND_CODE:
+ return Td->Word0.ConditionCode;
+ break;
+ case TD_CURR_BUFFER_PTR:
+ return (UINT32)(UINTN) Td->CurrBufferPointer;
+ break;
+
+ case TD_NEXT_PTR:
+ return (UINT32)(UINTN) Td->NextTD;
+ break;
+
+ case TD_BUFFER_END_PTR:
+ return (UINT32)(UINTN) Td->BufferEndPointer;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Free the Ed,Td,buffer that were created during transferring
+
+ @Param Ohc Device private data
+**/
+
+VOID
+OhciFreeDynamicIntMemory(
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ INTERRUPT_CONTEXT_ENTRY *Entry;
+ if (Ohc != NULL) {
+ while (Ohc->InterruptContextList != NULL) {
+ Entry = Ohc->InterruptContextList;
+ OhciFreeInterruptEdByEd (Ohc, Entry->Ed);
+ OhciFreeInterruptContextEntry (Ohc, Entry);
+ Ohc->InterruptContextList = Ohc->InterruptContextList->NextEntry;
+ }
+ }
+}
+/**
+
+ Free the Ed that were initilized during driver was starting,
+ those memory were used as interrupt ED head
+
+ @Param Ohc Device private data
+
+
+**/
+VOID
+OhciFreeFixedIntMemory (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ static UINT32 Leaf[] = {32,16,8,4,2,1};
+ UINTN Index;
+ UINTN Level;
+
+ for (Level = 0; Level < 6; Level++) {
+ for (Index = 0; Index < Leaf[Index]; Index++) {
+ if (Ohc->IntervalList[Level][Index] != NULL) {
+ UsbHcFreeMem(Ohc->MemPool, Ohc->IntervalList[Level][Index], sizeof(ED_DESCRIPTOR));
+ }
+ }
+ }
+}
+/**
+
+ Release all OHCI used memory when OHCI going to quit
+
+ @Param Ohc Device private data
+
+ @retval EFI_SUCCESS Memory released
+
+**/
+
+EFI_STATUS
+OhciFreeIntTransferMemory (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ //
+ // Free the Ed,Td,buffer that were created during transferring
+ //
+ OhciFreeDynamicIntMemory (Ohc);
+ //
+ // Free the Ed that were initilized during driver was starting
+ //
+ OhciFreeFixedIntMemory (Ohc);
+ return EFI_SUCCESS;
+}
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.h
new file mode 100644
index 0000000..86055cb
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.h
@@ -0,0 +1,411 @@
+/** @file
+ Provides some data struct used by OHCI controller driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#ifndef _OHCI_URB_H
+#define _OHCI_URB_H
+
+#include "Descriptor.h"
+
+
+//
+// Func List
+//
+
+
+/**
+
+ Create a TD
+
+ @Param Ohc UHC private data
+
+ @retval TD structure pointer
+
+**/
+TD_DESCRIPTOR *
+OhciCreateTD (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+
+/**
+
+ Free a TD
+
+ @Param Ohc UHC private data
+ @Param Td Pointer to a TD to free
+
+ @retval EFI_SUCCESS TD freed
+
+**/
+EFI_STATUS
+OhciFreeTD (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN TD_DESCRIPTOR *Td
+ );
+
+/**
+
+ Create a ED
+
+ @Param Ohc Device private data
+
+ @retval ED descriptor pointer
+
+**/
+ED_DESCRIPTOR *
+OhciCreateED (
+ USB_OHCI_HC_DEV *Ohc
+ );
+
+
+/**
+
+ Free a ED
+
+ @Param Ohc UHC private data
+ @Param Ed Pointer to a ED to free
+
+ @retval EFI_SUCCESS ED freed
+
+**/
+
+EFI_STATUS
+OhciFreeED (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *Ed
+ );
+
+/**
+
+ Free ED
+
+ @Param Ohc Device private data
+ @Param Ed Pointer to a ED to free
+
+ @retval EFI_SUCCESS ED freed
+
+**/
+EFI_STATUS
+OhciFreeAllTDFromED (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *Ed
+ );
+
+/**
+
+ Find a working ED match the requirement
+
+ @Param EdHead Head of the ED list
+ @Param DeviceAddress Device address to search
+ @Param EndPointNum End point num to search
+ @Param EdDir ED Direction to search
+
+ @retval ED descriptor searched
+
+**/
+
+ED_DESCRIPTOR *
+OhciFindWorkingEd (
+ IN ED_DESCRIPTOR *EdHead,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointNum,
+ IN UINT8 EdDir
+ );
+
+
+/**
+
+ Initialize interrupt list.
+
+ @Param Ohc Device private data
+
+ @retval EFI_SUCCESS Initialization done
+
+**/
+EFI_STATUS
+OhciInitializeInterruptList (
+ USB_OHCI_HC_DEV *Ohc
+ );
+
+/**
+
+ Attach an ED
+
+ @Param Ed Ed to be attached
+ @Param NewEd Ed to attach
+
+ @retval EFI_SUCCESS NewEd attached to Ed
+ @retval EFI_INVALID_PARAMETER Ed is NULL
+
+**/
+EFI_STATUS
+OhciAttachED (
+ IN ED_DESCRIPTOR *Ed,
+ IN ED_DESCRIPTOR *NewEd
+ );
+
+/**
+
+ Count ED number on a ED chain
+
+ @Param Ed Head of the ED chain
+
+ @retval ED number on the chain
+
+**/
+
+UINTN
+CountEdNum (
+ IN ED_DESCRIPTOR *Ed
+ );
+
+/**
+
+ Find the minimal burn ED list on a specific depth level
+
+ @Param Ohc Device private data
+ @Param Depth Depth level
+
+ @retval ED list found
+
+**/
+
+ED_DESCRIPTOR *
+OhciFindMinInterruptEDList (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Depth
+ );
+
+/**
+
+ Attach an ED to an ED list
+
+ @Param OHC UHC private data
+ @Param ListType Type of the ED list
+ @Param Ed ED to attach
+ @Param EdList ED list to be attached
+
+ @retval EFI_SUCCESS ED attached to ED list
+
+**/
+ED_DESCRIPTOR *
+OhciAttachEDToList (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN DESCRIPTOR_LIST_TYPE ListType,
+ IN ED_DESCRIPTOR *Ed,
+ IN ED_DESCRIPTOR *EdList
+ );
+
+/**
+
+ Remove interrupt EDs that match requirement
+
+ @Param Ohc UHC private data
+ @Param IntEd The address of Interrupt endpoint
+
+ @retval EFI_SUCCESS EDs match requirement removed
+
+**/
+
+EFI_STATUS
+OhciFreeInterruptEdByEd (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *IntEd
+ );
+
+/**
+
+ Remove interrupt EDs that match requirement
+
+ @Param Ohc UHC private data
+ @Param FunctionAddress Requirement on function address
+ @Param EndPointNum Requirement on end point number
+
+ @retval EFI_SUCCESS EDs match requirement removed
+
+**/
+EFI_STATUS
+OhciFreeInterruptEdByAddr (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT8 FunctionAddress,
+ IN UINT8 EndPointNum
+ );
+
+
+/**
+
+ Link Td2 to the end of Td1
+
+ @Param Td1 TD to be linked
+ @Param Td2 TD to link
+
+ @retval EFI_SUCCESS TD successfully linked
+ @retval EFI_INVALID_PARAMETER Td1 is NULL
+
+**/
+EFI_STATUS
+OhciLinkTD (
+ IN TD_DESCRIPTOR *Td1,
+ IN TD_DESCRIPTOR *Td2
+ );
+
+
+/**
+
+ Attach TD list to ED
+
+ @Param Ed ED which TD list attach on
+ @Param HeadTd Head of the TD list to attach
+
+ @retval EFI_SUCCESS TD list attached on the ED
+
+**/
+EFI_STATUS
+OhciAttachTDListToED (
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd
+ );
+
+
+/**
+
+ Set value to ED specific field
+
+ @Param Ed ED to be set
+ @Param Field Field to be set
+ @Param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetEDField (
+ IN ED_DESCRIPTOR *Ed,
+ IN UINT32 Field,
+ IN UINT32 Value
+ );
+
+
+/**
+
+ Get value from an ED's specific field
+
+ @Param Ed ED pointer
+ @Param Field Field to get value from
+
+ @retval Value of the field
+
+**/
+UINT32
+OhciGetEDField (
+ IN ED_DESCRIPTOR *Ed,
+ IN UINT32 Field
+ );
+
+
+/**
+
+ Set value to TD specific field
+
+ @Param Td TD to be set
+ @Param Field Field to be set
+ @Param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetTDField (
+ IN TD_DESCRIPTOR *Td,
+ IN UINT32 Field,
+ IN UINT32 Value
+ );
+
+
+/**
+
+ Get value from ED specific field
+
+ @Param Td TD pointer
+ @Param Field Field to get value from
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetTDField (
+ IN TD_DESCRIPTOR *Td,
+ IN UINT32 Field
+ );
+/**
+
+ Free the Ed,Td,buffer that were created during transferring
+
+ @Param Ohc Device private data
+**/
+
+VOID
+OhciFreeDynamicIntMemory(
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+
+/**
+
+ Free the Ed that were initilized during driver was starting,
+ those memory were used as interrupt ED head
+
+ @Param Ohc Device private data
+
+
+**/
+VOID
+OhciFreeFixedIntMemory (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+/**
+
+ Release all OHCI used memory when OHCI going to quit
+
+ @Param Ohc Device private data
+
+ @retval EFI_SUCCESS Memory released
+
+**/
+
+EFI_STATUS
+OhciFreeIntTransferMemory (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.c
new file mode 100644
index 0000000..08fb0db
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.c
@@ -0,0 +1,584 @@
+/** @file
+ Routine procedures for memory allocate/free.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "Ohci.h"
+
+
+/**
+ Allocate a block of memory to be used by the buffer pool.
+
+ @param Pool The buffer pool to allocate memory for.
+ @param Pages How many pages to allocate.
+
+ @return The allocated memory block or NULL if failed.
+
+**/
+USBHC_MEM_BLOCK *
+UsbHcAllocMemBlock (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Pages
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ VOID *BufHost;
+ VOID *Mapping;
+ EFI_PHYSICAL_ADDRESS MappedAddr;
+ UINTN Bytes;
+ EFI_STATUS Status;
+
+ PciIo = Pool->PciIo;
+
+ Block = AllocateZeroPool (sizeof (USBHC_MEM_BLOCK));
+ if (Block == NULL) {
+ return NULL;
+ }
+
+ //
+ // each bit in the bit array represents USBHC_MEM_UNIT
+ // bytes of memory in the memory block.
+ //
+ ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
+
+ Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
+ Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
+ Block->Bits = AllocateZeroPool (Block->BitsLen);
+
+ if (Block->Bits == NULL) {
+ gBS->FreePool (Block);
+ return NULL;
+ }
+
+ //
+ // Allocate the number of Pages of memory, then map it for
+ // bus master read and write.
+ //
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ &BufHost,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto FREE_BITARRAY;
+ }
+
+ Bytes = EFI_PAGES_TO_SIZE (Pages);
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ BufHost,
+ &Bytes,
+ &MappedAddr,
+ &Mapping
+ );
+
+ if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) {
+ goto FREE_BUFFER;
+ }
+
+ //
+ // Check whether the data structure used by the host controller
+ // should be restricted into the same 4G
+ //
+ if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {
+ PciIo->Unmap (PciIo, Mapping);
+ goto FREE_BUFFER;
+ }
+
+ Block->BufHost = BufHost;
+ Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
+ Block->Mapping = Mapping;
+
+ return Block;
+
+FREE_BUFFER:
+ PciIo->FreeBuffer (PciIo, Pages, BufHost);
+
+FREE_BITARRAY:
+ gBS->FreePool (Block->Bits);
+ gBS->FreePool (Block);
+ return NULL;
+}
+
+
+/**
+ Free the memory block from the memory pool.
+
+ @param Pool The memory pool to free the block from.
+ @param Block The memory block to free.
+
+**/
+VOID
+UsbHcFreeMemBlock (
+ IN USBHC_MEM_POOL *Pool,
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ ASSERT ((Pool != NULL) && (Block != NULL));
+
+ PciIo = Pool->PciIo;
+
+ //
+ // Unmap the common buffer then free the structures
+ //
+ PciIo->Unmap (PciIo, Block->Mapping);
+ PciIo->FreeBuffer (PciIo, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost);
+
+ gBS->FreePool (Block->Bits);
+ gBS->FreePool (Block);
+}
+
+
+/**
+ Alloc some memory from the block.
+
+ @param Block The memory block to allocate memory from.
+ @param Units Number of memory units to allocate.
+
+ @return The pointer to the allocated memory. If couldn't allocate the needed memory,
+ the return value is NULL.
+
+**/
+VOID *
+UsbHcAllocMemFromBlock (
+ IN USBHC_MEM_BLOCK *Block,
+ IN UINTN Units
+ )
+{
+ UINTN Byte;
+ UINT8 Bit;
+ UINTN StartByte;
+ UINT8 StartBit;
+ UINTN Available;
+ UINTN Count;
+
+ ASSERT ((Block != 0) && (Units != 0));
+
+ StartByte = 0;
+ StartBit = 0;
+ Available = 0;
+
+ for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
+ //
+ // If current bit is zero, the corresponding memory unit is
+ // available, otherwise we need to restart our searching.
+ // Available counts the consective number of zero bit.
+ //
+ if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
+ Available++;
+
+ if (Available >= Units) {
+ break;
+ }
+
+ NEXT_BIT (Byte, Bit);
+
+ } else {
+ NEXT_BIT (Byte, Bit);
+
+ Available = 0;
+ StartByte = Byte;
+ StartBit = Bit;
+ }
+ }
+
+ if (Available < Units) {
+ return NULL;
+ }
+
+ //
+ // Mark the memory as allocated
+ //
+ Byte = StartByte;
+ Bit = StartBit;
+
+ for (Count = 0; Count < Units; Count++) {
+ ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
+
+ Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | USB_HC_BIT (Bit));
+ NEXT_BIT (Byte, Bit);
+ }
+
+ return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
+}
+
+/**
+ Calculate the corresponding pci bus address according to the Mem parameter.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The pointer to host memory.
+ @param Size The size of the memory region.
+
+ @return the pci memory address
+**/
+EFI_PHYSICAL_ADDRESS
+UsbHcGetPciAddressForHostMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ UINTN AllocSize;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ UINTN Offset;
+
+ Head = Pool->Head;
+ AllocSize = USBHC_MEM_ROUND (Size);
+
+ if (Mem == NULL) {
+ return 0;
+ }
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ //
+ // scan the memory block list for the memory block that
+ // completely contains the allocated memory.
+ //
+ if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {
+ break;
+ }
+ }
+
+ ASSERT ((Block != NULL));
+ //
+ // calculate the pci memory address for host memory address.
+ //
+ Offset = (UINT8 *)Mem - Block->BufHost;
+ PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset);
+ return PhyAddr;
+}
+
+
+/**
+ Insert the memory block to the pool's list of the blocks.
+
+ @param Head The head of the memory pool's block list.
+ @param Block The memory block to insert.
+
+**/
+VOID
+UsbHcInsertMemBlockToPool (
+ IN USBHC_MEM_BLOCK *Head,
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ ASSERT ((Head != NULL) && (Block != NULL));
+ Block->Next = Head->Next;
+ Head->Next = Block;
+}
+
+
+/**
+ Is the memory block empty?
+
+ @param Block The memory block to check.
+
+ @retval TRUE The memory block is empty.
+ @retval FALSE The memory block isn't empty.
+
+**/
+BOOLEAN
+UsbHcIsMemBlockEmpty (
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < Block->BitsLen; Index++) {
+ if (Block->Bits[Index] != 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Unlink the memory block from the pool's list.
+
+ @param Head The block list head of the memory's pool.
+ @param BlockToUnlink The memory block to unlink.
+
+**/
+VOID
+UsbHcUnlinkMemBlock (
+ IN USBHC_MEM_BLOCK *Head,
+ IN USBHC_MEM_BLOCK *BlockToUnlink
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+
+ ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ if (Block->Next == BlockToUnlink) {
+ Block->Next = BlockToUnlink->Next;
+ BlockToUnlink->Next = NULL;
+ break;
+ }
+ }
+}
+
+
+/**
+ Initialize the memory management pool for the host controller.
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param Check4G Whether the host controller requires allocated memory
+ from one 4G address space.
+ @param Which4G The 4G memory area each memory allocated should be from.
+
+ @retval EFI_SUCCESS The memory pool is initialized.
+ @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
+
+**/
+USBHC_MEM_POOL *
+UsbHcInitMemPool (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN BOOLEAN Check4G,
+ IN UINT32 Which4G
+ )
+{
+ USBHC_MEM_POOL *Pool;
+
+ Pool = AllocatePool (sizeof (USBHC_MEM_POOL));
+
+ if (Pool == NULL) {
+ return Pool;
+ }
+
+ Pool->PciIo = PciIo;
+ Pool->Check4G = Check4G;
+ Pool->Which4G = Which4G;
+ Pool->Head = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);
+
+ if (Pool->Head == NULL) {
+ gBS->FreePool (Pool);
+ Pool = NULL;
+ }
+
+ return Pool;
+}
+
+
+/**
+ Release the memory management pool.
+
+ @param Pool The USB memory pool to free.
+
+ @retval EFI_SUCCESS The memory pool is freed.
+ @retval EFI_DEVICE_ERROR Failed to free the memory pool.
+
+**/
+EFI_STATUS
+UsbHcFreeMemPool (
+ IN USBHC_MEM_POOL *Pool
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+
+ ASSERT (Pool->Head != NULL);
+
+ //
+ // Unlink all the memory blocks from the pool, then free them.
+ // UsbHcUnlinkMemBlock can't be used to unlink and free the
+ // first block.
+ //
+ for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
+ UsbHcUnlinkMemBlock (Pool->Head, Block);
+ UsbHcFreeMemBlock (Pool, Block);
+ }
+
+ UsbHcFreeMemBlock (Pool, Pool->Head);
+ gBS->FreePool (Pool);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Allocate some memory from the host controller's memory pool
+ which can be used to communicate with host controller.
+
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+
+ @return The allocated memory or NULL.
+
+**/
+VOID *
+UsbHcAllocateMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ USBHC_MEM_BLOCK *NewBlock;
+ VOID *Mem;
+ UINTN AllocSize;
+ UINTN Pages;
+
+ Mem = NULL;
+ AllocSize = USBHC_MEM_ROUND (Size);
+ Head = Pool->Head;
+ ASSERT (Head != NULL);
+
+ //
+ // First check whether current memory blocks can satisfy the allocation.
+ //
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
+
+ if (Mem != NULL) {
+ ZeroMem (Mem, Size);
+ break;
+ }
+ }
+
+ if (Mem != NULL) {
+ return Mem;
+ }
+
+ //
+ // Create a new memory block if there is not enough memory
+ // in the pool. If the allocation size is larger than the
+ // default page number, just allocate a large enough memory
+ // block. Otherwise allocate default pages.
+ //
+ if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
+ Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
+ } else {
+ Pages = USBHC_MEM_DEFAULT_PAGES;
+ }
+
+ NewBlock = UsbHcAllocMemBlock (Pool, Pages);
+
+ if (NewBlock == NULL) {
+ DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));
+ return NULL;
+ }
+
+ //
+ // Add the new memory block to the pool, then allocate memory from it
+ //
+ UsbHcInsertMemBlockToPool (Head, NewBlock);
+ Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
+
+ if (Mem != NULL) {
+ ZeroMem (Mem, Size);
+ }
+
+ return Mem;
+}
+
+
+/**
+ Free the allocated memory back to the memory pool.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The memory to free.
+ @param Size The size of the memory to free.
+
+**/
+VOID
+UsbHcFreeMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ UINT8 *ToFree;
+ UINTN AllocSize;
+ UINTN Byte;
+ UINTN Bit;
+ UINTN Count;
+
+ Head = Pool->Head;
+ AllocSize = USBHC_MEM_ROUND (Size);
+ ToFree = (UINT8 *) Mem;
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ //
+ // scan the memory block list for the memory block that
+ // completely contains the memory to free.
+ //
+ if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {
+ //
+ // compute the start byte and bit in the bit array
+ //
+ Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;
+ Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;
+
+ //
+ // reset associated bits in bit arry
+ //
+ for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
+ ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
+
+ Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
+ NEXT_BIT (Byte, Bit);
+ }
+
+ break;
+ }
+ }
+
+ //
+ // If Block == NULL, it means that the current memory isn't
+ // in the host controller's pool. This is critical because
+ // the caller has passed in a wrong memory point
+ //
+ ASSERT (Block != NULL);
+
+ //
+ // Release the current memory block if it is empty and not the head
+ //
+ if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
+ UsbHcUnlinkMemBlock (Head, Block);
+ UsbHcFreeMemBlock (Pool, Block);
+ }
+
+ return ;
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.h
new file mode 100644
index 0000000..273c574
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.h
@@ -0,0 +1,176 @@
+/** @file
+ This file contains the definination for host controller memory
+ management routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _USB_HC_MEM_H_
+#define _USB_HC_MEM_H_
+
+#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
+
+#define USB_HC_BIT_IS_SET(Data, Bit) \
+ ((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
+
+#define USB_HC_HIGH_32BIT(Addr64) \
+ ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
+
+typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
+struct _USBHC_MEM_BLOCK {
+ UINT8 *Bits; // Bit array to record which unit is allocated
+ UINTN BitsLen;
+ UINT8 *Buf;
+ UINT8 *BufHost;
+ UINTN BufLen; // Memory size in bytes
+ VOID *Mapping;
+ USBHC_MEM_BLOCK *Next;
+};
+
+//
+// USBHC_MEM_POOL is used to manage the memory used by USB
+// host controller. EHCI requires the control memory and transfer
+// data to be on the same 4G memory.
+//
+typedef struct _USBHC_MEM_POOL {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ BOOLEAN Check4G;
+ UINT32 Which4G;
+ USBHC_MEM_BLOCK *Head;
+} USBHC_MEM_POOL;
+
+//
+// Memory allocation unit, must be 2^n, n>4
+//
+#define USBHC_MEM_UNIT 64
+
+#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
+#define USBHC_MEM_DEFAULT_PAGES 16
+
+#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
+
+//
+// Advance the byte and bit to the next bit, adjust byte accordingly.
+//
+#define NEXT_BIT(Byte, Bit) \
+ do { \
+ (Bit)++; \
+ if ((Bit) > 7) { \
+ (Byte)++; \
+ (Bit) = 0; \
+ } \
+ } while (0)
+
+
+
+/**
+ Initialize the memory management pool for the host controller.
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param Check4G Whether the host controller requires allocated memory
+ from one 4G address space.
+ @param Which4G The 4G memory area each memory allocated should be from.
+
+ @retval EFI_SUCCESS The memory pool is initialized.
+ @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
+
+**/
+USBHC_MEM_POOL *
+UsbHcInitMemPool (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN BOOLEAN Check4G,
+ IN UINT32 Which4G
+ );
+
+
+/**
+ Release the memory management pool.
+
+ @param Pool The USB memory pool to free.
+
+ @retval EFI_SUCCESS The memory pool is freed.
+ @retval EFI_DEVICE_ERROR Failed to free the memory pool.
+
+**/
+EFI_STATUS
+UsbHcFreeMemPool (
+ IN USBHC_MEM_POOL *Pool
+ );
+
+
+/**
+ Allocate some memory from the host controller's memory pool
+ which can be used to communicate with host controller.
+
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+
+ @return The allocated memory or NULL.
+
+**/
+VOID *
+UsbHcAllocateMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Size
+ );
+
+
+/**
+ Free the allocated memory back to the memory pool.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The memory to free.
+ @param Size The size of the memory to free.
+
+**/
+VOID
+UsbHcFreeMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ );
+
+/**
+ Calculate the corresponding pci bus address according to the Mem parameter.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The pointer to host memory.
+ @param Size The size of the memory region.
+
+ @return the pci memory address
+**/
+EFI_PHYSICAL_ADDRESS
+UsbHcGetPciAddressForHostMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/Descriptor.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/Descriptor.h
new file mode 100644
index 0000000..affff75
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/Descriptor.h
@@ -0,0 +1,155 @@
+/** @file
+ This file contains the descriptor definination of OHCI spec
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#ifndef _DESCRIPTOR_H
+#define _DESCRIPTOR_H
+
+#define ED_FUNC_ADD 0x0001
+#define ED_ENDPT_NUM 0x0002
+#define ED_DIR 0x0004
+#define ED_SPEED 0x0008
+#define ED_SKIP 0x0010
+#define ED_FORMAT 0x0020
+#define ED_MAX_PACKET 0x0040
+#define ED_TDTAIL_PTR 0x0080
+#define ED_HALTED 0x0100
+#define ED_DTTOGGLE 0x0200
+#define ED_TDHEAD_PTR 0x0400
+#define ED_NEXT_EDPTR 0x0800
+#define ED_PDATA 0x1000
+#define ED_ZERO 0x2000
+
+#define TD_BUFFER_ROUND 0x0001
+#define TD_DIR_PID 0x0002
+#define TD_DELAY_INT 0x0004
+#define TD_DT_TOGGLE 0x0008
+#define TD_ERROR_CNT 0x0010
+#define TD_COND_CODE 0x0020
+#define TD_CURR_BUFFER_PTR 0x0040
+#define TD_NEXT_PTR 0x0080
+#define TD_BUFFER_END_PTR 0x0100
+#define TD_PDATA 0x0200
+
+#define ED_FROM_TD_DIR 0x0
+#define ED_OUT_DIR 0x1
+#define ED_IN_DIR 0x2
+#define ED_FROM_TD_ALSO_DIR 0x3
+
+#define TD_SETUP_PID 0x00
+#define TD_OUT_PID 0x01
+#define TD_IN_PID 0x02
+#define TD_NODATA_PID 0x03
+
+#define HI_SPEED 0
+#define LO_SPEED 1
+
+#define TD_NO_ERROR 0x00
+#define TD_CRC_ERROR 0x01
+#define TD_BITSTUFFING_ERROR 0x02
+#define TD_TOGGLE_ERROR 0x03
+#define TD_DEVICE_STALL 0x04
+#define TD_NO_RESPONSE 0x05
+#define TD_PIDCHK_FAIL 0x06
+#define TD_PID_UNEXPECTED 0x07
+#define TD_DATA_OVERRUN 0x08
+#define TD_DATA_UNDERRUN 0x09
+#define TD_BUFFER_OVERRUN 0x0C
+#define TD_BUFFER_UNDERRUN 0x0D
+#define TD_TOBE_PROCESSED 0x0E
+#define TD_TOBE_PROCESSED_2 0x0F
+
+#define TD_NO_DELAY 0x7
+
+#define TD_INT 0x1
+#define TD_CTL 0x2
+#define TD_BLK 0x3
+
+typedef struct {
+ UINT32 Reserved:18;
+ UINT32 BufferRounding:1;
+ UINT32 DirPID:2;
+ UINT32 DelayInterrupt:3;
+ UINT32 DataToggle:2;
+ UINT32 ErrorCount:2;
+ UINT32 ConditionCode:4;
+} TD_DESCRIPTOR_WORD0;
+
+typedef struct _TD_DESCRIPTOR {
+ TD_DESCRIPTOR_WORD0 Word0;
+ VOID *CurrBufferPointer;
+ struct _TD_DESCRIPTOR *NextTD;
+ VOID *BufferEndPointer;
+ struct _TD_DESCRIPTOR *NextTDPointer;
+ UINT8 *DataBuffer;
+ UINT32 ActualSendLength;
+} TD_DESCRIPTOR;
+
+typedef struct {
+ UINT32 FunctionAddress:7;
+ UINT32 EndPointNum:4;
+ UINT32 Direction:2;
+ UINT32 Speed:1;
+ UINT32 Skip:1;
+ UINT32 Format:1;
+ UINT32 MaxPacketSize:11;
+ UINT32 FreeSpace:5;
+} ED_DESCRIPTOR_WORD0;
+
+typedef struct {
+ UINT32 Halted:1;
+ UINT32 ToggleCarry:1;
+ UINT32 Zero:2;
+ UINT32 TdHeadPointer:28;
+} ED_DESCRIPTOR_WORD2;
+
+typedef struct _ED_DESCRIPTOR {
+ ED_DESCRIPTOR_WORD0 Word0;
+ TD_DESCRIPTOR *TdTailPointer;
+ ED_DESCRIPTOR_WORD2 Word2;
+ struct _ED_DESCRIPTOR *NextED;
+} ED_DESCRIPTOR;
+
+#define TD_PTR(p) ((TD_DESCRIPTOR *)((p) << 4))
+#define ED_PTR(p) ((ED_DESCRIPTOR *)((p) << 4))
+#define RIGHT_SHIFT_4(p) ((UINT32)(p) >> 4)
+
+typedef enum {
+ CONTROL_LIST,
+ BULK_LIST,
+ INTERRUPT_LIST,
+ ISOCHRONOUS_LIST
+} DESCRIPTOR_LIST_TYPE;
+
+#endif \ No newline at end of file
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c
new file mode 100755
index 0000000..1426185
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c
@@ -0,0 +1,1426 @@
+/** @file
+ This file contains the implementation of Usb Hc Protocol.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "OhcPeim.h"
+
+/**
+ Submits control transfer to a target USB device.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param DeviceAddress The target device address.
+ @param DeviceSpeed Target device speed.
+ @param MaximumPacketLength Maximum packet size the default control transfer
+ endpoint is capable of sending or receiving.
+ @param Request USB device request to send.
+ @param TransferDirection Specifies the data direction for the data stage.
+ @param Data Data buffer to be transmitted or received from USB device.
+ @param DataLength The size (in bytes) of the data buffer.
+ @param TimeOut Indicates the maximum timeout, in millisecond.
+ @param TransferResult Return the result of this control transfer.
+
+ @retval EFI_SUCCESS Transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT Transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaxPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ ED_DESCRIPTOR *Ed;
+ TD_DESCRIPTOR *HeadTd;
+ TD_DESCRIPTOR *SetupTd;
+ TD_DESCRIPTOR *DataTd;
+ TD_DESCRIPTOR *StatusTd;
+ TD_DESCRIPTOR *EmptyTd;
+ EFI_STATUS Status;
+ UINT32 DataPidDir;
+ UINT32 StatusPidDir;
+ UINTN TimeCount;
+ UINT32 ErrorCode;
+
+ UINTN ActualSendLength;
+ UINTN LeftLength;
+ UINT8 DataToggle;
+
+ UINTN ReqMapLength = 0;
+ EFI_PHYSICAL_ADDRESS ReqMapPhyAddr = 0;
+
+ UINTN DataMapLength = 0;
+ EFI_PHYSICAL_ADDRESS DataMapPhyAddr = 0;
+
+ HeadTd = NULL;
+ DataTd = NULL;
+
+ if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&
+ TransferDirection != EfiUsbNoData) ||
+ Request == NULL || DataLength == NULL || TransferResult == NULL ||
+ (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||
+ (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||
+ (DeviceSpeed != EFI_USB_SPEED_LOW && DeviceSpeed != EFI_USB_SPEED_FULL) ||
+ (MaxPacketLength != 8 && MaxPacketLength != 16 &&
+ MaxPacketLength != 32 && MaxPacketLength != 64)) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: EFI_INVALID_PARAMETER\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*DataLength > MAX_BYTES_PER_TD) {
+ DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This);
+
+ if (TransferDirection == EfiUsbDataIn) {
+ DataPidDir = TD_IN_PID;
+ StatusPidDir = TD_OUT_PID;
+ } else {
+ DataPidDir = TD_OUT_PID;
+ StatusPidDir = TD_IN_PID;
+ }
+
+ OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);
+ if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to disable CONTROL transfer\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
+ Ed = OhciCreateED (Ohc);
+ if (Ed == NULL) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ OhciSetEDField (Ed, ED_SKIP, 1);
+ OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
+ OhciSetEDField (Ed, ED_ENDPT_NUM, 0);
+ OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
+ OhciSetEDField (Ed, ED_SPEED, DeviceSpeed);
+ OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
+ OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
+ OhciSetEDField (Ed, ED_PDATA, 0);
+ OhciSetEDField (Ed, ED_ZERO, 0);
+ OhciSetEDField (Ed, ED_TDHEAD_PTR, (UINT32) NULL);
+ OhciSetEDField (Ed, ED_TDTAIL_PTR, (UINT32) NULL);
+ OhciSetEDField (Ed, ED_NEXT_EDPTR, (UINT32) NULL);
+ OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);
+ //
+ // Setup Stage
+ //
+ if(Request != NULL) {
+ ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);
+ ReqMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Request;
+ }
+ SetupTd = OhciCreateTD (Ohc);
+ if (SetupTd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\n"));
+ goto FREE_ED_BUFF;
+ }
+ HeadTd = SetupTd;
+ OhciSetTDField (SetupTd, TD_PDATA, 0);
+ OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);
+ OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);
+ OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);
+ OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINTN)ReqMapPhyAddr);
+ OhciSetTDField (SetupTd, TD_NEXT_PTR, (UINT32) NULL);
+ OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINTN)ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1);
+ SetupTd->ActualSendLength = 0;
+ SetupTd->DataBuffer = NULL;
+ SetupTd->NextTDPointer = NULL;
+
+ DataMapLength = *DataLength;
+ if ((Data != NULL) && (DataMapLength != 0)) {
+ DataMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
+ }
+ //
+ //Data Stage
+ //
+ LeftLength = DataMapLength;
+ ActualSendLength = DataMapLength;
+ DataToggle = 1;
+ while (LeftLength > 0) {
+ ActualSendLength = LeftLength;
+ if (LeftLength > MaxPacketLength) {
+ ActualSendLength = MaxPacketLength;
+ }
+ DataTd = OhciCreateTD (Ohc);
+ if (DataTd == NULL) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Data TD buffer\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_TD_BUFF;
+ }
+ OhciSetTDField (DataTd, TD_PDATA, 0);
+ OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
+ OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
+ OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);
+ OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);
+ OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32) DataMapPhyAddr + ActualSendLength - 1);
+ OhciSetTDField (DataTd, TD_NEXT_PTR, (UINT32) NULL);
+ DataTd->ActualSendLength = ActualSendLength;
+ DataTd->DataBuffer = (UINT8 *)(UINTN)DataMapPhyAddr;
+ DataTd->NextTDPointer = 0;
+ OhciLinkTD (HeadTd, DataTd);
+ DataToggle ^= 1;
+ DataMapPhyAddr += ActualSendLength;
+ LeftLength -= ActualSendLength;
+ }
+ //
+ // Status Stage
+ //
+ StatusTd = OhciCreateTD (Ohc);
+ if (StatusTd == NULL) {
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Status TD buffer\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_TD_BUFF;
+ }
+ OhciSetTDField (StatusTd, TD_PDATA, 0);
+ OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);
+ OhciSetTDField (StatusTd, TD_DELAY_INT, 7);
+ OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);
+ OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, (UINT32) NULL);
+ OhciSetTDField (StatusTd, TD_NEXT_PTR, (UINT32) NULL);
+ OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, (UINT32) NULL);
+ StatusTd->ActualSendLength = 0;
+ StatusTd->DataBuffer = NULL;
+ StatusTd->NextTDPointer = NULL;
+ OhciLinkTD (HeadTd, StatusTd);
+ //
+ // Empty Stage
+ //
+ EmptyTd = OhciCreateTD (Ohc);
+ if (EmptyTd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Empty TD buffer\n"));
+ goto FREE_TD_BUFF;
+ }
+ OhciSetTDField (EmptyTd, TD_PDATA, 0);
+ OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
+ OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
+ OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
+ //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
+ EmptyTd->Word0.DataToggle = 0;
+ OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
+ OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
+ OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
+ OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
+ EmptyTd->ActualSendLength = 0;
+ EmptyTd->DataBuffer = NULL;
+ EmptyTd->NextTDPointer = NULL;
+ OhciLinkTD (HeadTd, EmptyTd);
+ Ed->TdTailPointer = EmptyTd;
+ OhciAttachTDListToED (Ed, HeadTd);
+ //
+ OhciSetEDField (Ed, ED_SKIP, 0);
+ MicroSecondDelay (20 * HC_1_MILLISECOND);
+ OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);
+ OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);
+ MicroSecondDelay (20 * HC_1_MILLISECOND);
+ if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 1) {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 1) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable CONTROL transfer\n"));
+ goto FREE_TD_BUFF;
+ }
+ }
+
+ TimeCount = 0;
+ Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
+
+ while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ TimeCount++;
+ Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
+ }
+ //
+ *TransferResult = ConvertErrorCode (ErrorCode);
+
+ if (ErrorCode != TD_NO_ERROR) {
+ if (ErrorCode == TD_TOBE_PROCESSED) {
+ DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));
+ } else {
+ DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
+ }
+
+ *DataLength = 0;
+ }
+
+ OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);
+ if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ DEBUG ((EFI_D_INFO, "OhciControlTransfer: Cannot disable CONTROL_ENABLE transfer\n"));
+ goto FREE_TD_BUFF;
+ }
+ }
+
+FREE_TD_BUFF:
+ while (HeadTd) {
+ DataTd = HeadTd;
+ HeadTd = HeadTd->NextTDPointer;
+ UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
+ }
+
+FREE_ED_BUFF:
+ UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
+
+ return Status;
+}
+
+/**
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and its direction in bit 7.
+ @param MaxiPacketLength Maximum packet size the endpoint is capable of
+ sending or receiving.
+ @param Data A pointers to the buffers of data to transmit
+ from or receive into.
+ @param DataLength The lenght of the data buffer.
+ @param DataToggle On input, the initial data toggle for the transfer;
+ On output, it is updated to to next data toggle to use of
+ the subsequent bulk transfer.
+ @param TimeOut Indicates the maximum time, in millisecond, which the
+ transfer is allowed to complete.
+ @param TransferResult A pointer to the detailed result information of the
+ bulk transfer.
+
+ @retval EFI_SUCCESS The transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
+ @retval EFI_INVALID_PARAMETER Parameters are invalid.
+ @retval EFI_TIMEOUT The transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaxPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ ED_DESCRIPTOR *Ed;
+ UINT8 EdDir;
+ UINT32 DataPidDir;
+ TD_DESCRIPTOR *HeadTd;
+ TD_DESCRIPTOR *DataTd;
+ TD_DESCRIPTOR *EmptyTd;
+ EFI_STATUS Status;
+ EFI_USB_DATA_DIRECTION TransferDirection;
+ UINT8 EndPointNum;
+ UINTN TimeCount;
+ UINT32 ErrorCode;
+
+ UINT8 CurrentToggle;
+ VOID *Mapping;
+ UINTN MapLength;
+ EFI_PHYSICAL_ADDRESS MapPyhAddr;
+ UINTN LeftLength;
+ UINTN ActualSendLength;
+ BOOLEAN FirstTD;
+
+ Mapping = NULL;
+ MapLength = 0;
+ MapPyhAddr = 0;
+ LeftLength = 0;
+ Status = EFI_SUCCESS;
+
+ if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||
+ *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||
+ (MaxPacketLength != 8 && MaxPacketLength != 16 &&
+ MaxPacketLength != 32 && MaxPacketLength != 64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
+
+ if ((EndPointAddress & 0x80) != 0) {
+ TransferDirection = EfiUsbDataIn;
+ EdDir = ED_IN_DIR;
+ DataPidDir = TD_IN_PID;
+ } else {
+ TransferDirection = EfiUsbDataOut;
+ EdDir = ED_OUT_DIR;
+ DataPidDir = TD_OUT_PID;
+ }
+
+ EndPointNum = (EndPointAddress & 0xF);
+
+ OhciSetHcControl (Ohc, BULK_ENABLE, 0);
+ if (OhciGetHcControl (Ohc, BULK_ENABLE) != 0) {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ if (OhciGetHcControl (Ohc, BULK_ENABLE) != 0) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
+
+ Ed = OhciCreateED (Ohc);
+ if (Ed == NULL) {
+ DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ OhciSetEDField (Ed, ED_SKIP, 1);
+ OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
+ OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
+ OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
+ OhciSetEDField (Ed, ED_SPEED, HI_SPEED);
+ OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
+ OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
+ OhciSetEDField (Ed, ED_PDATA, 0);
+ OhciSetEDField (Ed, ED_ZERO, 0);
+ OhciSetEDField (Ed, ED_TDHEAD_PTR, (UINT32) NULL);
+ OhciSetEDField (Ed, ED_TDTAIL_PTR, (UINT32) NULL);
+ OhciSetEDField (Ed, ED_NEXT_EDPTR, (UINT32) NULL);
+ OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);
+
+ if(Data != NULL) {
+ MapLength = *DataLength;
+ MapPyhAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
+ }
+ //
+ //Data Stage
+ //
+ LeftLength = MapLength;
+ ActualSendLength = MapLength;
+ CurrentToggle = *DataToggle;
+ HeadTd = NULL;
+ FirstTD = TRUE;
+ while (LeftLength > 0) {
+ ActualSendLength = LeftLength;
+ if (LeftLength > MaxPacketLength) {
+ ActualSendLength = MaxPacketLength;
+ }
+ DataTd = OhciCreateTD (Ohc);
+ if (DataTd == NULL) {
+ DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate Data TD buffer\r\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_TD_BUFF;
+ }
+ OhciSetTDField (DataTd, TD_PDATA, 0);
+ OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
+ OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
+ OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
+ OhciSetTDField (DataTd, TD_DT_TOGGLE, CurrentToggle);
+ OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
+ OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
+ OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32) MapPyhAddr + ActualSendLength - 1);
+ OhciSetTDField (DataTd, TD_NEXT_PTR, (UINT32) NULL);
+ DataTd->ActualSendLength = ActualSendLength;
+ DataTd->DataBuffer = (UINT8 *)(UINTN)MapPyhAddr;
+ DataTd->NextTDPointer = 0;
+ if (FirstTD) {
+ HeadTd = DataTd;
+ FirstTD = FALSE;
+ } else {
+ OhciLinkTD (HeadTd, DataTd);
+ }
+ CurrentToggle ^= 1;
+ MapPyhAddr += ActualSendLength;
+ LeftLength -= ActualSendLength;
+ }
+ //
+ // Empty Stage
+ //
+ EmptyTd = OhciCreateTD (Ohc);
+ if (EmptyTd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate Empty TD buffer\r\n"));
+ goto FREE_TD_BUFF;
+ }
+ OhciSetTDField (EmptyTd, TD_PDATA, 0);
+ OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
+ OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
+ OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
+ //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
+ EmptyTd->Word0.DataToggle = 0;
+ OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
+ OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
+ OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
+ OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
+ OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
+ EmptyTd->ActualSendLength = 0;
+ EmptyTd->DataBuffer = NULL;
+ EmptyTd->NextTDPointer = NULL;
+ OhciLinkTD (HeadTd, EmptyTd);
+ Ed->TdTailPointer = EmptyTd;
+ OhciAttachTDListToED (Ed, HeadTd);
+
+ OhciSetEDField (Ed, ED_SKIP, 0);
+ OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);
+ OhciSetHcControl (Ohc, BULK_ENABLE, 1);
+ if (OhciGetHcControl (Ohc, BULK_ENABLE) != 1) {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ if (OhciGetHcControl (Ohc, BULK_ENABLE) != 1) {
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ goto FREE_TD_BUFF;
+ }
+ }
+
+ TimeCount = 0;
+ Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
+
+ while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ TimeCount++;
+ Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
+ }
+
+ *TransferResult = ConvertErrorCode (ErrorCode);
+
+ if (ErrorCode != TD_NO_ERROR) {
+ if (ErrorCode == TD_TOBE_PROCESSED) {
+ DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));
+ } else {
+ DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
+ }
+ *DataLength = 0;
+ }
+ *DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
+
+FREE_TD_BUFF:
+ while (HeadTd) {
+ DataTd = HeadTd;
+ HeadTd = HeadTd->NextTDPointer;
+ UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
+ }
+ UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
+
+ return Status;
+}
+/**
+ Retrieves the number of root hub ports.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the
+ PEI_USB_HOST_CONTROLLER_PPI.
+ @param[out] NumOfPorts The pointer to the number of the root hub ports.
+
+ @retval EFI_SUCCESS The port number was retrieved successfully.
+ @retval EFI_INVALID_PARAMETER PortNumber is NULL.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciGetRootHubNumOfPorts (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *NumOfPorts
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ if (NumOfPorts == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
+ *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
+
+ return EFI_SUCCESS;
+}
+/**
+ Retrieves the current status of a USB root hub port.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param PortNumber The root hub port to retrieve the state from.
+ @param PortStatus Variable to receive the port state.
+
+ @retval EFI_SUCCESS The status of the USB root hub port specified.
+ by PortNumber was returned in PortStatus.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ UINT8 NumOfPorts;
+
+ Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
+
+ OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
+ if (PortNumber >= NumOfPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_POWER;
+ }
+ if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
+ }
+ if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Sets a feature for the specified root hub port.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI
+ @param PortNumber Root hub port to set.
+ @param PortFeature Feature to set.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was set.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+ @retval EFI_TIMEOUT The time out occurred.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ EFI_STATUS Status;
+ UINT8 NumOfPorts;
+ UINTN RetryTimes;
+
+ OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
+ if (PortNumber >= NumOfPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
+
+ Status = EFI_SUCCESS;
+
+
+ switch (PortFeature) {
+ case EfiUsbPortPower:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortReset:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||
+ OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
+ break;
+
+ case EfiUsbPortEnable:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);;
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+
+ case EfiUsbPortSuspend:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);;
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/**
+ Clears a feature for the specified root hub port.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param PortNumber Specifies the root hub port whose feature
+ is requested to be cleared.
+ @param PortFeature Indicates the feature selector associated with the
+ feature clear request.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was cleared
+ for the USB root hub port specified by PortNumber.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+{
+ USB_OHCI_HC_DEV *Ohc;
+ EFI_STATUS Status;
+ UINT8 NumOfPorts;
+ UINTN RetryTimes;
+
+
+ OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
+ if (PortNumber >= NumOfPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
+
+ Status = EFI_SUCCESS;
+
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortSuspend:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortReset:
+ break;
+
+ case EfiUsbPortPower:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortConnectChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortResetChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+
+ case EfiUsbPortEnableChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortSuspendChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbPortOverCurrentChange:
+ Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
+
+ //
+ // Verify the state
+ //
+ RetryTimes = 0;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ RetryTimes++;
+ } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
+ RetryTimes < MAX_RETRY_TIMES);
+
+ if (RetryTimes >= MAX_RETRY_TIMES) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+/**
+ Provides software reset for the USB host controller.
+
+ @param This This EFI_USB_HC_PROTOCOL instance.
+ @param Attributes A bit mask of the reset operation to perform.
+
+ @retval EFI_SUCCESS The reset operation succeeded.
+ @retval EFI_INVALID_PARAMETER Attributes is not valid.
+ @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
+ not currently supported by the host controller.
+ @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
+
+**/
+EFI_STATUS
+InitializeUsbHC (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT16 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT8 NumOfPorts;
+ UINT32 PowerOnGoodTime;
+ UINT32 Data32;
+ BOOLEAN Flag = FALSE;
+
+ if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = EFI_SUCCESS;
+
+ if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {
+ MicroSecondDelay (50 * HC_1_MILLISECOND);
+ Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ MicroSecondDelay (50 * HC_1_MILLISECOND);
+ //
+ // Wait for host controller reset.
+ //
+ PowerOnGoodTime = 50;
+ do {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ Data32 = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS );
+ if ((Data32 & HC_RESET) == 0) {
+ Flag = TRUE;
+ break;
+ }
+ }while(PowerOnGoodTime--);
+ if (!Flag){
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
+ if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {
+ Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ MicroSecondDelay (50 * HC_1_MILLISECOND);
+ }
+ //
+ // Initialize host controller operational registers
+ //
+ OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778);
+ OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
+ OhciSetPeriodicStart (Ohc, 0x2a2f);
+ OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x0);
+ OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0);
+ OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0);
+ OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1);
+ //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);
+ //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);
+
+ OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0);
+ OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff);
+ OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE);
+ OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER);
+ OhciGetRootHubNumOfPorts (PeiServices, &Ohc->UsbHostControllerPpi, &NumOfPorts);
+ for (Index = 0; Index < NumOfPorts; Index++) {
+ if (!EFI_ERROR (OhciSetRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortReset))) {
+ MicroSecondDelay (200 * HC_1_MILLISECOND);
+ OhciClearRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortReset);
+ MicroSecondDelay (HC_1_MILLISECOND);
+ OhciSetRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortEnable);
+ MicroSecondDelay (HC_1_MILLISECOND);
+ }
+ }
+
+ Ohc->MemPool = UsbHcInitMemPool(TRUE, 0);
+ if(Ohc->MemPool == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
+ OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
+ OhciSetHcControl (Ohc, CONTROL_ENABLE | BULK_ENABLE, 1);
+ OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
+ MicroSecondDelay (50 * HC_1_MILLISECOND);
+ //
+ // Wait till first SOF occurs, and then clear it
+ //
+ while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);
+ OhciClearInterruptStatus (Ohc, START_OF_FRAME);
+ MicroSecondDelay (HC_1_MILLISECOND);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Submits control transfer to a target USB device.
+
+ Calls underlying OhciControlTransfer to do work. This wrapper routine required
+ on Quark so that USB DMA transfers do not cause an IMR violation.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param DeviceAddress The target device address.
+ @param DeviceSpeed Target device speed.
+ @param MaximumPacketLength Maximum packet size the default control transfer
+ endpoint is capable of sending or receiving.
+ @param Request USB device request to send.
+ @param TransferDirection Specifies the data direction for the data stage.
+ @param Data Data buffer to be transmitted or received from USB device.
+ @param DataLength The size (in bytes) of the data buffer.
+ @param TimeOut Indicates the maximum timeout, in millisecond.
+ @param TransferResult Return the result of this control transfer.
+
+ @retval EFI_SUCCESS Transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT Transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedirectOhciControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaxPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_DEVICE_REQUEST *NewRequest;
+ VOID *NewData;
+ UINT8 *Alloc;
+
+ //
+ // Allocate memory external to IMR protected region for transfer data.
+ //
+ RedirectMemoryServicesEnable ();
+ Status = (*PeiServices)->AllocatePool (
+ PeiServices,
+ sizeof(EFI_USB_DEVICE_REQUEST) + *DataLength,
+ (VOID **) &Alloc
+ );
+ RedirectMemoryServicesDisable ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Setup pointers to transfer buffers.
+ //
+ NewRequest = (EFI_USB_DEVICE_REQUEST *) Alloc;
+ Alloc += sizeof(EFI_USB_DEVICE_REQUEST);
+ NewData = (VOID *) Alloc;
+
+ //
+ // Copy callers request packet into transfer request packet.
+ //
+ if (Request != NULL) {
+ CopyMem (NewRequest,Request,sizeof(EFI_USB_DEVICE_REQUEST));
+ } else {
+ NewRequest = NULL;
+ }
+ //
+ // Copy callers data into transfer data buffer.
+ //
+ if (Data != NULL) {
+ if (DataLength > 0) {
+ CopyMem (NewData,Data,*DataLength);
+ }
+ } else {
+ NewData = NULL;
+ }
+
+ //
+ // Call underlying OhciControlTransfer to do work.
+ //
+ Status = OhciControlTransfer (
+ PeiServices,
+ This,
+ DeviceAddress,
+ DeviceSpeed,
+ MaxPacketLength,
+ NewRequest,
+ TransferDirection,
+ NewData,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
+
+ //
+ // Copy transfer buffer back into callers buffer.
+ //
+ if (Data != NULL && *DataLength > 0) {
+ CopyMem (Data, NewData, *DataLength);
+ }
+
+ return Status;
+}
+
+/**
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ Calls underlying OhciBulkTransfer to do work. This wrapper routine required
+ on Quark so that USB DMA transfers do not cause an IMR violation.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and its direction in bit 7.
+ @param MaxiPacketLength Maximum packet size the endpoint is capable of
+ sending or receiving.
+ @param Data A pointers to the buffers of data to transmit
+ from or receive into.
+ @param DataLength The lenght of the data buffer.
+ @param DataToggle On input, the initial data toggle for the transfer;
+ On output, it is updated to to next data toggle to use of
+ the subsequent bulk transfer.
+ @param TimeOut Indicates the maximum time, in millisecond, which the
+ transfer is allowed to complete.
+ @param TransferResult A pointer to the detailed result information of the
+ bulk transfer.
+
+ @retval EFI_SUCCESS The transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
+ @retval EFI_INVALID_PARAMETER Parameters are invalid.
+ @retval EFI_TIMEOUT The transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedirectOhciBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaxPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *NewData;
+
+ //
+ // Allocate memory external to IMR protected region for transfer data.
+ //
+ RedirectMemoryServicesEnable ();
+ Status = (*PeiServices)->AllocatePool (
+ PeiServices,
+ *DataLength,
+ (VOID **) &NewData
+ );
+ RedirectMemoryServicesDisable ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Copy callers data into transfer buffer.
+ //
+ if (Data != NULL) {
+ if (DataLength > 0) {
+ CopyMem (NewData,Data,*DataLength);
+ }
+ } else {
+ NewData = NULL;
+ }
+
+ //
+ // Call underlying OhciBulkTransfer to do work.
+ //
+ Status = OhciBulkTransfer (
+ PeiServices,
+ This,
+ DeviceAddress,
+ EndPointAddress,
+ MaxPacketLength,
+ NewData,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+
+ //
+ // Copy transfer buffer back into callers buffer.
+ //
+ if (Data != NULL && *DataLength > 0) {
+ CopyMem (Data, NewData, *DataLength);
+ }
+
+ return Status;
+}
+
+/**
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS PPI successfully installed.
+
+**/
+EFI_STATUS
+OhcPeimEntry (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+
+ PEI_USB_CONTROLLER_PPI *ChipSetUsbControllerPpi;
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINTN ControllerType;
+ UINTN BaseAddress;
+ UINTN MemPages;
+ USB_OHCI_HC_DEV *Ohc;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+
+
+ //
+ // Shadow this PEIM to run from memory
+ //
+ if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
+ return EFI_SUCCESS;
+ }
+ Status = PeiServicesLocatePpi (
+ &gPeiUsbControllerPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &ChipSetUsbControllerPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Index = 0;
+ while (TRUE) {
+ Status = ChipSetUsbControllerPpi->GetUsbController (
+ (EFI_PEI_SERVICES **) PeiServices,
+ ChipSetUsbControllerPpi,
+ Index,
+ &ControllerType,
+ &BaseAddress
+ );
+ //
+ // When status is error, meant no controller is found
+ //
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // This PEIM is for OHC type controller.
+ //
+ if (ControllerType != PEI_OHCI_CONTROLLER) {
+ Index++;
+ continue;
+ }
+
+ MemPages = sizeof (USB_OHCI_HC_DEV) / PAGESIZE + 1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ MemPages,
+ &TempPtr
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to allocate buffer for the %dth OHCI ControllerPpi\n", Index));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);
+ Ohc = (USB_OHCI_HC_DEV *) ((UINTN) TempPtr);
+
+ Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE;
+
+ Ohc->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
+
+ //
+ // Initialize Uhc's hardware
+ //
+ Status = InitializeUsbHC (
+ (EFI_PEI_SERVICES **)PeiServices,
+ Ohc,
+ EFI_USB_HC_RESET_GLOBAL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index));
+ return Status;
+ }
+ //
+ // Control & Bulk transfer services are accessed via their Redirect
+ // routine versions on Quark so that USB DMA transfers do not cause an
+ // IMR violation.
+ //
+ Ohc->UsbHostControllerPpi.ControlTransfer = RedirectOhciControlTransfer;
+ Ohc->UsbHostControllerPpi.BulkTransfer = RedirectOhciBulkTransfer;
+ Ohc->UsbHostControllerPpi.GetRootHubPortNumber = OhciGetRootHubNumOfPorts;
+ Ohc->UsbHostControllerPpi.GetRootHubPortStatus = OhciGetRootHubPortStatus;
+ Ohc->UsbHostControllerPpi.SetRootHubPortFeature = OhciSetRootHubPortFeature;
+ Ohc->UsbHostControllerPpi.ClearRootHubPortFeature = OhciClearRootHubPortFeature;
+
+ Ohc->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ Ohc->PpiDescriptor.Guid = &gPeiUsbHostControllerPpiGuid;
+ Ohc->PpiDescriptor.Ppi = &Ohc->UsbHostControllerPpi;
+
+ Status = PeiServicesInstallPpi (&Ohc->PpiDescriptor);
+ if (EFI_ERROR (Status)) {
+ Index++;
+ continue;
+ }
+ Index++;
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.h
new file mode 100644
index 0000000..07c2ec5
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.h
@@ -0,0 +1,277 @@
+/** @file
+ Provides the definition of Usb Hc Protocol and OHCI controller
+ private data structure.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#ifndef _OHCI_PEIM_H
+#define _OHCI_PEIM_H
+
+#include <PiPei.h>
+
+#include <Ppi/UsbController.h>
+#include <Ppi/UsbHostController.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+#include <Library/RedirectPeiServicesLib.h>
+
+typedef struct _USB_OHCI_HC_DEV USB_OHCI_HC_DEV;
+
+#include "UsbHcMem.h"
+#include "OhciReg.h"
+#include "OhciSched.h"
+#include "OhciUrb.h"
+#include "Descriptor.h"
+
+#define EFI_USB_SPEED_FULL 0x0000
+#define EFI_USB_SPEED_LOW 0x0001
+#define EFI_USB_SPEED_HIGH 0x0002
+
+#define PAGESIZE 4096
+
+#define HC_1_MICROSECOND 1
+#define HC_1_MILLISECOND (1000 * HC_1_MICROSECOND)
+#define HC_1_SECOND (1000 * HC_1_MILLISECOND)
+
+
+#define USB_OHCI_HC_DEV_SIGNATURE SIGNATURE_32('o','h','c','i')
+
+struct _USB_OHCI_HC_DEV {
+ UINTN Signature;
+ PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi;
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ UINT32 UsbHostControllerBaseAddress;
+ VOID *MemPool;
+};
+
+#define PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(a) CR (a, USB_OHCI_HC_DEV, UsbHostControllerPpi, USB_OHCI_HC_DEV_SIGNATURE)
+
+//
+// Func List
+//
+
+/**
+ Provides software reset for the USB host controller.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param Attributes A bit mask of the reset operation to perform.
+
+ @retval EFI_SUCCESS The reset operation succeeded.
+ @retval EFI_INVALID_PARAMETER Attributes is not valid.
+ @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
+ not currently supported by the host controller.
+ @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
+
+**/
+EFI_STATUS
+InitializeUsbHC (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT16 Attributes
+ );
+
+/**
+ Submits control transfer to a target USB device.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param DeviceAddress The target device address.
+ @param DeviceSpeed Target device speed.
+ @param MaximumPacketLength Maximum packet size the default control transfer
+ endpoint is capable of sending or receiving.
+ @param Request USB device request to send.
+ @param TransferDirection Specifies the data direction for the data stage.
+ @param Data Data buffer to be transmitted or received from USB device.
+ @param DataLength The size (in bytes) of the data buffer.
+ @param TimeOut Indicates the maximum timeout, in millisecond.
+ @param TransferResult Return the result of this control transfer.
+
+ @retval EFI_SUCCESS Transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT Transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaxPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+/**
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and its direction in bit 7.
+ @param MaxiPacketLength Maximum packet size the endpoint is capable of
+ sending or receiving.
+ @param Data A pointers to the buffers of data to transmit
+ from or receive into.
+ @param DataLength The lenght of the data buffer.
+ @param DataToggle On input, the initial data toggle for the transfer;
+ On output, it is updated to to next data toggle to use of
+ the subsequent bulk transfer.
+ @param TimeOut Indicates the maximum time, in millisecond, which the
+ transfer is allowed to complete.
+ @param TransferResult A pointer to the detailed result information of the
+ bulk transfer.
+
+ @retval EFI_SUCCESS The transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
+ @retval EFI_INVALID_PARAMETER Parameters are invalid.
+ @retval EFI_TIMEOUT The transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaxPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+/**
+ Retrieves the number of root hub ports.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the
+ PEI_USB_HOST_CONTROLLER_PPI.
+ @param[out] NumOfPorts The pointer to the number of the root hub ports.
+
+ @retval EFI_SUCCESS The port number was retrieved successfully.
+ @retval EFI_INVALID_PARAMETER PortNumber is NULL.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciGetRootHubNumOfPorts (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *NumOfPorts
+ );
+/**
+ Retrieves the current status of a USB root hub port.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param PortNumber The root hub port to retrieve the state from.
+ @param PortStatus Variable to receive the port state.
+
+ @retval EFI_SUCCESS The status of the USB root hub port specified.
+ by PortNumber was returned in PortStatus.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ );
+/**
+
+ Sets a feature for the specified root hub port.
+
+ @param This A pointer to the EFI_USB_HC_PROTOCOL.
+ @param PortNumber Specifies the root hub port whose feature
+ is requested to be set.
+ @param PortFeature Indicates the feature selector associated
+ with the feature set request.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was set for the
+ USB root hub port specified by PortNumber.
+ @retval EFI_DEVICE_ERROR Set feature failed because of hardware issue
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+**/
+EFI_STATUS
+EFIAPI
+OhciSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+/**
+ Clears a feature for the specified root hub port.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
+ @param PortNumber Specifies the root hub port whose feature
+ is requested to be cleared.
+ @param PortFeature Indicates the feature selector associated with the
+ feature clear request.
+
+ @retval EFI_SUCCESS The feature specified by PortFeature was cleared
+ for the USB root hub port specified by PortNumber.
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+
+**/
+
+EFI_STATUS
+EFIAPI
+OhciClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf
new file mode 100644
index 0000000..ffda11a
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf
@@ -0,0 +1,85 @@
+## @file
+# FIX ME!
+#
+# FIX ME!
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = OhciPei
+ FILE_GUID = 332A0926-429B-4624-9211-A36B23DF0389
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = OhcPeimEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ Descriptor.h
+ OhcPeim.c
+ OhcPeim.h
+ OhciSched.c
+ OhciSched.h
+ OhciReg.c
+ OhciReg.h
+ OhciUrb.c
+ OhciUrb.h
+ UsbHcMem.c
+ UsbHcMem.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+ IoLib
+ TimerLib
+ BaseMemoryLib
+ PeimEntryPoint
+ PeiServicesLib
+ RedirectPeiServicesLib
+
+[Ppis]
+ gPeiUsbHostControllerPpiGuid # PPI ALWAYS_PRODUCED
+ gPeiUsbControllerPpiGuid # PPI ALWAYS_CONSUMED
+
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid
+
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.c
new file mode 100644
index 0000000..56c0e47
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.c
@@ -0,0 +1,1412 @@
+/** @file
+ The OHCI register operation routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "OhcPeim.h"
+
+/**
+
+ Get OHCI operational reg value
+
+ @param Ohc UHC private data
+ @param Offset Offset of the operational reg
+
+ @retval Value of the register
+
+**/
+UINT32
+OhciGetOperationalReg (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Offset
+ )
+{
+
+ return MmioRead32 (Ohc->UsbHostControllerBaseAddress + Offset);
+
+}
+/**
+
+ Set OHCI operational reg value
+
+ @param Ohc UHC private data
+ @param Offset Offset of the operational reg
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set to the reg
+
+**/
+
+
+EFI_STATUS
+OhciSetOperationalReg (
+ USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Offset,
+ IN UINT32 *Value
+ )
+{
+ MmioWrite32(Ohc->UsbHostControllerBaseAddress + Offset, *Value);
+ return EFI_SUCCESS;
+}
+/**
+
+ Get HcRevision reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of the register
+
+**/
+
+
+UINT32
+OhciGetHcRevision (
+ USB_OHCI_HC_DEV *Ohc
+ )
+{
+ return OhciGetOperationalReg (Ohc, HC_REVISION);
+}
+/**
+
+ Set HcReset reg value
+
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcReset (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcRESET Reset;
+
+ Status = EFI_SUCCESS;
+ *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc, USBHOST_OFFSET_UHCHR);
+
+ if (Field & RESET_SYSTEM_BUS) {
+ Reset.FSBIR = Value;
+ }
+
+ if (Field & RESET_HOST_CONTROLLER) {
+ Reset.FHR = Value;
+ }
+
+ if (Field & RESET_CLOCK_GENERATION) {
+ Reset.CGR = Value;
+ }
+
+ if (Field & RESET_SSE_GLOBAL) {
+ Reset.SSE = Value;
+ }
+
+ if (Field & RESET_PSPL) {
+ Reset.PSPL = Value;
+ }
+
+ if (Field & RESET_PCPL) {
+ Reset.PCPL = Value;
+ }
+
+ if (Field & RESET_SSEP1) {
+ Reset.SSEP1 = Value;
+ }
+
+ if (Field & RESET_SSEP2) {
+ Reset.SSEP2 = Value;
+ }
+
+ if (Field & RESET_SSEP3) {
+ Reset.SSEP3 = Value;
+ }
+
+ OhciSetOperationalReg (Ohc, USBHOST_OFFSET_UHCHR, (UINT32*)&Reset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Get specific field of HcReset reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcReset (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Field
+ )
+{
+ HcRESET Reset;
+ UINT32 Value;
+
+
+ *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc, USBHOST_OFFSET_UHCHR);
+ Value = 0;
+
+ switch (Field) {
+ case RESET_SYSTEM_BUS:
+ Value = Reset.FSBIR;
+ break;
+
+ case RESET_HOST_CONTROLLER:
+ Value = Reset.FHR;
+ break;
+
+ case RESET_CLOCK_GENERATION:
+ Value = Reset.CGR;
+ break;
+
+ case RESET_SSE_GLOBAL:
+ Value = Reset.SSE;
+ break;
+
+ case RESET_PSPL:
+ Value = Reset.PSPL;
+ break;
+
+ case RESET_PCPL:
+ Value = Reset.PCPL;
+ break;
+
+ case RESET_SSEP1:
+ Value = Reset.SSEP1;
+ break;
+
+ case RESET_SSEP2:
+ Value = Reset.SSEP2;
+ break;
+
+ case RESET_SSEP3:
+ Value = Reset.SSEP3;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+
+ return Value;
+}
+
+/**
+
+ Set HcControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcCONTROL Control;
+
+
+
+ *(UINT32 *) &Control = OhciGetOperationalReg (Ohc, HC_CONTROL);
+
+ if (Field & CONTROL_BULK_RATIO) {
+ Control.ControlBulkRatio = Value;
+ }
+
+ if (Field & HC_FUNCTIONAL_STATE) {
+ Control.FunctionalState = Value;
+ }
+
+ if (Field & PERIODIC_ENABLE) {
+ Control.PeriodicEnable = Value;
+ }
+
+ if (Field & CONTROL_ENABLE) {
+ Control.ControlEnable = Value;
+ }
+
+ if (Field & ISOCHRONOUS_ENABLE) {
+ Control.IsochronousEnable = Value;
+ }
+
+ if (Field & BULK_ENABLE) {
+ Control.BulkEnable = Value;
+ }
+
+ if (Field & INTERRUPT_ROUTING) {
+ Control.InterruptRouting = Value;
+ }
+
+ Status = OhciSetOperationalReg (Ohc, HC_CONTROL, (UINT32*)&Control);
+
+ return Status;
+}
+
+
+/**
+
+ Get specific field of HcControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+
+UINT32
+OhciGetHcControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcCONTROL Control;
+
+ *(UINT32 *) &Control = OhciGetOperationalReg (Ohc, HC_CONTROL);
+
+ switch (Field) {
+ case CONTROL_BULK_RATIO:
+ return Control.ControlBulkRatio;
+ break;
+ case PERIODIC_ENABLE:
+ return Control.PeriodicEnable;
+ break;
+ case CONTROL_ENABLE:
+ return Control.ControlEnable;
+ break;
+ case BULK_ENABLE:
+ return Control.BulkEnable;
+ break;
+ case ISOCHRONOUS_ENABLE:
+ return Control.IsochronousEnable;
+ break;
+ case HC_FUNCTIONAL_STATE:
+ return Control.FunctionalState;
+ break;
+ case INTERRUPT_ROUTING:
+ return Control.InterruptRouting;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set HcCommand reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcCommandStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcCOMMAND_STATUS CommandStatus;
+
+ ZeroMem (&CommandStatus, sizeof (HcCOMMAND_STATUS));
+
+ if(Field & HC_RESET){
+ CommandStatus.HcReset = Value;
+ }
+
+ if(Field & CONTROL_LIST_FILLED){
+ CommandStatus.ControlListFilled = Value;
+ }
+
+ if(Field & BULK_LIST_FILLED){
+ CommandStatus.BulkListFilled = Value;
+ }
+
+ if(Field & CHANGE_OWNER_REQUEST){
+ CommandStatus.ChangeOwnerRequest = Value;
+ }
+
+ if(Field & SCHEDULE_OVERRUN_COUNT){
+ CommandStatus.ScheduleOverrunCount = Value;
+ }
+
+ Status = OhciSetOperationalReg (Ohc, HC_COMMAND_STATUS, (UINT32*)&CommandStatus);
+
+ return Status;
+}
+
+/**
+
+ Get specific field of HcCommand reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcCommandStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcCOMMAND_STATUS CommandStatus;
+
+ *(UINT32 *) &CommandStatus = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS);
+
+ switch (Field){
+ case HC_RESET:
+ return CommandStatus.HcReset;
+ break;
+ case CONTROL_LIST_FILLED:
+ return CommandStatus.ControlListFilled;
+ break;
+ case BULK_LIST_FILLED:
+ return CommandStatus.BulkListFilled;
+ break;
+ case CHANGE_OWNER_REQUEST:
+ return CommandStatus.ChangeOwnerRequest;
+ break;
+ case SCHEDULE_OVERRUN_COUNT:
+ return CommandStatus.ScheduleOverrunCount;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Clear specific fields of Interrupt Status
+
+ @param Ohc UHC private data
+ @param Field Field to clear
+
+ @retval EFI_SUCCESS Fields cleared
+
+**/
+
+EFI_STATUS
+OhciClearInterruptStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ EFI_STATUS Status;
+ HcINTERRUPT_STATUS InterruptStatus;
+
+ ZeroMem (&InterruptStatus, sizeof (HcINTERRUPT_STATUS));
+
+ if(Field & SCHEDULE_OVERRUN){
+ InterruptStatus.SchedulingOverrun = 1;
+ }
+
+ if(Field & WRITEBACK_DONE_HEAD){
+ InterruptStatus.WriteBackDone = 1;
+ }
+ if(Field & START_OF_FRAME){
+ InterruptStatus.Sof = 1;
+ }
+
+ if(Field & RESUME_DETECT){
+ InterruptStatus.ResumeDetected = 1;
+ }
+
+ if(Field & UNRECOVERABLE_ERROR){
+ InterruptStatus.UnrecoverableError = 1;
+ }
+
+ if(Field & FRAME_NUMBER_OVERFLOW){
+ InterruptStatus.FrameNumOverflow = 1;
+ }
+
+ if(Field & ROOTHUB_STATUS_CHANGE){
+ InterruptStatus.RHStatusChange = 1;
+ }
+
+ if(Field & OWNERSHIP_CHANGE){
+ InterruptStatus.OwnerChange = 1;
+ }
+
+ Status = OhciSetOperationalReg (Ohc, HC_INTERRUPT_STATUS, (UINT32*)&InterruptStatus);
+
+ return Status;
+}
+
+/**
+
+ Get fields of HcInterrupt reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcInterruptStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcINTERRUPT_STATUS InterruptStatus;
+
+ *(UINT32 *) &InterruptStatus = OhciGetOperationalReg (Ohc, HC_INTERRUPT_STATUS);
+
+ switch (Field){
+ case SCHEDULE_OVERRUN:
+ return InterruptStatus.SchedulingOverrun;
+ break;
+
+ case WRITEBACK_DONE_HEAD:
+ return InterruptStatus.WriteBackDone;
+ break;
+
+ case START_OF_FRAME:
+ return InterruptStatus.Sof;
+ break;
+
+ case RESUME_DETECT:
+ return InterruptStatus.ResumeDetected;
+ break;
+
+ case UNRECOVERABLE_ERROR:
+ return InterruptStatus.UnrecoverableError;
+ break;
+
+ case FRAME_NUMBER_OVERFLOW:
+ return InterruptStatus.FrameNumOverflow;
+ break;
+
+ case ROOTHUB_STATUS_CHANGE:
+ return InterruptStatus.RHStatusChange;
+ break;
+
+ case OWNERSHIP_CHANGE:
+ return InterruptStatus.OwnerChange;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set Interrupt Control reg value
+
+ @param Ohc UHC private data
+ @param StatEnable Enable or Disable
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetInterruptControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN BOOLEAN StatEnable,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcINTERRUPT_CONTROL InterruptState;
+
+
+ ZeroMem (&InterruptState, sizeof (HcINTERRUPT_CONTROL));
+
+ if(Field & SCHEDULE_OVERRUN) {
+ InterruptState.SchedulingOverrunInt = Value;
+ }
+
+ if(Field & WRITEBACK_DONE_HEAD) {
+ InterruptState.WriteBackDoneInt = Value;
+ }
+ if(Field & START_OF_FRAME) {
+ InterruptState.SofInt = Value;
+ }
+
+ if(Field & RESUME_DETECT) {
+ InterruptState.ResumeDetectedInt = Value;
+ }
+
+ if(Field & UNRECOVERABLE_ERROR) {
+ InterruptState.UnrecoverableErrorInt = Value;
+ }
+
+ if(Field & FRAME_NUMBER_OVERFLOW) {
+ InterruptState.FrameNumOverflowInt = Value;
+ }
+
+ if(Field & ROOTHUB_STATUS_CHANGE) {
+ InterruptState.RHStatusChangeInt = Value;
+ }
+
+ if(Field & OWNERSHIP_CHANGE) {
+ InterruptState.OwnerChangedInt = Value;
+ }
+
+ if(Field & MASTER_INTERRUPT) {
+ InterruptState.MasterInterruptEnable = Value;
+ }
+
+ if (StatEnable) {
+ Status = OhciSetOperationalReg (Ohc, HC_INTERRUPT_ENABLE, (UINT32*)&InterruptState);
+ } else {
+ Status = OhciSetOperationalReg (Ohc, HC_INTERRUPT_DISABLE, (UINT32*)&InterruptState);
+ }
+
+ return Status;
+}
+
+/**
+
+ Get field of HcInterruptControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcInterruptControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcINTERRUPT_CONTROL InterruptState;
+
+ *(UINT32 *) &InterruptState = OhciGetOperationalReg (Ohc, HC_INTERRUPT_ENABLE);
+
+ switch (Field){
+ case SCHEDULE_OVERRUN:
+ return InterruptState.SchedulingOverrunInt;
+ break;
+
+ case WRITEBACK_DONE_HEAD:
+ return InterruptState.WriteBackDoneInt;
+ break;
+
+ case START_OF_FRAME:
+ return InterruptState.SofInt;
+ break;
+
+ case RESUME_DETECT:
+ return InterruptState.ResumeDetectedInt;
+ break;
+
+ case UNRECOVERABLE_ERROR:
+ return InterruptState.UnrecoverableErrorInt;
+ break;
+
+ case FRAME_NUMBER_OVERFLOW:
+ return InterruptState.FrameNumOverflowInt;
+ break;
+
+ case ROOTHUB_STATUS_CHANGE:
+ return InterruptState.RHStatusChangeInt;
+ break;
+
+ case OWNERSHIP_CHANGE:
+ return InterruptState.OwnerChangedInt;
+ break;
+
+ case MASTER_INTERRUPT:
+ return InterruptState.MasterInterruptEnable;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set memory pointer of specific type
+
+ @param Ohc UHC private data
+ @param PointerType Type of the pointer to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Memory pointer set
+
+**/
+
+EFI_STATUS
+OhciSetMemoryPointer(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN PointerType,
+ IN VOID *Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Verify;
+
+ Status = OhciSetOperationalReg (Ohc, PointerType, (UINT32*)&Value);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Verify = OhciGetOperationalReg (Ohc, PointerType);
+
+ while (Verify != (UINT32) Value) {
+ MicroSecondDelay (HC_1_MILLISECOND);
+ Verify = OhciGetOperationalReg (Ohc, PointerType);
+ };
+
+
+ return Status;
+}
+
+/**
+
+ Get memory pointer of specific type
+
+ @param Ohc UHC private data
+ @param PointerType Type of pointer
+
+ @retval Memory pointer of the specific type
+
+**/
+
+VOID *
+OhciGetMemoryPointer (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN PointerType
+ )
+{
+
+ return (VOID *) OhciGetOperationalReg (Ohc, PointerType);
+}
+
+
+/**
+
+ Set Frame Interval value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameInterval (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcFRM_INTERVAL FrameInterval;
+
+
+ *(UINT32 *) &FrameInterval = OhciGetOperationalReg(Ohc, HC_FRM_INTERVAL);
+
+ if (Field & FRAME_INTERVAL) {
+ FrameInterval.FrmIntervalToggle = !FrameInterval.FrmIntervalToggle;
+ FrameInterval.FrameInterval = Value;
+ }
+
+ if (Field & FS_LARGEST_DATA_PACKET) {
+ FrameInterval.FSMaxDataPacket = Value;
+ }
+
+ if (Field & FRMINT_TOGGLE) {
+ FrameInterval.FrmIntervalToggle = Value;
+ }
+
+ Status = OhciSetOperationalReg (
+ Ohc,
+ HC_FRM_INTERVAL,
+ (UINT32*)&FrameInterval
+ );
+
+ return Status;
+}
+
+
+/**
+
+ Get field of frame interval reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetFrameInterval (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcFRM_INTERVAL FrameInterval;
+
+ *(UINT32 *) &FrameInterval = OhciGetOperationalReg (Ohc, HC_FRM_INTERVAL);
+
+ switch (Field){
+ case FRAME_INTERVAL:
+ return FrameInterval.FrameInterval;
+ break;
+
+ case FS_LARGEST_DATA_PACKET:
+ return FrameInterval.FSMaxDataPacket;
+ break;
+
+ case FRMINT_TOGGLE:
+ return FrameInterval.FrmIntervalToggle;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set Frame Remaining reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameRemaining (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcFRAME_REMAINING FrameRemaining;
+
+
+ *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc, HC_FRM_REMAINING);
+
+ FrameRemaining.FrameRemaining = Value;
+ FrameRemaining.FrameRemainingToggle = !FrameRemaining.FrameRemainingToggle;
+
+ Status = OhciSetOperationalReg (Ohc, HC_FRM_REMAINING, (UINT32*)&FrameRemaining);
+
+ return Status;
+}
+/**
+
+ Get value of frame remaining reg
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of frame remaining reg
+
+**/
+UINT32
+OhciGetFrameRemaining (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+
+{
+ HcFRAME_REMAINING FrameRemaining;
+
+
+ *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc, HC_FRM_REMAINING);
+
+ switch (Field){
+ case FRAME_REMAINING:
+ return FrameRemaining.FrameRemaining;
+ break;
+
+ case FRAME_REMAIN_TOGGLE:
+ return FrameRemaining.FrameRemainingToggle;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+/**
+
+ Set frame number reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameNumber(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+ Status = OhciSetOperationalReg (Ohc, HC_FRM_NUMBER, &Value);
+
+ return Status;
+}
+
+/**
+
+ Get frame number reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of frame number reg
+
+**/
+
+UINT32
+OhciGetFrameNumber (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ return OhciGetOperationalReg(Ohc, HC_FRM_NUMBER);
+}
+
+/**
+
+ Set period start reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetPeriodicStart (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+
+ Status = OhciSetOperationalReg (Ohc, HC_PERIODIC_START, &Value);
+
+ return Status;
+}
+
+
+/**
+
+ Get periodic start reg value
+
+ @param Ohc UHC private data
+
+ @param Value of periodic start reg
+
+**/
+
+UINT32
+OhciGetPeriodicStart (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ return OhciGetOperationalReg(Ohc, HC_PERIODIC_START);
+}
+
+
+/**
+
+ Set Ls Threshold reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetLsThreshold (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+
+ Status = OhciSetOperationalReg (Ohc, HC_PERIODIC_START, &Value);
+
+ return Status;
+}
+
+
+/**
+
+ Get Ls Threshold reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of Ls Threshold reg
+
+**/
+
+UINT32
+OhciGetLsThreshold (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ return OhciGetOperationalReg(Ohc, HC_PERIODIC_START);
+}
+
+/**
+
+ Set Root Hub Descriptor reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetRootHubDescriptor (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ HcRH_DESC_A DescriptorA;
+ HcRH_DESC_B DescriptorB;
+
+
+ if (Field & (RH_DEV_REMOVABLE || RH_PORT_PWR_CTRL_MASK)) {
+ *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc, HC_RH_DESC_B);
+
+ if(Field & RH_DEV_REMOVABLE) {
+ DescriptorB.DeviceRemovable = Value;
+ }
+ if(Field & RH_PORT_PWR_CTRL_MASK) {
+ DescriptorB.PortPowerControlMask = Value;
+ }
+
+ Status = OhciSetOperationalReg (Ohc, HC_RH_DESC_B, (UINT32*)&DescriptorB);
+
+ return Status;
+ }
+
+ *(UINT32 *)&DescriptorA = OhciGetOperationalReg (Ohc, HC_RH_DESC_A);
+
+ if(Field & RH_NUM_DS_PORTS) {
+ DescriptorA.NumDownStrmPorts = Value;
+ }
+ if(Field & RH_NO_PSWITCH) {
+ DescriptorA.NoPowerSwitch = Value;
+ }
+ if(Field & RH_PSWITCH_MODE) {
+ DescriptorA.PowerSwitchMode = Value;
+ }
+ if(Field & RH_DEVICE_TYPE) {
+ DescriptorA.DeviceType = Value;
+ }
+ if(Field & RH_OC_PROT_MODE) {
+ DescriptorA.OverCurrentProtMode = Value;
+ }
+ if(Field & RH_NOC_PROT) {
+ DescriptorA.NoOverCurrentProtMode = Value;
+ }
+ if(Field & RH_NO_POTPGT) {
+ DescriptorA.PowerOnToPowerGoodTime = Value;
+ }
+
+ Status = OhciSetOperationalReg (Ohc, HC_RH_DESC_A, (UINT32*)&DescriptorA);
+
+ return Status;
+}
+
+
+/**
+
+ Get Root Hub Descriptor reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetRootHubDescriptor (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcRH_DESC_A DescriptorA;
+ HcRH_DESC_B DescriptorB;
+
+
+ *(UINT32 *) &DescriptorA = OhciGetOperationalReg (Ohc, HC_RH_DESC_A);
+ *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc, HC_RH_DESC_B);
+
+ switch (Field){
+ case RH_DEV_REMOVABLE:
+ return DescriptorB.DeviceRemovable;
+ break;
+
+ case RH_PORT_PWR_CTRL_MASK:
+ return DescriptorB.PortPowerControlMask;
+ break;
+
+ case RH_NUM_DS_PORTS:
+ return DescriptorA.NumDownStrmPorts;
+ break;
+
+ case RH_NO_PSWITCH:
+ return DescriptorA.NoPowerSwitch;
+ break;
+
+ case RH_PSWITCH_MODE:
+ return DescriptorA.PowerSwitchMode;
+ break;
+
+ case RH_DEVICE_TYPE:
+ return DescriptorA.DeviceType;
+ break;
+
+ case RH_OC_PROT_MODE:
+ return DescriptorA.OverCurrentProtMode;
+ break;
+
+ case RH_NOC_PROT:
+ return DescriptorA.NoOverCurrentProtMode;
+ break;
+
+ case RH_NO_POTPGT:
+ return DescriptorA.PowerOnToPowerGoodTime;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+
+/**
+
+ Set Root Hub Status reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetRootHubStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ EFI_STATUS Status;
+ HcRH_STATUS RootHubStatus;
+
+
+ ZeroMem (&RootHubStatus, sizeof(HcRH_STATUS));
+
+ if(Field & RH_LOCAL_PSTAT){
+ RootHubStatus.LocalPowerStat = 1;
+ }
+ if(Field & RH_OC_ID){
+ RootHubStatus.OverCurrentIndicator = 1;
+ }
+ if(Field & RH_REMOTE_WK_ENABLE){
+ RootHubStatus.DevRemoteWakeupEnable = 1;
+ }
+ if(Field & RH_LOCAL_PSTAT_CHANGE){
+ RootHubStatus.LocalPowerStatChange = 1;
+ }
+ if(Field & RH_OC_ID_CHANGE){
+ RootHubStatus.OverCurrentIndicatorChange = 1;
+ }
+ if(Field & RH_CLR_RMT_WK_ENABLE){
+ RootHubStatus.ClearRemoteWakeupEnable = 1;
+ }
+
+ Status = OhciSetOperationalReg (Ohc, HC_RH_STATUS, (UINT32*)&RootHubStatus);
+
+ return Status;
+}
+
+
+/**
+
+ Get Root Hub Status reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetRootHubStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ )
+{
+ HcRH_STATUS RootHubStatus;
+
+
+ *(UINT32 *) &RootHubStatus = OhciGetOperationalReg (Ohc, HC_RH_STATUS);
+
+ switch (Field) {
+ case RH_LOCAL_PSTAT:
+ return RootHubStatus.LocalPowerStat;
+ break;
+ case RH_OC_ID:
+ return RootHubStatus.OverCurrentIndicator;
+ break;
+ case RH_REMOTE_WK_ENABLE:
+ return RootHubStatus.DevRemoteWakeupEnable;
+ break;
+ case RH_LOCAL_PSTAT_CHANGE:
+ return RootHubStatus.LocalPowerStatChange;
+ break;
+ case RH_OC_ID_CHANGE:
+ return RootHubStatus.OverCurrentIndicatorChange;
+ break;
+ case RH_CLR_RMT_WK_ENABLE:
+ return RootHubStatus.ClearRemoteWakeupEnable;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+
+/**
+
+ Set Root Hub Port Status reg value
+
+ @param Ohc UHC private data
+ @param Index Index of the port
+ @param Field Field to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetRootHubPortStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Index,
+ IN UINTN Field
+ )
+{
+ EFI_STATUS Status;
+ HcRHPORT_STATUS PortStatus;
+
+
+ ZeroMem (&PortStatus, sizeof(HcRHPORT_STATUS));
+
+ if (Field & RH_CLEAR_PORT_ENABLE) {
+ PortStatus.CurrentConnectStat = 1;
+ }
+ if (Field & RH_SET_PORT_ENABLE) {
+ PortStatus.EnableStat = 1;
+ }
+ if (Field & RH_SET_PORT_SUSPEND) {
+ PortStatus.SuspendStat = 1;
+ }
+ if (Field & RH_CLEAR_SUSPEND_STATUS) {
+ PortStatus.OCIndicator = 1;
+ }
+ if (Field & RH_SET_PORT_RESET) {
+ PortStatus.ResetStat = 1;
+ }
+ if (Field & RH_SET_PORT_POWER) {
+ PortStatus.PowerStat = 1;
+ }
+ if (Field & RH_CLEAR_PORT_POWER) {
+ PortStatus.LsDeviceAttached = 1;
+ }
+ if (Field & RH_CONNECT_STATUS_CHANGE) {
+ PortStatus.ConnectStatChange = 1;
+ }
+ if (Field & RH_PORT_ENABLE_STAT_CHANGE) {
+ PortStatus.EnableStatChange = 1;
+ }
+ if (Field & RH_PORT_SUSPEND_STAT_CHANGE) {
+ PortStatus.SuspendStatChange = 1;
+ }
+ if (Field & RH_OC_INDICATOR_CHANGE) {
+ PortStatus.OCIndicatorChange = 1;
+ }
+ if (Field & RH_PORT_RESET_STAT_CHANGE ) {
+ PortStatus.ResetStatChange = 1;
+ }
+
+ Status = OhciSetOperationalReg (Ohc, HC_RH_PORT_STATUS + (Index * 4), (UINT32*)&PortStatus);
+
+ return Status;
+}
+
+
+/**
+
+ Get Root Hub Port Status reg value
+
+ @param Ohc UHC private data
+ @param Index Index of the port
+ @param Field Field to get
+
+ @retval Value of the field and index
+
+**/
+
+UINT32
+OhciReadRootHubPortStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Index,
+ IN UINTN Field
+ )
+{
+ HcRHPORT_STATUS PortStatus;
+
+ *(UINT32 *) &PortStatus = OhciGetOperationalReg (
+ Ohc,
+ HC_RH_PORT_STATUS + (Index * 4)
+ );
+
+ switch (Field){
+ case RH_CURR_CONNECT_STAT:
+ return PortStatus.CurrentConnectStat;
+ break;
+ case RH_PORT_ENABLE_STAT:
+ return PortStatus.EnableStat;
+ break;
+ case RH_PORT_SUSPEND_STAT:
+ return PortStatus.SuspendStat;
+ break;
+ case RH_PORT_OC_INDICATOR:
+ return PortStatus.OCIndicator;
+ break;
+ case RH_PORT_RESET_STAT:
+ return PortStatus.ResetStat;
+ break;
+ case RH_PORT_POWER_STAT:
+ return PortStatus.PowerStat;
+ break;
+ case RH_LSDEVICE_ATTACHED:
+ return PortStatus.LsDeviceAttached;
+ break;
+ case RH_CONNECT_STATUS_CHANGE:
+ return PortStatus.ConnectStatChange;
+ break;
+ case RH_PORT_ENABLE_STAT_CHANGE:
+ return PortStatus.EnableStatChange;
+ break;
+ case RH_PORT_SUSPEND_STAT_CHANGE:
+ return PortStatus.SuspendStatChange;
+ break;
+ case RH_OC_INDICATOR_CHANGE:
+ return PortStatus.OCIndicatorChange;
+ break;
+ case RH_PORT_RESET_STAT_CHANGE:
+ return PortStatus.ResetStatChange;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.h
new file mode 100644
index 0000000..71dd71e
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.h
@@ -0,0 +1,899 @@
+/** @file
+ This file contains the definination for host controller
+ register operation routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#ifndef _OHCI_REGS_H
+#define _OHCI_REGS_H
+
+#define HC_STATE_RESET 0x0
+#define HC_STATE_RESUME 0x1
+#define HC_STATE_OPERATIONAL 0x2
+#define HC_STATE_SUSPEND 0x3
+
+#define PERIODIC_ENABLE 0x01
+#define ISOCHRONOUS_ENABLE 0x02
+#define CONTROL_ENABLE 0x04
+#define BULK_ENABLE 0x08
+#define CONTROL_BULK_RATIO 0x10
+
+#define HC_FUNCTIONAL_STATE 0x20
+#define INTERRUPT_ROUTING 0x40
+
+#define HC_RESET 0x01
+#define CONTROL_LIST_FILLED 0x02
+#define BULK_LIST_FILLED 0x04
+#define CHANGE_OWNER_REQUEST 0x08
+
+#define SCHEDULE_OVERRUN_COUNT 0x10
+
+#define SCHEDULE_OVERRUN 0x00001
+#define WRITEBACK_DONE_HEAD 0x00002
+#define START_OF_FRAME 0x00004
+#define RESUME_DETECT 0x00008
+#define UNRECOVERABLE_ERROR 0x00010
+#define FRAME_NUMBER_OVERFLOW 0x00020
+#define ROOTHUB_STATUS_CHANGE 0x00040
+#define OWNERSHIP_CHANGE 0x00080
+
+#define MASTER_INTERRUPT 0x00400
+
+#define CONTROL_HEAD 0x001
+#define BULK_HEAD 0x002
+#define DONE_HEAD 0x004
+
+#define Hc_HCCA 0x001
+#define Hc_PERIODIC_CURRENT 0x002
+#define Hc_CONTOL_HEAD 0x004
+#define Hc_CONTROL_CURRENT_PTR 0x008
+#define Hc_BULK_HEAD 0x010
+#define Hc_BULK_CURRENT_PTR 0x020
+#define Hc_DONE_HEAD 0x040
+
+#define FRAME_INTERVAL 0x008
+#define FS_LARGEST_DATA_PACKET 0x010
+#define FRMINT_TOGGLE 0x020
+#define FRAME_REMAINING 0x040
+#define FRAME_REMAIN_TOGGLE 0x080
+
+#define RH_DESC_A 0x00001
+#define RH_DESC_B 0x00002
+#define RH_NUM_DS_PORTS 0x00004
+#define RH_NO_PSWITCH 0x00008
+#define RH_PSWITCH_MODE 0x00010
+#define RH_DEVICE_TYPE 0x00020
+#define RH_OC_PROT_MODE 0x00040
+#define RH_NOC_PROT 0x00080
+#define RH_POTPGT 0x00100
+#define RH_NO_POTPGT 0x00200
+#define RH_DEV_REMOVABLE 0x00400
+#define RH_PORT_PWR_CTRL_MASK 0x00800
+
+#define RH_LOCAL_PSTAT 0x00001
+#define RH_OC_ID 0x00002
+#define RH_REMOTE_WK_ENABLE 0x00004
+#define RH_LOCAL_PSTAT_CHANGE 0x00008
+#define RH_OC_ID_CHANGE 0x00010
+#define RH_CLR_RMT_WK_ENABLE 0x00020
+
+#define RH_CLEAR_PORT_ENABLE 0x0001
+#define RH_SET_PORT_ENABLE 0x0002
+#define RH_SET_PORT_SUSPEND 0x0004
+#define RH_CLEAR_SUSPEND_STATUS 0x0008
+#define RH_SET_PORT_RESET 0x0010
+#define RH_SET_PORT_POWER 0x0020
+#define RH_CLEAR_PORT_POWER 0x0040
+#define RH_CONNECT_STATUS_CHANGE 0x10000
+#define RH_PORT_ENABLE_STAT_CHANGE 0x20000
+#define RH_PORT_SUSPEND_STAT_CHANGE 0x40000
+#define RH_OC_INDICATOR_CHANGE 0x80000
+#define RH_PORT_RESET_STAT_CHANGE 0x100000
+
+#define RH_CURR_CONNECT_STAT 0x0001
+#define RH_PORT_ENABLE_STAT 0x0002
+#define RH_PORT_SUSPEND_STAT 0x0004
+#define RH_PORT_OC_INDICATOR 0x0008
+#define RH_PORT_RESET_STAT 0x0010
+#define RH_PORT_POWER_STAT 0x0020
+#define RH_LSDEVICE_ATTACHED 0x0040
+
+#define RESET_SYSTEM_BUS (1 << 0)
+#define RESET_HOST_CONTROLLER (1 << 1)
+#define RESET_CLOCK_GENERATION (1 << 2)
+#define RESET_SSE_GLOBAL (1 << 5)
+#define RESET_PSPL (1 << 6)
+#define RESET_PCPL (1 << 7)
+#define RESET_SSEP1 (1 << 9)
+#define RESET_SSEP2 (1 << 10)
+#define RESET_SSEP3 (1 << 11)
+
+#define ONE_SECOND 1000000
+#define ONE_MILLI_SEC 1000
+#define MAX_BYTES_PER_TD 0x1000
+#define MAX_RETRY_TIMES 100
+#define PORT_NUMBER_ON_MAINSTONE2 1
+
+
+//
+// Operational Register Offsets
+//
+
+//
+// Command & Status Registers Offsets
+//
+#define HC_REVISION 0x00
+#define HC_CONTROL 0x04
+#define HC_COMMAND_STATUS 0x08
+#define HC_INTERRUPT_STATUS 0x0C
+#define HC_INTERRUPT_ENABLE 0x10
+#define HC_INTERRUPT_DISABLE 0x14
+
+//
+// Memory Pointer Offsets
+//
+#define HC_HCCA 0x18
+#define HC_PERIODIC_CURRENT 0x1C
+#define HC_CONTROL_HEAD 0x20
+#define HC_CONTROL_CURRENT_PTR 0x24
+#define HC_BULK_HEAD 0x28
+#define HC_BULK_CURRENT_PTR 0x2C
+#define HC_DONE_HEAD 0x30
+
+//
+// Frame Register Offsets
+//
+#define HC_FRM_INTERVAL 0x34
+#define HC_FRM_REMAINING 0x38
+#define HC_FRM_NUMBER 0x3C
+#define HC_PERIODIC_START 0x40
+#define HC_LS_THREASHOLD 0x44
+
+//
+// Root Hub Register Offsets
+//
+#define HC_RH_DESC_A 0x48
+#define HC_RH_DESC_B 0x4C
+#define HC_RH_STATUS 0x50
+#define HC_RH_PORT_STATUS 0x54
+
+#define USBHOST_OFFSET_UHCHR 0x64 // Usb Host reset register
+
+#define OHC_BAR_INDEX 0
+
+//
+// Usb Host controller register offset
+//
+#define USBHOST_OFFSET_UHCREV 0x0 // Usb Host revision register
+#define USBHOST_OFFSET_UHCHCON 0x4 // Usb Host control register
+#define USBHOST_OFFSET_UHCCOMS 0x8 // Usb Host Command Status register
+#define USBHOST_OFFSET_UHCINTS 0xC // Usb Host Interrupt Status register
+#define USBHOST_OFFSET_UHCINTE 0x10 // Usb Host Interrupt Enable register
+#define USBHOST_OFFSET_UHCINTD 0x14 // Usb Host Interrupt Disable register
+#define USBHOST_OFFSET_UHCHCCA 0x18 // Usb Host Controller Communication Area
+#define USBHOST_OFFSET_UHCPCED 0x1C // Usb Host Period Current Endpoint Descriptor
+#define USBHOST_OFFSET_UHCCHED 0x20 // Usb Host Control Head Endpoint Descriptor
+#define USBHOST_OFFSET_UHCCCED 0x24 // Usb Host Control Current Endpoint Descriptor
+#define USBHOST_OFFSET_UHCBHED 0x28 // Usb Host Bulk Head Endpoint Descriptor
+#define USBHOST_OFFSET_UHCBCED 0x2C // Usb Host Bulk Current Endpoint Descriptor
+#define USBHOST_OFFSET_UHCDHEAD 0x30 // Usb Host Done Head register
+#define USBHOST_OFFSET_UHCFMI 0x34 // Usb Host Frame Interval register
+#define USBHOST_OFFSET_UHCFMR 0x38 // Usb Host Frame Remaining register
+#define USBHOST_OFFSET_UHCFMN 0x3C // Usb Host Frame Number register
+#define USBHOST_OFFSET_UHCPERS 0x40 // Usb Host Periodic Start register
+#define USBHOST_OFFSET_UHCLST 0x44 // Usb Host Low-Speed Threshold register
+#define USBHOST_OFFSET_UHCRHDA 0x48 // Usb Host Root Hub Descriptor A register
+#define USBHOST_OFFSET_UHCRHDB 0x4C // Usb Host Root Hub Descriptor B register
+#define USBHOST_OFFSET_UHCRHS 0x50 // Usb Host Root Hub Status register
+#define USBHOST_OFFSET_UHCRHPS1 0x54 // Usb Host Root Hub Port Status 1 register
+
+//
+// Usb Host controller register bit fields
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 ProgInterface;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} USB_CLASSC;
+
+typedef struct {
+ UINT32 Revision:8;
+ UINT32 Rsvd:24;
+} HcREVISION;
+
+typedef struct {
+ UINT32 ControlBulkRatio:2;
+ UINT32 PeriodicEnable:1;
+ UINT32 IsochronousEnable:1;
+ UINT32 ControlEnable:1;
+ UINT32 BulkEnable:1;
+ UINT32 FunctionalState:2;
+ UINT32 InterruptRouting:1;
+ UINT32 RemoteWakeup:1;
+ UINT32 RemoteWakeupEnable:1;
+ UINT32 Reserved:21;
+} HcCONTROL;
+
+typedef struct {
+ UINT32 HcReset:1;
+ UINT32 ControlListFilled:1;
+ UINT32 BulkListFilled:1;
+ UINT32 ChangeOwnerRequest:1;
+ UINT32 Reserved1:12;
+ UINT32 ScheduleOverrunCount:2;
+ UINT32 Reserved:14;
+} HcCOMMAND_STATUS;
+
+typedef struct {
+ UINT32 SchedulingOverrun:1;
+ UINT32 WriteBackDone:1;
+ UINT32 Sof:1;
+ UINT32 ResumeDetected:1;
+ UINT32 UnrecoverableError:1;
+ UINT32 FrameNumOverflow:1;
+ UINT32 RHStatusChange:1;
+ UINT32 Reserved1:23;
+ UINT32 OwnerChange:1;
+ UINT32 Reserved2:1;
+} HcINTERRUPT_STATUS;
+
+typedef struct {
+ UINT32 SchedulingOverrunInt:1;
+ UINT32 WriteBackDoneInt:1;
+ UINT32 SofInt:1;
+ UINT32 ResumeDetectedInt:1;
+ UINT32 UnrecoverableErrorInt:1;
+ UINT32 FrameNumOverflowInt:1;
+ UINT32 RHStatusChangeInt:1;
+ UINT32 Reserved:23;
+ UINT32 OwnerChangedInt:1;
+ UINT32 MasterInterruptEnable:1;
+} HcINTERRUPT_CONTROL;
+
+typedef struct {
+ UINT32 Rerserved:8;
+ UINT32 Hcca:24;
+} HcHCCA;
+
+typedef struct {
+ UINT32 Reserved:4;
+ UINT32 MemoryPtr:28;
+} HcMEMORY_PTR;
+
+typedef struct {
+ UINT32 FrameInterval:14;
+ UINT32 Reserved:2;
+ UINT32 FSMaxDataPacket:15;
+ UINT32 FrmIntervalToggle:1;
+} HcFRM_INTERVAL;
+
+typedef struct {
+ UINT32 FrameRemaining:14;
+ UINT32 Reserved:17;
+ UINT32 FrameRemainingToggle:1;
+} HcFRAME_REMAINING;
+
+typedef struct {
+ UINT32 FrameNumber:16;
+ UINT32 Reserved:16;
+} HcFRAME_NUMBER;
+
+typedef struct {
+ UINT32 PeriodicStart:14;
+ UINT32 Reserved:18;
+} HcPERIODIC_START;
+
+typedef struct {
+ UINT32 LsThreshold:12;
+ UINT32 Reserved:20;
+} HcLS_THRESHOLD;
+
+typedef struct {
+ UINT32 NumDownStrmPorts:8;
+ UINT32 PowerSwitchMode:1;
+ UINT32 NoPowerSwitch:1;
+ UINT32 DeviceType:1;
+ UINT32 OverCurrentProtMode:1;
+ UINT32 NoOverCurrentProtMode:1;
+ UINT32 Reserved:11;
+ UINT32 PowerOnToPowerGoodTime:8;
+} HcRH_DESC_A;
+
+typedef struct {
+ UINT32 DeviceRemovable:16;
+ UINT32 PortPowerControlMask:16;
+} HcRH_DESC_B;
+
+typedef struct {
+ UINT32 LocalPowerStat:1;
+ UINT32 OverCurrentIndicator:1;
+ UINT32 Reserved1:13;
+ UINT32 DevRemoteWakeupEnable:1;
+ UINT32 LocalPowerStatChange:1;
+ UINT32 OverCurrentIndicatorChange:1;
+ UINT32 Reserved2:13;
+ UINT32 ClearRemoteWakeupEnable:1;
+} HcRH_STATUS;
+
+typedef struct {
+ UINT32 CurrentConnectStat:1;
+ UINT32 EnableStat:1;
+ UINT32 SuspendStat:1;
+ UINT32 OCIndicator:1;
+ UINT32 ResetStat:1;
+ UINT32 Reserved1:3;
+ UINT32 PowerStat:1;
+ UINT32 LsDeviceAttached:1;
+ UINT32 Reserved2:6;
+ UINT32 ConnectStatChange:1;
+ UINT32 EnableStatChange:1;
+ UINT32 SuspendStatChange:1;
+ UINT32 OCIndicatorChange:1;
+ UINT32 ResetStatChange:1;
+ UINT32 Reserved3:11;
+} HcRHPORT_STATUS;
+
+typedef struct {
+ UINT32 FSBIR:1;
+ UINT32 FHR:1;
+ UINT32 CGR:1;
+ UINT32 SSDC:1;
+ UINT32 UIT:1;
+ UINT32 SSE:1;
+ UINT32 PSPL:1;
+ UINT32 PCPL:1;
+ UINT32 Reserved0:1;
+ UINT32 SSEP1:1;
+ UINT32 SSEP2:1;
+ UINT32 SSEP3:1;
+ UINT32 Reserved1:20;
+} HcRESET;
+
+#pragma pack()
+
+//
+// Func List
+//
+/**
+
+ Get OHCI operational reg value
+
+ @param Ohc UHC private data
+ @param Offset Offset of the operational reg
+
+ @retval Value of the register
+
+**/
+UINT32
+OhciGetOperationalReg (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Offset
+ );
+/**
+
+ Set OHCI operational reg value
+
+ @param Ohc UHC private data
+ @param Offset Offset of the operational reg
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set to the reg
+
+**/
+EFI_STATUS
+OhciSetOperationalReg (
+ USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Offset,
+ IN UINT32 *Value
+ );
+/**
+
+ Get HcRevision reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of the register
+
+**/
+
+
+UINT32
+OhciGetHcRevision (
+ USB_OHCI_HC_DEV *Ohc
+ );
+
+/**
+
+ Set HcReset reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcReset (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Field,
+ IN UINT32 Value
+ );
+/**
+
+ Get specific field of HcReset reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcReset (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Field
+ );
+/**
+
+ Set HcControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+/**
+
+ Get specific field of HcControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+
+UINT32
+OhciGetHcControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Set HcCommand reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetHcCommandStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+/**
+
+ Get specific field of HcCommand reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcCommandStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Clear specific fields of Interrupt Status
+
+ @param Ohc UHC private data
+ @param Field Field to clear
+
+ @retval EFI_SUCCESS Fields cleared
+
+**/
+
+EFI_STATUS
+OhciClearInterruptStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Get fields of HcInterrupt reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcInterruptStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Set Interrupt Control reg value
+
+ @param Ohc UHC private data
+ @param StatEnable Enable or Disable
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetInterruptControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN BOOLEAN StatEnable,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+/**
+
+ Get field of HcInterruptControl reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetHcInterruptControl (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Set memory pointer of specific type
+
+ @param Ohc UHC private data
+ @param PointerType Type of the pointer to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Memory pointer set
+
+**/
+
+EFI_STATUS
+OhciSetMemoryPointer(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN PointerType,
+ IN VOID *Value
+ );
+/**
+
+ Get memory pointer of specific type
+
+ @param Ohc UHC private data
+ @param PointerType Type of pointer
+
+ @retval Memory pointer of the specific type
+
+**/
+
+VOID *
+OhciGetMemoryPointer (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN PointerType
+ );
+/**
+
+ Set Frame Interval value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameInterval (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+/**
+
+ Get field of frame interval reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetFrameInterval (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Set Frame Remaining reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameRemaining (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ );
+/**
+
+ Get value of frame remaining reg
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of frame remaining reg
+
+**/
+UINT32
+OhciGetFrameRemaining (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Set frame number reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetFrameNumber(
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ );
+/**
+
+ Get frame number reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of frame number reg
+
+**/
+
+UINT32
+OhciGetFrameNumber (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+/**
+
+ Set period start reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetPeriodicStart (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ );
+/**
+
+ Get periodic start reg value
+
+ @param Ohc UHC private data
+
+ @param Value of periodic start reg
+
+**/
+
+UINT32
+OhciGetPeriodicStart (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+/**
+
+ Set Ls Threshold reg value
+
+ @param Ohc UHC private data
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetLsThreshold (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Value
+ );
+/**
+
+ Get Ls Threshold reg value
+
+ @param Ohc UHC private data
+
+ @retval Value of Ls Threshold reg
+
+**/
+
+UINT32
+OhciGetLsThreshold (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+/**
+
+ Set Root Hub Descriptor reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+ @param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetRootHubDescriptor (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field,
+ IN UINT32 Value
+ );
+/**
+
+ Get Root Hub Descriptor reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetRootHubDescriptor (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Set Root Hub Status reg value
+
+ @param Ohc UHC private data
+ @param Field Field to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetRootHubStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Get Root Hub Status reg value
+
+ @param Ohc UHC private data
+ @param Field Field to get
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetRootHubStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINTN Field
+ );
+/**
+
+ Set Root Hub Port Status reg value
+
+ @param Ohc UHC private data
+ @param Index Index of the port
+ @param Field Field to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+
+EFI_STATUS
+OhciSetRootHubPortStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Index,
+ IN UINTN Field
+ );
+/**
+
+ Get Root Hub Port Status reg value
+
+ @param Ohc UHC private data
+ @param Index Index of the port
+ @param Field Field to get
+
+ @retval Value of the field and index
+
+**/
+
+UINT32
+OhciReadRootHubPortStatus (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN UINT32 Index,
+ IN UINTN Field
+ );
+
+#endif \ No newline at end of file
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.c
new file mode 100644
index 0000000..948a414
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.c
@@ -0,0 +1,247 @@
+/** @file
+ OHCI transfer scheduling routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "OhcPeim.h"
+
+/**
+
+ Convert Error code from OHCI format to EFI format
+
+ @Param ErrorCode ErrorCode in OHCI format
+
+ @retval ErrorCode in EFI format
+
+**/
+UINT32
+ConvertErrorCode (
+ IN UINT32 ErrorCode
+ )
+{
+ UINT32 TransferResult;
+
+ switch (ErrorCode) {
+ case TD_NO_ERROR:
+ TransferResult = EFI_USB_NOERROR;
+ break;
+
+ case TD_TOBE_PROCESSED:
+ case TD_TOBE_PROCESSED_2:
+ TransferResult = EFI_USB_ERR_NOTEXECUTE;
+ break;
+
+ case TD_DEVICE_STALL:
+ TransferResult = EFI_USB_ERR_STALL;
+ break;
+
+ case TD_BUFFER_OVERRUN:
+ case TD_BUFFER_UNDERRUN:
+ TransferResult = EFI_USB_ERR_BUFFER;
+ break;
+
+ case TD_CRC_ERROR:
+ TransferResult = EFI_USB_ERR_CRC;
+ break;
+
+ case TD_NO_RESPONSE:
+ TransferResult = EFI_USB_ERR_TIMEOUT;
+ break;
+
+ case TD_BITSTUFFING_ERROR:
+ TransferResult = EFI_USB_ERR_BITSTUFF;
+ break;
+
+ default:
+ TransferResult = EFI_USB_ERR_SYSTEM;
+ }
+
+ return TransferResult;
+}
+
+
+/**
+
+ Check TDs Results
+
+ @Param Ohc UHC private data
+ @Param Td TD_DESCRIPTOR
+ @Param Result Result to return
+
+ @retval TRUE means OK
+ @retval FLASE means Error or Short packet
+
+**/
+BOOLEAN
+OhciCheckTDsResults (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN TD_DESCRIPTOR *Td,
+ OUT UINT32 *Result
+ )
+{
+ UINT32 TdCompletionCode;
+
+ *Result = EFI_USB_NOERROR;
+
+ while (Td) {
+ TdCompletionCode = Td->Word0.ConditionCode;
+
+ *Result |= ConvertErrorCode(TdCompletionCode);
+ //
+ // if any error encountered, stop processing the left TDs.
+ //
+ if (*Result) {
+ return FALSE;
+ }
+
+ Td = Td->NextTDPointer;
+ }
+ return TRUE;
+
+}
+
+
+/**
+
+ Check the task status on an ED
+
+ @Param Ed Pointer to the ED task that TD hooked on
+ @Param HeadTd TD header for current transaction
+
+ @retval Task Status Code
+
+**/
+
+UINT32
+CheckEDStatus (
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd
+ )
+{
+ while(HeadTd != NULL) {
+ if (HeadTd->Word0.ConditionCode != 0) {
+ return HeadTd->Word0.ConditionCode;
+ }
+ HeadTd = HeadTd->NextTDPointer;
+ }
+
+ if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {
+ return TD_TOBE_PROCESSED;
+ }
+
+ return TD_NO_ERROR;
+}
+
+/**
+
+ Check the task status
+
+ @Param Ohc UHC private data
+ @Param ListType Pipe type
+ @Param Ed Pointer to the ED task hooked on
+ @Param HeadTd Head of TD corresponding to the task
+ @Param ErrorCode return the ErrorCode
+
+ @retval EFI_SUCCESS Task done
+ @retval EFI_NOT_READY Task on processing
+ @retval EFI_DEVICE_ERROR Some error occured
+
+**/
+EFI_STATUS
+CheckIfDone (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN DESCRIPTOR_LIST_TYPE ListType,
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd,
+ OUT UINT32 *ErrorCode
+ )
+{
+ *ErrorCode = TD_TOBE_PROCESSED;
+
+ switch (ListType) {
+ case CONTROL_LIST:
+ if (OhciGetHcCommandStatus (Ohc, CONTROL_LIST_FILLED) != 0) {
+ return EFI_NOT_READY;
+ }
+ break;
+
+ case BULK_LIST:
+ if (OhciGetHcCommandStatus (Ohc, BULK_LIST_FILLED) != 0) {
+ return EFI_NOT_READY;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ *ErrorCode = CheckEDStatus (Ed, HeadTd);
+
+
+ if (*ErrorCode == TD_NO_ERROR) {
+ return EFI_SUCCESS;
+ } else if (*ErrorCode == TD_TOBE_PROCESSED) {
+ return EFI_NOT_READY;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+
+/**
+
+ Convert TD condition code to Efi Status
+
+ @Param ConditionCode Condition code to convert
+
+ @retval EFI_SUCCESS No error occured
+ @retval EFI_NOT_READY TD still on processing
+ @retval EFI_DEVICE_ERROR Error occured in processing TD
+
+**/
+
+EFI_STATUS
+OhciTDConditionCodeToStatus (
+ IN UINT32 ConditionCode
+ )
+{
+ if (ConditionCode == TD_NO_ERROR) {
+ return EFI_SUCCESS;
+ }
+
+ if (ConditionCode == TD_TOBE_PROCESSED) {
+ return EFI_NOT_READY;
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.h
new file mode 100644
index 0000000..57304e4
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.h
@@ -0,0 +1,132 @@
+/** @file
+ This file contains the definination for host controller schedule routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#ifndef _OHCI_SCHED_H
+#define _OHCI_SCHED_H
+
+#include "Descriptor.h"
+
+#define HCCA_MEM_SIZE 256
+#define GRID_SIZE 16
+#define GRID_SHIFT 4
+
+/**
+
+ Convert Error code from OHCI format to EFI format
+
+ @Param ErrorCode ErrorCode in OHCI format
+
+ @retval ErrorCode in EFI format
+
+**/
+UINT32
+ConvertErrorCode (
+ IN UINT32 ErrorCode
+ );
+/**
+
+ Check TDs Results
+
+ @Param Ohc UHC private data
+ @Param Td TD_DESCRIPTOR
+ @Param Result Result to return
+
+ @retval TRUE means OK
+ @retval FLASE means Error or Short packet
+
+**/
+BOOLEAN
+OhciCheckTDsResults (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN TD_DESCRIPTOR *Td,
+ OUT UINT32 *Result
+ );
+/**
+
+ Check the task status on an ED
+
+ @Param Ed Pointer to the ED task that TD hooked on
+ @Param HeadTd TD header for current transaction
+
+ @retval Task Status Code
+
+**/
+
+UINT32
+CheckEDStatus (
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd
+ );
+/**
+
+ Check the task status
+
+ @Param Ohc UHC private data
+ @Param ListType Pipe type
+ @Param Ed Pointer to the ED task hooked on
+ @Param HeadTd Head of TD corresponding to the task
+ @Param ErrorCode return the ErrorCode
+
+ @retval EFI_SUCCESS Task done
+ @retval EFI_NOT_READY Task on processing
+ @retval EFI_DEVICE_ERROR Some error occured
+
+**/
+EFI_STATUS
+CheckIfDone (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN DESCRIPTOR_LIST_TYPE ListType,
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd,
+ OUT UINT32 *ErrorCode
+ );
+/**
+
+ Convert TD condition code to Efi Status
+
+ @Param ConditionCode Condition code to convert
+
+ @retval EFI_SUCCESS No error occured
+ @retval EFI_NOT_READY TD still on processing
+ @retval EFI_DEVICE_ERROR Error occured in processing TD
+
+**/
+
+EFI_STATUS
+OhciTDConditionCodeToStatus (
+ IN UINT32 ConditionCode
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.c
new file mode 100644
index 0000000..8eb72a1
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.c
@@ -0,0 +1,584 @@
+/** @file
+ This file contains URB request, each request is warpped in a
+ URB (Usb Request Block).
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+
+#include "OhcPeim.h"
+
+
+/**
+
+ Create a TD
+
+ @Param Ohc UHC private data
+
+ @retval TD structure pointer
+
+**/
+TD_DESCRIPTOR *
+OhciCreateTD (
+ IN USB_OHCI_HC_DEV *Ohc
+ )
+{
+ TD_DESCRIPTOR *Td;
+
+ Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR));
+ if (Td == NULL) {
+ return NULL;
+ }
+ Td->CurrBufferPointer = NULL;
+ Td->NextTD = NULL;
+ Td->BufferEndPointer = NULL;
+ Td->NextTDPointer = NULL;
+
+ return Td;
+}
+
+
+/**
+
+ Free a TD
+
+ @Param Ohc UHC private data
+ @Param Td Pointer to a TD to free
+
+ @retval EFI_SUCCESS TD freed
+
+**/
+EFI_STATUS
+OhciFreeTD (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN TD_DESCRIPTOR *Td
+ )
+{
+ if (Td == NULL) {
+ return EFI_SUCCESS;
+ }
+ UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Create a ED
+
+ @Param Ohc Device private data
+
+ @retval ED descriptor pointer
+
+**/
+ED_DESCRIPTOR *
+OhciCreateED (
+ USB_OHCI_HC_DEV *Ohc
+ )
+{
+ ED_DESCRIPTOR *Ed;
+ Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));
+ if (Ed == NULL) {
+ return NULL;
+ }
+ Ed->Word0.Skip = 1;
+ Ed->TdTailPointer = NULL;
+ Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) NULL);
+ Ed->NextED = NULL;
+
+ return Ed;
+}
+
+/**
+
+ Free a ED
+
+ @Param Ohc UHC private data
+ @Param Ed Pointer to a ED to free
+
+ @retval EFI_SUCCESS ED freed
+
+**/
+
+EFI_STATUS
+OhciFreeED (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *Ed
+ )
+{
+ if (Ed == NULL) {
+ return EFI_SUCCESS;
+ }
+ UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Free ED
+
+ @Param Ohc Device private data
+ @Param Ed Pointer to a ED to free
+
+ @retval EFI_SUCCESS ED freed
+
+**/
+EFI_STATUS
+OhciFreeAllTDFromED (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *Ed
+ )
+{
+ TD_DESCRIPTOR *HeadTd;
+ TD_DESCRIPTOR *TailTd;
+ TD_DESCRIPTOR *Td;
+ TD_DESCRIPTOR *TempTd;
+
+ if (Ed == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);
+ TailTd = Ed->TdTailPointer;
+
+ Td = HeadTd;
+ while (Td != TailTd) {
+ TempTd = Td;
+ Td = Td->NextTDPointer;
+ OhciFreeTD (Ohc, TempTd);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Attach an ED
+
+ @Param Ed Ed to be attached
+ @Param NewEd Ed to attach
+
+ @retval EFI_SUCCESS NewEd attached to Ed
+ @retval EFI_INVALID_PARAMETER Ed is NULL
+
+**/
+EFI_STATUS
+OhciAttachED (
+ IN ED_DESCRIPTOR *Ed,
+ IN ED_DESCRIPTOR *NewEd
+ )
+{
+ ED_DESCRIPTOR *Temp;
+
+ if (Ed == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Ed->NextED == NULL){
+ Ed->NextED = NewEd;
+ } else {
+ Temp = Ed->NextED;
+ Ed->NextED = NewEd;
+ NewEd->NextED = Temp;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+
+ Attach an ED to an ED list
+
+ @Param OHC UHC private data
+ @Param ListType Type of the ED list
+ @Param Ed ED to attach
+ @Param EdList ED list to be attached
+
+ @retval EFI_SUCCESS ED attached to ED list
+
+**/
+EFI_STATUS
+OhciAttachEDToList (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN DESCRIPTOR_LIST_TYPE ListType,
+ IN ED_DESCRIPTOR *Ed,
+ IN ED_DESCRIPTOR *EdList
+ )
+{
+ ED_DESCRIPTOR *HeadEd;
+
+ switch(ListType) {
+ case CONTROL_LIST:
+ HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);
+ if (HeadEd == NULL) {
+ OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);
+ } else {
+ OhciAttachED (HeadEd, Ed);
+ }
+ break;
+
+ case BULK_LIST:
+ HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);
+ if (HeadEd == NULL) {
+ OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);
+ } else {
+ OhciAttachED (HeadEd, Ed);
+ }
+ break;
+
+ case INTERRUPT_LIST:
+ OhciAttachED (EdList, Ed);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+
+ Link Td2 to the end of Td1
+
+ @Param Td1 TD to be linked
+ @Param Td2 TD to link
+
+ @retval EFI_SUCCESS TD successfully linked
+ @retval EFI_INVALID_PARAMETER Td1 is NULL
+
+**/
+EFI_STATUS
+OhciLinkTD (
+ IN TD_DESCRIPTOR *Td1,
+ IN TD_DESCRIPTOR *Td2
+ )
+{
+ TD_DESCRIPTOR *TempTd;
+
+ if (Td1 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Td1 == Td2) {
+ return EFI_SUCCESS;
+ }
+
+ TempTd = Td1;
+ while (TempTd->NextTD != NULL) {
+ TempTd = TempTd->NextTD;
+ }
+
+ TempTd->NextTD = Td2;
+ TempTd->NextTDPointer = Td2;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Attach TD list to ED
+
+ @Param Ed ED which TD list attach on
+ @Param HeadTd Head of the TD list to attach
+
+ @retval EFI_SUCCESS TD list attached on the ED
+
+**/
+EFI_STATUS
+OhciAttachTDListToED (
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd
+ )
+{
+ TD_DESCRIPTOR *TempTd;
+
+ TempTd = TD_PTR (Ed->Word2.TdHeadPointer);
+
+ if (TempTd != NULL) {
+ while (TempTd->NextTD != NULL) {
+ TempTd = TempTd->NextTD;
+ }
+ TempTd->NextTD = HeadTd;
+ TempTd->NextTDPointer = HeadTd;
+ } else {
+ Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) HeadTd);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Set value to ED specific field
+
+ @Param Ed ED to be set
+ @Param Field Field to be set
+ @Param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetEDField (
+ IN ED_DESCRIPTOR *Ed,
+ IN UINT32 Field,
+ IN UINT32 Value
+ )
+{
+ if (Field & ED_FUNC_ADD) {
+ Ed->Word0.FunctionAddress = Value;
+ }
+ if (Field & ED_ENDPT_NUM) {
+ Ed->Word0.EndPointNum = Value;
+ }
+ if (Field & ED_DIR) {
+ Ed->Word0.Direction = Value;
+ }
+ if (Field & ED_SPEED) {
+ Ed->Word0.Speed = Value;
+ }
+ if (Field & ED_SKIP) {
+ Ed->Word0.Skip = Value;
+ }
+ if (Field & ED_FORMAT) {
+ Ed->Word0.Format = Value;
+ }
+ if (Field & ED_MAX_PACKET) {
+ Ed->Word0.MaxPacketSize = Value;
+ }
+ if (Field & ED_PDATA) {
+ Ed->Word0.FreeSpace = Value;
+ }
+ if (Field & ED_ZERO) {
+ Ed->Word2.Zero = Value;
+ }
+ if (Field & ED_TDTAIL_PTR) {
+ Ed->TdTailPointer = (VOID *) Value;
+ }
+
+ if (Field & ED_HALTED) {
+ Ed->Word2.Halted = Value;
+ }
+ if (Field & ED_DTTOGGLE) {
+ Ed->Word2.ToggleCarry = Value;
+ }
+ if (Field & ED_TDHEAD_PTR) {
+ Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);
+ }
+
+ if (Field & ED_NEXT_EDPTR) {
+ Ed->NextED = (VOID *) Value;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Get value from an ED's specific field
+
+ @Param Ed ED pointer
+ @Param Field Field to get value from
+
+ @retval Value of the field
+
+**/
+UINT32
+OhciGetEDField (
+ IN ED_DESCRIPTOR *Ed,
+ IN UINT32 Field
+ )
+{
+ switch (Field) {
+ case ED_FUNC_ADD:
+ return Ed->Word0.FunctionAddress;
+ break;
+ case ED_ENDPT_NUM:
+ return Ed->Word0.EndPointNum;
+ break;
+ case ED_DIR:
+ return Ed->Word0.Direction;
+ break;
+ case ED_SPEED:
+ return Ed->Word0.Speed;
+ break;
+ case ED_SKIP:
+ return Ed->Word0.Skip;
+ break;
+ case ED_FORMAT:
+ return Ed->Word0.Format;
+ break;
+ case ED_MAX_PACKET:
+ return Ed->Word0.MaxPacketSize;
+ break;
+
+ case ED_TDTAIL_PTR:
+ return (UINT32) Ed->TdTailPointer;
+ break;
+
+ case ED_HALTED:
+ return Ed->Word2.Halted;
+ break;
+
+ case ED_DTTOGGLE:
+ return Ed->Word2.ToggleCarry;
+ break;
+
+ case ED_TDHEAD_PTR:
+ return Ed->Word2.TdHeadPointer << 4;
+ break;
+
+ case ED_NEXT_EDPTR:
+ return (UINT32) Ed->NextED;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
+
+
+/**
+
+ Set value to TD specific field
+
+ @Param Td TD to be set
+ @Param Field Field to be set
+ @Param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetTDField (
+ IN TD_DESCRIPTOR *Td,
+ IN UINT32 Field,
+ IN UINT32 Value
+ )
+{
+ if (Field & TD_PDATA) {
+ Td->Word0.Reserved = Value;
+ }
+ if (Field & TD_BUFFER_ROUND) {
+ Td->Word0.BufferRounding = Value;
+ }
+ if (Field & TD_DIR_PID) {
+ Td->Word0.DirPID = Value;
+ }
+ if (Field & TD_DELAY_INT) {
+ Td->Word0.DelayInterrupt = Value;
+ }
+ if (Field & TD_DT_TOGGLE) {
+ Td->Word0.DataToggle = Value | 0x2;
+ }
+ if (Field & TD_ERROR_CNT) {
+ Td->Word0.ErrorCount = Value;
+ }
+ if (Field & TD_COND_CODE) {
+ Td->Word0.ConditionCode = Value;
+ }
+
+ if (Field & TD_CURR_BUFFER_PTR) {
+ Td->CurrBufferPointer = (VOID *) Value;
+ }
+
+
+ if (Field & TD_NEXT_PTR) {
+ Td->NextTD = (VOID *) Value;
+ }
+
+ if (Field & TD_BUFFER_END_PTR) {
+ Td->BufferEndPointer = (VOID *) Value;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Get value from ED specific field
+
+ @Param Td TD pointer
+ @Param Field Field to get value from
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetTDField (
+ IN TD_DESCRIPTOR *Td,
+ IN UINT32 Field
+ )
+{
+ switch (Field){
+ case TD_BUFFER_ROUND:
+ return Td->Word0.BufferRounding;
+ break;
+ case TD_DIR_PID:
+ return Td->Word0.DirPID;
+ break;
+ case TD_DELAY_INT:
+ return Td->Word0.DelayInterrupt;
+ break;
+ case TD_DT_TOGGLE:
+ return Td->Word0.DataToggle;
+ break;
+ case TD_ERROR_CNT:
+ return Td->Word0.ErrorCount;
+ break;
+ case TD_COND_CODE:
+ return Td->Word0.ConditionCode;
+ break;
+ case TD_CURR_BUFFER_PTR:
+ return (UINT32) Td->CurrBufferPointer;
+ break;
+
+ case TD_NEXT_PTR:
+ return (UINT32) Td->NextTD;
+ break;
+
+ case TD_BUFFER_END_PTR:
+ return (UINT32) Td->BufferEndPointer;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ return 0;
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.h
new file mode 100644
index 0000000..abba6fe
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.h
@@ -0,0 +1,255 @@
+/** @file
+ Provides some data struct used by OHCI controller driver.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#ifndef _OHCI_URB_H
+#define _OHCI_URB_H
+
+#include "Descriptor.h"
+
+
+//
+// Func List
+//
+
+
+/**
+
+ Create a TD
+
+ @Param Ohc UHC private data
+
+ @retval TD structure pointer
+
+**/
+TD_DESCRIPTOR *
+OhciCreateTD (
+ IN USB_OHCI_HC_DEV *Ohc
+ );
+
+/**
+
+ Free a TD
+
+ @Param Ohc UHC private data
+ @Param Td Pointer to a TD to free
+
+ @retval EFI_SUCCESS TD freed
+
+**/
+EFI_STATUS
+OhciFreeTD (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN TD_DESCRIPTOR *Td
+ );
+
+/**
+
+ Create a ED
+
+ @Param Ohc Device private data
+
+ @retval ED descriptor pointer
+
+**/
+ED_DESCRIPTOR *
+OhciCreateED (
+ USB_OHCI_HC_DEV *Ohc
+ );
+
+
+/**
+
+ Free a ED
+
+ @Param Ohc UHC private data
+ @Param Ed Pointer to a ED to free
+
+ @retval EFI_SUCCESS ED freed
+
+**/
+
+EFI_STATUS
+OhciFreeED (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *Ed
+ );
+
+/**
+
+ Free ED
+
+ @Param Ohc Device private data
+ @Param Ed Pointer to a ED to free
+
+ @retval EFI_SUCCESS ED freed
+
+**/
+EFI_STATUS
+OhciFreeAllTDFromED (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN ED_DESCRIPTOR *Ed
+ );
+
+/**
+
+ Attach an ED
+
+ @Param Ed Ed to be attached
+ @Param NewEd Ed to attach
+
+ @retval EFI_SUCCESS NewEd attached to Ed
+ @retval EFI_INVALID_PARAMETER Ed is NULL
+
+**/
+EFI_STATUS
+OhciAttachED (
+ IN ED_DESCRIPTOR *Ed,
+ IN ED_DESCRIPTOR *NewEd
+ );
+/**
+
+ Attach an ED to an ED list
+
+ @Param OHC UHC private data
+ @Param ListType Type of the ED list
+ @Param Ed ED to attach
+ @Param EdList ED list to be attached
+
+ @retval EFI_SUCCESS ED attached to ED list
+
+**/
+EFI_STATUS
+OhciAttachEDToList (
+ IN USB_OHCI_HC_DEV *Ohc,
+ IN DESCRIPTOR_LIST_TYPE ListType,
+ IN ED_DESCRIPTOR *Ed,
+ IN ED_DESCRIPTOR *EdList
+ );
+EFI_STATUS
+OhciLinkTD (
+ IN TD_DESCRIPTOR *Td1,
+ IN TD_DESCRIPTOR *Td2
+ );
+
+
+/**
+
+ Attach TD list to ED
+
+ @Param Ed ED which TD list attach on
+ @Param HeadTd Head of the TD list to attach
+
+ @retval EFI_SUCCESS TD list attached on the ED
+
+**/
+EFI_STATUS
+OhciAttachTDListToED (
+ IN ED_DESCRIPTOR *Ed,
+ IN TD_DESCRIPTOR *HeadTd
+ );
+
+
+/**
+
+ Set value to ED specific field
+
+ @Param Ed ED to be set
+ @Param Field Field to be set
+ @Param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetEDField (
+ IN ED_DESCRIPTOR *Ed,
+ IN UINT32 Field,
+ IN UINT32 Value
+ );
+
+
+/**
+
+ Get value from an ED's specific field
+
+ @Param Ed ED pointer
+ @Param Field Field to get value from
+
+ @retval Value of the field
+
+**/
+UINT32
+OhciGetEDField (
+ IN ED_DESCRIPTOR *Ed,
+ IN UINT32 Field
+ );
+
+
+/**
+
+ Set value to TD specific field
+
+ @Param Td TD to be set
+ @Param Field Field to be set
+ @Param Value Value to set
+
+ @retval EFI_SUCCESS Value set
+
+**/
+EFI_STATUS
+OhciSetTDField (
+ IN TD_DESCRIPTOR *Td,
+ IN UINT32 Field,
+ IN UINT32 Value
+ );
+
+
+/**
+
+ Get value from ED specific field
+
+ @Param Td TD pointer
+ @Param Field Field to get value from
+
+ @retval Value of the field
+
+**/
+
+UINT32
+OhciGetTDField (
+ IN TD_DESCRIPTOR *Td,
+ IN UINT32 Field
+ );
+
+#endif
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.c
new file mode 100644
index 0000000..4c93531
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.c
@@ -0,0 +1,517 @@
+/** @file
+ Routine procedures for memory allocate/free.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+
+#include "OhcPeim.h"
+
+
+/**
+ Allocate a block of memory to be used by the buffer pool.
+
+ Use Redirect memory services to allocate memmory so that USB DMA transfers do
+ not cause IMR violations on Quark.
+
+ @param Pool The buffer pool to allocate memory for.
+ @param Pages How many pages to allocate.
+
+ @return The allocated memory block or NULL if failed.
+
+**/
+USBHC_MEM_BLOCK *
+UsbHcAllocMemBlock (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Pages
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+ VOID *BufHost;
+ VOID *Mapping;
+ EFI_PHYSICAL_ADDRESS MappedAddr;
+ EFI_STATUS Status;
+ UINTN PageNumber;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+
+ Mapping = NULL;
+ PageNumber = sizeof(USBHC_MEM_BLOCK)/PAGESIZE +1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ PageNumber,
+ &TempPtr
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
+
+ //
+ // each bit in the bit array represents USBHC_MEM_UNIT
+ // bytes of memory in the memory block.
+ //
+ ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
+
+ Block = (USBHC_MEM_BLOCK*)(UINTN)TempPtr;
+ Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
+ Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
+
+ PageNumber = (Block->BitsLen)/PAGESIZE +1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ PageNumber,
+ &TempPtr
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
+
+ Block->Bits = (UINT8 *)(UINTN)TempPtr;
+
+ RedirectMemoryServicesEnable ();
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ Pages,
+ &TempPtr
+ );
+ RedirectMemoryServicesDisable ();
+ ZeroMem ((VOID *)(UINTN)TempPtr, Pages*EFI_PAGE_SIZE);
+
+ BufHost = (VOID *)(UINTN)TempPtr;
+ MappedAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) BufHost;
+ //
+ // Check whether the data structure used by the host controller
+ // should be restricted into the same 4G
+ //
+ if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {
+ return NULL;
+ }
+
+ Block->BufHost = BufHost;
+ Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
+ Block->Mapping = Mapping;
+ Block->Next = NULL;
+
+ return Block;
+
+}
+
+
+/**
+ Free the memory block from the memory pool.
+
+ @param Pool The memory pool to free the block from.
+ @param Block The memory block to free.
+
+**/
+VOID
+UsbHcFreeMemBlock (
+ IN USBHC_MEM_POOL *Pool,
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+
+ ASSERT ((Pool != NULL) && (Block != NULL));
+}
+
+
+/**
+ Alloc some memory from the block.
+
+ @param Block The memory block to allocate memory from.
+ @param Units Number of memory units to allocate.
+
+ @return The pointer to the allocated memory. If couldn't allocate the needed memory,
+ the return value is NULL.
+
+**/
+VOID *
+UsbHcAllocMemFromBlock (
+ IN USBHC_MEM_BLOCK *Block,
+ IN UINTN Units
+ )
+{
+ UINTN Byte;
+ UINT8 Bit;
+ UINTN StartByte;
+ UINT8 StartBit;
+ UINTN Available;
+ UINTN Count;
+
+ ASSERT ((Block != 0) && (Units != 0));
+
+ StartByte = 0;
+ StartBit = 0;
+ Available = 0;
+
+ for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
+ //
+ // If current bit is zero, the corresponding memory unit is
+ // available, otherwise we need to restart our searching.
+ // Available counts the consective number of zero bit.
+ //
+ if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
+ Available++;
+
+ if (Available >= Units) {
+ break;
+ }
+
+ NEXT_BIT (Byte, Bit);
+
+ } else {
+ NEXT_BIT (Byte, Bit);
+
+ Available = 0;
+ StartByte = Byte;
+ StartBit = Bit;
+ }
+ }
+
+ if (Available < Units) {
+ return NULL;
+ }
+
+ //
+ // Mark the memory as allocated
+ //
+ Byte = StartByte;
+ Bit = StartBit;
+
+ for (Count = 0; Count < Units; Count++) {
+ ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
+
+ Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));
+ NEXT_BIT (Byte, Bit);
+ }
+
+ return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
+}
+
+/**
+ Insert the memory block to the pool's list of the blocks.
+
+ @param Head The head of the memory pool's block list.
+ @param Block The memory block to insert.
+
+**/
+VOID
+UsbHcInsertMemBlockToPool (
+ IN USBHC_MEM_BLOCK *Head,
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ ASSERT ((Head != NULL) && (Block != NULL));
+ Block->Next = Head->Next;
+ Head->Next = Block;
+}
+
+
+/**
+ Is the memory block empty?
+
+ @param Block The memory block to check.
+
+ @retval TRUE The memory block is empty.
+ @retval FALSE The memory block isn't empty.
+
+**/
+BOOLEAN
+UsbHcIsMemBlockEmpty (
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < Block->BitsLen; Index++) {
+ if (Block->Bits[Index] != 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Unlink the memory block from the pool's list.
+
+ @param Head The block list head of the memory's pool.
+ @param BlockToUnlink The memory block to unlink.
+
+**/
+VOID
+UsbHcUnlinkMemBlock (
+ IN USBHC_MEM_BLOCK *Head,
+ IN USBHC_MEM_BLOCK *BlockToUnlink
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+
+ ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ if (Block->Next == BlockToUnlink) {
+ Block->Next = BlockToUnlink->Next;
+ BlockToUnlink->Next = NULL;
+ break;
+ }
+ }
+}
+
+
+/**
+ Initialize the memory management pool for the host controller.
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param Check4G Whether the host controller requires allocated memory
+ from one 4G address space.
+ @param Which4G The 4G memory area each memory allocated should be from.
+
+ @retval EFI_SUCCESS The memory pool is initialized.
+ @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
+
+**/
+USBHC_MEM_POOL *
+UsbHcInitMemPool (
+ IN BOOLEAN Check4G,
+ IN UINT32 Which4G
+ )
+{
+ USBHC_MEM_POOL *Pool;
+ UINTN PageNumber;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+
+ PageNumber = sizeof(USBHC_MEM_POOL)/PAGESIZE +1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ PageNumber,
+ &TempPtr
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
+
+ Pool = (USBHC_MEM_POOL *) ((UINTN) TempPtr);
+ Pool->Check4G = Check4G;
+ Pool->Which4G = Which4G;
+ Pool->Head = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);
+
+ if (Pool->Head == NULL) {
+ Pool = NULL;
+ }
+
+ return Pool;
+}
+
+
+/**
+ Release the memory management pool.
+
+ @param Pool The USB memory pool to free.
+
+ @retval EFI_SUCCESS The memory pool is freed.
+ @retval EFI_DEVICE_ERROR Failed to free the memory pool.
+
+**/
+EFI_STATUS
+UsbHcFreeMemPool (
+ IN USBHC_MEM_POOL *Pool
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+
+ ASSERT (Pool->Head != NULL);
+
+ //
+ // Unlink all the memory blocks from the pool, then free them.
+ // UsbHcUnlinkMemBlock can't be used to unlink and free the
+ // first block.
+ //
+ for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
+ UsbHcFreeMemBlock (Pool, Block);
+ }
+
+ UsbHcFreeMemBlock (Pool, Pool->Head);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Allocate some memory from the host controller's memory pool
+ which can be used to communicate with host controller.
+
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+
+ @return The allocated memory or NULL.
+
+**/
+VOID *
+UsbHcAllocateMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ USBHC_MEM_BLOCK *NewBlock;
+ VOID *Mem;
+ UINTN AllocSize;
+ UINTN Pages;
+
+ Mem = NULL;
+ AllocSize = USBHC_MEM_ROUND (Size);
+ Head = Pool->Head;
+ ASSERT (Head != NULL);
+
+ //
+ // First check whether current memory blocks can satisfy the allocation.
+ //
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
+
+ if (Mem != NULL) {
+ ZeroMem (Mem, Size);
+ break;
+ }
+ }
+
+ if (Mem != NULL) {
+ return Mem;
+ }
+
+ //
+ // Create a new memory block if there is not enough memory
+ // in the pool. If the allocation size is larger than the
+ // default page number, just allocate a large enough memory
+ // block. Otherwise allocate default pages.
+ //
+ if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
+ Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
+ } else {
+ Pages = USBHC_MEM_DEFAULT_PAGES;
+ }
+
+ NewBlock = UsbHcAllocMemBlock (Pool, Pages);
+
+ if (NewBlock == NULL) {
+ DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));
+ return NULL;
+ }
+
+ //
+ // Add the new memory block to the pool, then allocate memory from it
+ //
+ UsbHcInsertMemBlockToPool (Head, NewBlock);
+ Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
+
+ if (Mem != NULL) {
+ ZeroMem (Mem, Size);
+ }
+
+ return Mem;
+}
+
+
+/**
+ Free the allocated memory back to the memory pool.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The memory to free.
+ @param Size The size of the memory to free.
+
+**/
+VOID
+UsbHcFreeMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ UINT8 *ToFree;
+ UINTN AllocSize;
+ UINTN Byte;
+ UINTN Bit;
+ UINTN Count;
+
+ Head = Pool->Head;
+ AllocSize = USBHC_MEM_ROUND (Size);
+ ToFree = (UINT8 *) Mem;
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ //
+ // scan the memory block list for the memory block that
+ // completely contains the memory to free.
+ //
+ if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {
+ //
+ // compute the start byte and bit in the bit array
+ //
+ Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;
+ Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;
+
+ //
+ // reset associated bits in bit arry
+ //
+ for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
+ ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
+
+ Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
+ NEXT_BIT (Byte, Bit);
+ }
+
+ break;
+ }
+ }
+
+ //
+ // If Block == NULL, it means that the current memory isn't
+ // in the host controller's pool. This is critical because
+ // the caller has passed in a wrong memory point
+ //
+ ASSERT (Block != NULL);
+
+ //
+ // Release the current memory block if it is empty and not the head
+ //
+ if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
+ UsbHcFreeMemBlock (Pool, Block);
+ }
+
+ return ;
+}
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.h
new file mode 100644
index 0000000..935ea96
--- /dev/null
+++ b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.h
@@ -0,0 +1,158 @@
+/** @file
+ This file contains the definination for host controller memory
+ management routines.
+
+Copyright (c) 2013 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Intel Corporation nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef _USB_HC_MEM_H_
+#define _USB_HC_MEM_H_
+
+#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
+
+#define USB_HC_BIT_IS_SET(Data, Bit) \
+ ((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
+
+#define USB_HC_HIGH_32BIT(Addr64) \
+ ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
+
+typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
+struct _USBHC_MEM_BLOCK {
+ UINT8 *Bits; // Bit array to record which unit is allocated
+ UINTN BitsLen;
+ UINT8 *Buf;
+ UINT8 *BufHost;
+ UINTN BufLen; // Memory size in bytes
+ VOID *Mapping;
+ USBHC_MEM_BLOCK *Next;
+};
+
+//
+// USBHC_MEM_POOL is used to manage the memory used by USB
+// host controller. EHCI requires the control memory and transfer
+// data to be on the same 4G memory.
+//
+typedef struct _USBHC_MEM_POOL {
+ BOOLEAN Check4G;
+ UINT32 Which4G;
+ USBHC_MEM_BLOCK *Head;
+} USBHC_MEM_POOL;
+
+//
+// Memory allocation unit, must be 2^n, n>4
+//
+#define USBHC_MEM_UNIT 64
+
+#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
+#define USBHC_MEM_DEFAULT_PAGES 16
+
+#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
+
+//
+// Advance the byte and bit to the next bit, adjust byte accordingly.
+//
+#define NEXT_BIT(Byte, Bit) \
+ do { \
+ (Bit)++; \
+ if ((Bit) > 7) { \
+ (Byte)++; \
+ (Bit) = 0; \
+ } \
+ } while (0)
+
+
+
+/**
+ Initialize the memory management pool for the host controller.
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param Check4G Whether the host controller requires allocated memory
+ from one 4G address space.
+ @param Which4G The 4G memory area each memory allocated should be from.
+
+ @retval EFI_SUCCESS The memory pool is initialized.
+ @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
+
+**/
+USBHC_MEM_POOL *
+UsbHcInitMemPool (
+ IN BOOLEAN Check4G,
+ IN UINT32 Which4G
+ );
+
+
+/**
+ Release the memory management pool.
+
+ @param Pool The USB memory pool to free.
+
+ @retval EFI_SUCCESS The memory pool is freed.
+ @retval EFI_DEVICE_ERROR Failed to free the memory pool.
+
+**/
+EFI_STATUS
+UsbHcFreeMemPool (
+ IN USBHC_MEM_POOL *Pool
+ );
+
+
+/**
+ Allocate some memory from the host controller's memory pool
+ which can be used to communicate with host controller.
+
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+
+ @return The allocated memory or NULL.
+
+**/
+VOID *
+UsbHcAllocateMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Size
+ );
+
+
+/**
+ Free the allocated memory back to the memory pool.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The memory to free.
+ @param Size The size of the memory to free.
+
+**/
+VOID
+UsbHcFreeMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ );
+
+#endif
diff --git a/buildallconfigs.sh b/buildallconfigs.sh
new file mode 100755
index 0000000..c8eb020
--- /dev/null
+++ b/buildallconfigs.sh
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+# This script is used to build all sets of config options
+
+set -e
+
+die()
+{
+ >&2 printf "$@"
+ exit 1
+}
+
+
+if [ $# -eq 0 ]; then
+ die "%s [GCC4x] [Platform name]\n" "$0"
+ exit 1
+fi
+
+
+# This is required when building with -DTPM_SUPPORT (or for EFI secure
+# boot). Save users vain build time and a more cryptic (!) error
+# message
+ossl_dir=CryptoPkg/Library/OpensslLib/openssl-0.9.8w
+
+test -d "${ossl_dir}" ||
+ die 'Missing OpenSSL dir %s
+Please follow instructions in CryptoPkg/Library/OpensslLib/Patch-HOWTO.txt\n' "${ossl_dir}"
+
+
+# Arrays require bash
+FLAVOUR=([0]='PLAIN' [1]='SECURE')
+ARG=( [0]='' [1]='-DSECURE_LD -DTPM_SUPPORT')
+
+
+set -x
+for num in 0 1; do
+ ./quarkbuild.sh -d32 "$@" ${ARG[$num]}
+ ./quarkbuild.sh -r32 "$@" ${ARG[$num]}
+ (
+ set -e
+ cd Build/*Platform/
+ mkdir ${FLAVOUR[$num]}/
+ ln -s RELEASE_GCC* RELEASE_GCC
+ ln -s DEBUG_GCC* DEBUG_GCC
+ mv RELEASE_GCC* DEBUG_GCC* ${FLAVOUR[$num]}/
+ )
+done
+
diff --git a/edksetup.bat b/edksetup.bat
new file mode 100644
index 0000000..509c198
--- /dev/null
+++ b/edksetup.bat
@@ -0,0 +1,171 @@
+@REM @file
+@REM Windows batch file to setup a WORKSPACE environment
+@REM
+@REM Copyright (c) 2013 Intel Corporation.
+@REM
+@REM Redistribution and use in source and binary forms, with or without
+@REM modification, are permitted provided that the following conditions
+@REM are met:
+@REM
+@REM * Redistributions of source code must retain the above copyright
+@REM notice, this list of conditions and the following disclaimer.
+@REM * Redistributions in binary form must reproduce the above copyright
+@REM notice, this list of conditions and the following disclaimer in
+@REM the documentation and/or other materials provided with the
+@REM distribution.
+@REM * Neither the name of Intel Corporation nor the names of its
+@REM contributors may be used to endorse or promote products derived
+@REM from this software without specific prior written permission.
+@REM
+@REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+@REM "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+@REM LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+@REM A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+@REM OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+@REM SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+@REM LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+@REM DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+@REM THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+@REM (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+@REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+@REM
+@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+@REM
+
+@REM set CYGWIN_HOME=C:\cygwin
+
+@REM usage:
+@REM edksetup.bat [--nt32] [AntBuild] [Rebuild] [ForceRebuild] [Reconfig]
+@REM if the argument, skip is present, only the paths and the
+@REM test and set of environment settings are performed.
+
+@REM ##############################################################
+@REM # You should not have to modify anything below this line
+@REM #
+
+@echo off
+
+@REM
+@REM Set the WORKSPACE to the current working directory
+@REM
+pushd .
+cd %~dp0
+
+if not defined WORKSPACE (
+ @goto SetWorkSpace
+)
+
+if %WORKSPACE% == %CD% (
+ @REM Workspace is not changed.
+ @goto ParseArgs
+)
+
+:SetWorkSpace
+@REM set new workspace
+@REM set EFI_SOURCE, ECP_SOURCE and EDK_SOURCE for the new workspace
+set WORKSPACE=%CD%
+set EFI_SOURCE=%CD%
+set EDK_SOURCE=%CD%
+set ECP_SOURCE=%CD%
+
+:ParseArgs
+
+if not defined VS_VERSION (
+ set VS_VERSION=
+ set VSCOMNTOOLS=
+
+ if defined VS90COMNTOOLS (
+ set VS_VERSION=VS2008
+ set VSCOMNTOOLS="%VS90COMNTOOLS%"
+ call "%VS90COMNTOOLS%\vsvars32.bat"
+ ) else (
+ if defined VS80COMNTOOLS (
+ set VS_VERSION=VS2005
+ set VSCOMNTOOLS="%VS80COMNTOOLS%"
+ call "%VS80COMNTOOLS%\vsvars32.bat"
+ ) else (
+ if defined VS71COMNTOOLS (
+ set VS_VERSION=VS2003
+ set VSCOMNTOOLS="%VS71COMNTOOLS%"
+ call "%VS71COMNTOOLS%\vsvars32.bat"
+ ) else (
+ echo.
+ echo !!! WARNING !!! Cannot find Visual Studio !!!
+ echo.
+ )
+ )
+ )
+)
+
+set VS_X86=
+set VSCOMNTOOLS_TMP=%VSCOMNTOOLS:(x86)=%
+if %VSCOMNTOOLS_TMP% == %VSCOMNTOOLS% goto ParseContinue
+set VS_X86=x86
+
+:ParseContinue
+@if /I "%1"=="-h" goto Usage
+@if /I "%1"=="-help" goto Usage
+@if /I "%1"=="--help" goto Usage
+@if /I "%1"=="/h" goto Usage
+@if /I "%1"=="/?" goto Usage
+@if /I "%1"=="/help" goto Usage
+@if /I not "%1"=="--nt32" goto no_nt32
+
+@REM Flag, --nt32 is set
+@REM The Nt32 Emluation Platform requires Microsoft Libraries
+@REM and headers to interface with Windows.
+
+shift
+
+:no_nt32
+@if /I "%1"=="NewBuild" shift
+@if not defined EDK_TOOLS_PATH set EDK_TOOLS_PATH=%WORKSPACE%\BaseTools
+@IF NOT EXIST "%EDK_TOOLS_PATH%\toolsetup.bat" goto BadBaseTools
+@call %EDK_TOOLS_PATH%\toolsetup.bat %*
+@if /I "%1"=="Reconfig" shift
+@goto check_cygwin
+
+:BadBaseTools
+ @REM
+ @REM Need the BaseTools Package in order to build
+ @REM
+ echo.
+ echo !!! ERROR !!! The BaseTools Package was not found !!!
+ echo.
+ echo Set the system environment variable, EDK_TOOLS_PATH to the BaseTools,
+ echo For example,
+ echo set EDK_TOOLS_PATH=C:\MyTools\BaseTools
+ echo The setup script, toolsetup.bat must reside in this folder.
+ echo.
+ @goto end
+
+:check_cygwin
+ @if exist c:\cygwin (
+ @set CYGWIN_HOME=c:\cygwin
+ ) else (
+ @echo.
+ @echo !!! WARNING !!! No CYGWIN_HOME set, gcc build may not be used !!!
+ @echo.
+ )
+
+@if NOT "%1"=="" goto Usage
+@goto end
+
+:Usage
+ @echo.
+ @echo Usage: "%0 [-h | -help | --help | /h | /help | /?] [--nt32] [Reconfig]"
+ @echo --nt32 Call vsvars32.bat for NT32 platform build.
+ @echo.
+ @echo Reconfig Reinstall target.txt, tools_def.txt and build_rule.txt.
+ @echo.
+ @echo Note that target.template, tools_def.template and build_rules.template
+ @echo will be only copied to target.txt, tools_def.txt and build_rule.txt
+ @echo respectively if they do not exist. Using option [Reconfig] to force the copy.
+ @echo.
+ @goto end
+
+:end
+ @popd
+ @echo on
+
diff --git a/edksetup.sh b/edksetup.sh
new file mode 100755
index 0000000..159b20a
--- /dev/null
+++ b/edksetup.sh
@@ -0,0 +1,70 @@
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# In *inux environment, the build tools's source is required and need to be compiled
+# firstly, please reference https://edk2.tianocore.org/unix-getting-started.html to
+# to get how to setup build tool.
+#
+# After build tool is downloaded and compiled, a soft symbol linker need to be created
+# at <workspace>/Conf. For example: ln -s /work/BaseTools /work/edk2/Conf/BaseToolsSource.
+#
+# Setup the environment for unix-like systems running a bash-like shell.
+# This file must be "sourced" not merely executed. For example: ". edksetup.sh"
+#
+# CYGWIN users: Your path and filename related environment variables should be
+# set up in the unix style. This script will make the necessary conversions to
+# windows style.
+#
+# Please reference edk2 user manual for more detail descriptions at https://edk2.tianocore.org/files/documents/64/494/EDKII_UserManual.pdf
+#
+
+if [ \
+ "$1" = "-?" -o \
+ "$1" = "-h" -o \
+ "$1" = "--help" \
+ ]
+then
+ echo BaseTools Usage: \'. edksetup.sh\'
+ echo
+ echo Please note: This script must be \'sourced\' so the environment can be changed.
+ echo \(Either \'. edksetup.sh\' or \'source edksetup.sh\'\)
+ return
+fi
+
+if [ -z "$WORKSPACE" ]
+then
+ . BaseTools/BuildEnv $*
+else
+ . $WORKSPACE/BaseTools/BuildEnv $*
+fi
+
+
diff --git a/quarkbuild.bat b/quarkbuild.bat
new file mode 100755
index 0000000..03abcfd
--- /dev/null
+++ b/quarkbuild.bat
@@ -0,0 +1,232 @@
+@REM
+@REM Copyright (c) 2013 Intel Corporation.
+@REM
+@REM Redistribution and use in source and binary forms, with or without
+@REM modification, are permitted provided that the following conditions
+@REM are met:
+@REM
+@REM * Redistributions of source code must retain the above copyright
+@REM notice, this list of conditions and the following disclaimer.
+@REM * Redistributions in binary form must reproduce the above copyright
+@REM notice, this list of conditions and the following disclaimer in
+@REM the documentation and/or other materials provided with the
+@REM distribution.
+@REM * Neither the name of Intel Corporation nor the names of its
+@REM contributors may be used to endorse or promote products derived
+@REM from this software without specific prior written permission.
+@REM
+@REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+@REM "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+@REM LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+@REM A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+@REM OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+@REM SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+@REM LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+@REM DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+@REM THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+@REM (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+@REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+@REM
+
+@echo off
+
+@REM Make sure you fully understand (the lack of) delayedexpansion
+@REM in batch files before you try to use error reporting
+set MY_ERROR_LVL=0
+
+
+@if /I "%1"=="" goto Usage
+@if /I "%1"=="-h" goto Usage
+@if /I "%1"=="-clean" goto Clean
+@if /I "%2"=="" goto Usage
+@if /I "%3"=="" goto Usage
+
+@REM
+@REM Windows build environment traditionally has problems with long path names.
+@REM most notably the MAX_PATH limit.
+@REM Substitute the source code root to avoid these problems.
+@REM
+set CURRENTDIR=%~dp0
+set CURRENTDIR=%CURRENTDIR:~0,-1%
+set CURRENTDRIVE=%~d1
+set SUBSTDRIVE=%2:
+
+subst /d %SUBSTDRIVE%
+subst %SUBSTDRIVE% %CURRENTDIR%
+%SUBSTDRIVE%
+
+@if not defined WORKSPACE (
+ call %SUBSTDRIVE%\edksetup.bat
+)
+
+@echo off
+
+if /I "%1"=="-r32" (
+ set TARGET=RELEASE
+ set DEBUG_PRINT_ERROR_LEVEL=-DDEBUG_PRINT_ERROR_LEVEL=0x80000000
+ set DEBUG_PROPERTY_MASK=-DDEBUG_PROPERTY_MASK=0x23
+ goto CheckParameter3
+)
+
+if /I "%1"=="-d32" (
+ set TARGET=DEBUG
+ set DEBUG_PRINT_ERROR_LEVEL=-DDEBUG_PRINT_ERROR_LEVEL=0x80000042
+ set DEBUG_PROPERTY_MASK=-DDEBUG_PROPERTY_MASK=0x27
+ goto CheckParameter3
+) else (
+ goto Usage
+)
+
+:CheckParameter3
+ set PLATFORM=%3
+ goto BuildAll
+
+:Clean
+echo Removing Build/Conf directories ...
+if exist Build rmdir Build /s /q
+if exist Conf rmdir Conf /s /q
+if exist *.log del *.log /q /f
+set WORKSPACE=
+set EDK_TOOLS_PATH=
+goto End
+
+:BuildAll
+@echo off
+
+@REM Add all arguments after the 3rd to the EDK_PARAMS variable
+@REM tokens=1-3 puts the 1st, 2nd and 3rd arguments in %%a, %%b and %%c
+@REM All remaining arguments are in %%d
+
+
+for /f "tokens=1-3*" %%a in ("%*") do (
+ set EDK_PARAMS=%%d
+)
+
+if NOT exist %WORKSPACE%\BaseTools (
+ echo Error: SVN directories missing - please run svn update to download
+ goto End
+)
+
+if exist %WORKSPACE%\QuarkSocPkg\QuarkNorthCluster\Binary\QuarkMicrocode\RMU.bin goto GotCMC
+echo Trying to fetch Chipset Microcode...
+%WORKSPACE%\fetchCMCBinary.py
+if %ERRORLEVEL% NEQ 0 (
+ set MY_ERROR_LVL=%ERRORLEVEL%
+ echo Error: Chipset Microcode is missing
+ goto End
+)
+
+:GotCMC
+
+@REM ###############################################################################
+@REM ######################## PreBuild-processing ######################
+@REM ###############################################################################
+if NOT exist %WORKSPACE%\Conf (
+ echo Error: Missing folder %WORKSPACE%\Conf\
+ goto End
+) else (
+ if exist %WORKSPACE%\QuarkPlatformPkg\Override\BaseTools\Conf\tools_def.template (
+ echo copying ... tools_def.template to %WORKSPACE%\Conf\tools_def.txt
+ copy /Y %WORKSPACE%\QuarkPlatformPkg\Override\BaseTools\Conf\tools_def.template %WORKSPACE%\Conf\tools_def.txt > nul
+ )
+ if exist %WORKSPACE%\QuarkPlatformPkg\Override\BaseTools\Conf\build_rule.template (
+ echo copying ... build_rule.template to %WORKSPACE%\Conf\build_rule.txt
+ copy /Y %WORKSPACE%\QuarkPlatformPkg\Override\BaseTools\Conf\build_rule.template %WORKSPACE%\Conf\build_rule.txt > nul
+ )
+)
+
+
+@if not exist Build\%PLATFORM%\%TARGET%_%VS_VERSION%%VS_X86%\IA32 (
+ mkdir Build\%PLATFORM%\%TARGET%_%VS_VERSION%%VS_X86%\IA32
+)
+
+@REM ####################################################################################################################
+@REM ###### Perform the actual build #############
+@REM ###### Warning: parameters here are supposed to override any corresponding value in Conf/target.txt #############
+@REM ####################################################################################################################
+build -p %PLATFORM%Pkg\%PLATFORM%Pkg.dsc -b %TARGET% -a IA32 -n 4 -t %VS_VERSION%%VS_X86% -y Report.log %EDK_PARAMS% %DEBUG_PRINT_ERROR_LEVEL% %DEBUG_PROPERTY_MASK%
+if %ERRORLEVEL% NEQ 0 ( set MY_ERROR_LVL=%ERRORLEVEL% & Goto End )
+
+@REM ###############################################################################
+@REM ######################## PostBuild-processing #####################
+@REM ###############################################################################
+.\QuarkPlatformPkg\Tools\QuarkSpiFixup\QuarkSpiFixup.py %PLATFORM% %TARGET% %VS_VERSION%%VS_X86%
+
+@REM ###############################################################################
+@REM ######################## Image signing stage ####################
+@REM ######################## (dummy signing) ####################
+@REM ###############################################################################
+set OutputModulesDir=%WORKSPACE%\Build\%PLATFORM%\%TARGET%_%VS_VERSION%%VS_X86%\FV
+
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %OutputModulesDir%\FlashModules\EDKII_BOOT_STAGE1_IMAGE1.Fv %OutputModulesDir%\EDKII_BOOT_STAGE1_IMAGE1.Fv.signed
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %OutputModulesDir%\FlashModules\EDKII_BOOT_STAGE1_IMAGE2.Fv %OutputModulesDir%\EDKII_BOOT_STAGE1_IMAGE2.Fv.signed
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %OutputModulesDir%\FlashModules\EDKII_BOOT_STAGE2_RECOVERY.Fv %OutputModulesDir%\EDKII_BOOT_STAGE2_RECOVERY.Fv.signed
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %OutputModulesDir%\FlashModules\EDKII_BOOT_STAGE2_COMPACT.Fv %OutputModulesDir%\EDKII_BOOT_STAGE2_COMPACT.Fv.signed
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %OutputModulesDir%\FlashModules\EDKII_BOOT_STAGE2.Fv %OutputModulesDir%\EDKII_BOOT_STAGE2.Fv.signed
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %OutputModulesDir%\FlashModules\EDKII_RECOVERY_IMAGE1.Fv %OutputModulesDir%\EDKII_RECOVERY_IMAGE1.Fv.signed
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %OutputModulesDir%\FlashModules\EDKII_RECOVERY_IMAGE2.Fv %OutputModulesDir%\EDKII_RECOVERY_IMAGE2.Fv.signed
+
+@REM ###############################################################################
+@REM #################### Capsule creation stage ################
+@REM #################### (Recovery and Update capsules) ################
+@REM ###############################################################################
+set CapsuleConfigFile=%WORKSPACE%\%PLATFORM%Pkg\Tools\CapsuleCreate\%PLATFORM%PkgCapsuleComponents.inf
+set CapsuleOutputFileNoReset=%OutputModulesDir%\%PLATFORM%PkgNoReset.Cap
+set CapsuleOutputFileReset=%OutputModulesDir%\%PLATFORM%PkgReset.Cap
+@REM CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
+@REM CAPSULE_FLAGS_INITIATE_RESET 0x00040000
+set CapsuleFlagsNoReset=0x00000000
+set CapsuleFlagsReset=0x00050000
+
+%WORKSPACE%\QuarkPlatformPkg\Tools\CapsuleCreate\CapsuleCreate.exe %CapsuleConfigFile% %OutputModulesDir% %CapsuleOutputFileNoReset% %CapsuleFlagsNoReset%
+%WORKSPACE%\QuarkPlatformPkg\Tools\CapsuleCreate\CapsuleCreate.exe %CapsuleConfigFile% %OutputModulesDir% %CapsuleOutputFileReset% %CapsuleFlagsReset%
+
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %CapsuleOutputFileReset% %CapsuleOutputFileReset%.signed
+%WORKSPACE%\QuarkPlatformPkg\Tools\SignTool\DummySignTool.exe %CapsuleOutputFileNoReset% %CapsuleOutputFileNoReset%.signed
+
+copy /b /Y %OutputModulesDir%\EDKII_BOOT_STAGE2_RECOVERY.Fv.signed + %CapsuleOutputFileReset%.signed %OutputModulesDir%\FVMAIN.fv > nul
+
+
+@REM ###############################################################################
+@REM ################ Create useful output directories ################
+@REM ###############################################################################
+@if not exist %OutputModulesDir%\RemediationModules (
+ mkdir %OutputModulesDir%\RemediationModules
+)
+
+@REM Copy the 'Recovery Capsule' and 'Update Capsules' to the RemediationModules directory
+copy /Y %OutputModulesDir%\FVMAIN.fv %OutputModulesDir%\RemediationModules\.
+copy /Y %CapsuleOutputFileReset%.signed %OutputModulesDir%\RemediationModules\.
+copy /Y %CapsuleOutputFileNoReset%.signed %OutputModulesDir%\RemediationModules\.
+copy /Y %WORKSPACE%\QuarkPlatformPkg\Applications\CapsuleApp.efi %OutputModulesDir%\RemediationModules\.
+
+@if not exist %OutputModulesDir%\Tools (
+ mkdir %OutputModulesDir%\Tools
+)
+
+@REM Copy the 'CapsuleCreate.exe' tool to the Tools directory
+copy /Y %WORKSPACE%\QuarkPlatformPkg\Tools\CapsuleCreate\CapsuleCreate.exe %OutputModulesDir%\Tools\.
+
+@if not exist %OutputModulesDir%\Applications (
+ mkdir %OutputModulesDir%\Applications
+)
+
+@REM Copy the 'CapsuleApp.efi' application to the Applications directory
+copy /Y %WORKSPACE%\QuarkPlatformPkg\Applications\CapsuleApp.efi %OutputModulesDir%\Applications\.
+
+copy Report.log Build\%PLATFORM%\%TARGET%_%VS_VERSION%%VS_X86%\ > nul
+if ERRORLEVEL 1 exit /b 1
+goto End
+
+:Usage
+ echo.
+ echo Usage: "%0 [-h | -r32 | -d32 | -clean] [subst drive letter] [PlatformName] [-DSECURE_LD(optional)] [-DSECURE_BOOT(optional)]"
+ echo.
+
+:End
+%CURRENTDRIVE%
+subst /d %SUBSTDRIVE%
+echo.
+exit /b %MY_ERROR_LVL%
+
+
diff --git a/quarkbuild.sh b/quarkbuild.sh
new file mode 100755
index 0000000..7c535d1
--- /dev/null
+++ b/quarkbuild.sh
@@ -0,0 +1,244 @@
+#!/bin/bash
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# This build script is:
+# 1. An implementation of the Tianocore instructions for GCC, plus
+# 2. Clanton-specific build steps
+
+# This script automates compiling the default configs. For anything
+# more custom edit the Conf/target.txt file and use the original
+# Tianocore 'build' command
+# http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=Using_EDK_II_with_Native_GCC_4.4
+
+set -e
+
+build_all()
+{
+
+ test -d ./BaseTools ||
+ die "Missing required directories, have you run 'svn update'?\n"
+
+ test -e ./QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin || {
+ echo "Trying to fetch Chipset Microcode"
+ ./fetchCMCBinary.py || die "Missing Chipset Microcode\n"
+ }
+
+ mkdir -p Conf
+
+ make -C BaseTools
+ # This defines EDK_TOOLS_PATH=..../BaseTools and others
+ . ./edksetup.sh
+
+
+ ###############################################################################
+ ######################## PreBuild-processing ######################
+ ###############################################################################
+ if [ -e $WORKSPACE/QuarkPlatformPkg/Override/BaseTools/Conf/tools_def.template ]
+ then
+ cp -f $WORKSPACE/QuarkPlatformPkg/Override/BaseTools/Conf/tools_def.template $WORKSPACE/Conf/tools_def.txt
+ fi
+ if [ -e $WORKSPACE/QuarkPlatformPkg/Override/BaseTools/Conf/build_rule.template ]
+ then
+ cp -f $WORKSPACE/QuarkPlatformPkg/Override/BaseTools/Conf/build_rule.template $WORKSPACE/Conf/build_rule.txt
+ fi
+
+ local thread_number_opt=''
+ if test -n "${THREAD_NUMBER}"; then
+ thread_number_opt="-n ${THREAD_NUMBER}"
+ fi
+
+ ####################################################################################################################
+ ###### Perform the actual build #############
+ ###### Warning: parameters here are supposed to override any corresponding value in Conf/target.txt #############
+ ####################################################################################################################
+ build -p ${platform}Pkg/${platform}Pkg.dsc -b ${target} -a IA32 ${thread_number_opt} -t $tool_opt -y Report.log $_args ${debug_print_error_level} ${debug_property_mask}
+
+
+ ###############################################################################
+ ######################## PostBuild-processing #####################
+ ###############################################################################
+ ./QuarkPlatformPkg/Tools/QuarkSpiFixup/QuarkSpiFixup.py $platform $target $tool_opt
+
+
+ ###############################################################################
+ ######################## Image signing stage ####################
+ ######################## (dummy signing) ####################
+ ###############################################################################
+ OutputModulesDir=$WORKSPACE/Build/${platform}/${target}_$tool_opt/FV
+
+ if [ ! -e $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool ]
+ then
+ make -C $WORKSPACE/QuarkPlatformPkg/Tools/SignTool
+ fi
+
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool ${OutputModulesDir}/FlashModules/EDKII_BOOT_STAGE1_IMAGE1.Fv $OutputModulesDir/EDKII_BOOT_STAGE1_IMAGE1.Fv.signed
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool ${OutputModulesDir}/FlashModules/EDKII_BOOT_STAGE1_IMAGE2.Fv $OutputModulesDir/EDKII_BOOT_STAGE1_IMAGE2.Fv.signed
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool ${OutputModulesDir}/FlashModules/EDKII_BOOT_STAGE2_RECOVERY.Fv $OutputModulesDir/EDKII_BOOT_STAGE2_RECOVERY.Fv.signed
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool ${OutputModulesDir}/FlashModules/EDKII_BOOT_STAGE2_COMPACT.Fv $OutputModulesDir/EDKII_BOOT_STAGE2_COMPACT.Fv.signed
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool ${OutputModulesDir}/FlashModules/EDKII_BOOT_STAGE2.Fv $OutputModulesDir/EDKII_BOOT_STAGE2.Fv.signed
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool ${OutputModulesDir}/FlashModules/EDKII_RECOVERY_IMAGE1.Fv $OutputModulesDir/EDKII_RECOVERY_IMAGE1.Fv.signed
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool ${OutputModulesDir}/FlashModules/EDKII_RECOVERY_IMAGE2.Fv $OutputModulesDir/EDKII_RECOVERY_IMAGE2.Fv.signed
+
+
+ ###############################################################################
+ #################### Capsule creation stage ################
+ #################### (Recovery and Update capsules) ################
+ ###############################################################################
+ CapsuleConfigFile=$WORKSPACE/${platform}Pkg/Tools/CapsuleCreate/${platform}PkgCapsuleComponents.inf
+ CapsuleOutputFileNoReset=$OutputModulesDir/${platform}PkgNoReset.Cap
+ CapsuleOutputFileReset=$OutputModulesDir/${platform}PkgReset.Cap
+ # CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
+ # CAPSULE_FLAGS_INITIATE_RESET 0x00040000
+ CapsuleFlagsNoReset=0x00000000
+ CapsuleFlagsReset=0x00050000
+
+ if [ ! -e $WORKSPACE/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate ]
+ then
+ make -C $WORKSPACE/QuarkPlatformPkg/Tools/CapsuleCreate
+ fi
+
+ if [ -e $WORKSPACE/${platform}Pkg/Tools/CapsuleCreate/${platform}PkgCapsuleComponents.inf ]
+ then
+ $WORKSPACE/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate $CapsuleConfigFile $OutputModulesDir $CapsuleOutputFileNoReset $CapsuleFlagsNoReset
+ $WORKSPACE/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate $CapsuleConfigFile $OutputModulesDir $CapsuleOutputFileReset $CapsuleFlagsReset
+ fi
+
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool $CapsuleOutputFileReset ${CapsuleOutputFileReset}.signed
+ $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool $CapsuleOutputFileNoReset ${CapsuleOutputFileNoReset}.signed
+ cat $OutputModulesDir/EDKII_BOOT_STAGE2_RECOVERY.Fv.signed $CapsuleOutputFileReset.signed > $OutputModulesDir/FVMAIN.fv
+
+ ###############################################################################
+ ################ Create useful output directories ################
+ ###############################################################################
+ # Create Remediation directory
+ if [ ! -e $OutputModulesDir/RemediationModules ]
+ then
+ mkdir $OutputModulesDir/RemediationModules
+ fi
+
+ # Copy the 'Recovery Capsule' and 'Update Capsules' to the RemediationModules directory
+ cp -f $OutputModulesDir/FVMAIN.fv $OutputModulesDir/RemediationModules/.
+ cp -f ${CapsuleOutputFileReset}.signed $OutputModulesDir/RemediationModules/.
+ cp -f ${CapsuleOutputFileNoReset}.signed $OutputModulesDir/RemediationModules/.
+ cp -f $WORKSPACE/QuarkPlatformPkg/Applications/CapsuleApp.efi $OutputModulesDir/RemediationModules/.
+
+ # Create Tools directory
+ if [ ! -e $OutputModulesDir/Tools ]
+ then
+ mkdir $OutputModulesDir/Tools
+ fi
+
+ # Copy the 'CapsuleCreate' tool to the Tools directory
+ cp -f $WORKSPACE/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate $OutputModulesDir/Tools/.
+
+ # Create Applications directory
+ if [ ! -e $OutputModulesDir/Applications ]
+ then
+ mkdir $OutputModulesDir/Applications
+ fi
+
+ # Copy the 'CapsuleApp.efi' application to the Application directory
+ cp -f $WORKSPACE/QuarkPlatformPkg/Applications/CapsuleApp.efi $OutputModulesDir/Applications/.
+
+ ########################################################################################
+ ######## Remove build files created (now that we are finished using them) ########
+ ########################################################################################
+ rm -f $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool
+ rm -f $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool.o
+ rm -f $WORKSPACE/QuarkPlatformPkg/Tools/SignTool/DummySignTool.d
+ rm -f $WORKSPACE/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate
+ rm -f $WORKSPACE/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.o
+ rm -f $WORKSPACE/QuarkPlatformPkg/Tools/CapsuleCreate/CapsuleCreate.d
+
+ cp -f ./Report.log ./Build/${platform}/${target}_$tool_opt
+}
+
+die()
+{
+ printf "ERROR: "
+ printf "$@"; exit 1
+}
+
+usage()
+{
+ die "$0 [-r32|-d32|-clean] [GCC43|GCC44|GCC45|GCC46|GCC47] [PlatformName] [-DSECURE_LD(optional)] [-DSECURE_BOOT(optional)]\n"
+}
+
+clean()
+{
+ printf "Warning: this option is different from every EDK2's 'build cleanXXX' feature\n"
+
+ ( set -x
+ rm -rf Conf Build
+ )
+}
+
+main()
+{
+ case "$1" in
+ -clean)
+ clean; exit 0
+ ;;
+ -r32)
+ target=RELEASE
+ debug_print_error_level=-DDEBUG_PRINT_ERROR_LEVEL=0x80000000
+ debug_property_mask=-DDEBUG_PROPERTY_MASK=0x23
+ ;;
+ -d32)
+ target=DEBUG
+ debug_print_error_level=-DDEBUG_PRINT_ERROR_LEVEL=0x80000042
+ debug_property_mask=-DDEBUG_PROPERTY_MASK=0x27
+ ;;
+ *)
+ usage
+ esac
+ case "$2" in
+ GCC43) ;;
+ GCC44) ;;
+ GCC45) ;;
+ GCC46) ;;
+ GCC47) ;;
+ *)
+ usage
+ esac
+
+ # 2nd argument is the build tools
+ tool_opt=$2
+
+ # 3rd argument is the platform name
+ platform=$3
+
+ # Add all arguments after the 3rd to the _args array
+ array=( $@ )
+ _args=${array[@]:3:$#}
+
+ build_all
+}
+
+
+main "$@"
diff --git a/svn_externals.txt b/svn_externals.txt
new file mode 100755
index 0000000..613f4d0
--- /dev/null
+++ b/svn_externals.txt
@@ -0,0 +1,13 @@
+BaseTools -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/BaseTools
+MdePkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/MdePkg
+MdeModulePkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/MdeModulePkg
+IntelFrameworkPkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/IntelFrameworkPkg
+IntelFrameworkModulePkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/IntelFrameworkModulePkg
+EdkShellBinPkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/EdkShellBinPkg
+PcAtChipsetPkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/PcAtChipsetPkg
+UefiCpuPkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/UefiCpuPkg
+ShellPkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/ShellPkg
+SourceLevelDebugPkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/SourceLevelDebugPkg
+CryptoPkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/CryptoPkg
+SecurityPkg -r13937 http://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1/SecurityPkg
+FatPkg -r67 http://svn.code.sf.net/p/edk2-fatdriver2/code/trunk/FatPkg
diff --git a/svn_setup.py b/svn_setup.py
new file mode 100755
index 0000000..85cc63d
--- /dev/null
+++ b/svn_setup.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2013 Intel Corporation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Marc Herbert
+
+from __future__ import print_function
+
+import os
+import shutil
+import stat
+import sys
+import subprocess
+import time
+import tempfile
+
+DEBUG=False
+SVN_EXTERNALS_FILE = "svn_externals.txt"
+
+
+def isWindows():
+ return os.name == 'nt'
+
+def info(*objs):
+ print("INFO: ", *objs, end='\n', file=sys.stdout)
+ sys.stdout.flush()
+def warning(*objs):
+ print("WARNING: ", *objs, end='\n', file=sys.stdout)
+ sys.stdout.flush()
+def error(*objs):
+ print("ERROR: ", *objs, end='\n', file=sys.stderr)
+ sys.stderr.flush()
+
+def die(*objs):
+ error(*objs)
+ if isWindows():
+ subprocess.call("cmd /c PAUSE")
+ sys.exit(1)
+
+#import inspect
+#info("Running ", os.path.abspath(inspect.getsourcefile(mainf)))
+
+DOTDOT = os.path.dirname(os.getcwd())
+CLONE_BASENAME = os.path.basename(os.getcwd())
+ADHOC = CLONE_BASENAME + "-svn_externals.repo"
+# '@' is a special character for subversion (peg revisions)
+ADHOC = ADHOC.replace('@', '_at_')
+ADHOC_PATH = os.path.join(DOTDOT, ADHOC)
+
+# info("Parent directory:", DOTDOT)
+info("Ad-hoc SVN repo:", ADHOC_PATH)
+
+
+def my_system(args):
+
+ if DEBUG:
+ info("About to run:", args)
+ time.sleep(2)
+ else:
+ info("Running:", ' '.join(args))
+
+ # - stdout: Python has no portable, non-blocking read operation on
+ # pipes so we cannot capture long, progress information on the
+ # fly. So we just let stdout be inherited.
+ # http://www.python.org/dev/peps/pep-3145/
+
+ # -stderr: On the other hand we assume stderr will be small and
+ # final and want to know if there is any error message all, so we
+ # block-read on it. As a bonus feature this gets rid of the extra
+ # command window on Windows.
+ child = subprocess.Popen(args, stderr=subprocess.PIPE)
+ err = child.stderr.read()
+ child.wait()
+
+ if err:
+ die("stderr output of: ", args, "\n", err)
+
+ if child.returncode:
+ die(args, "returned: ", child.returncode)
+
+ if DEBUG:
+ info("Done running:", args)
+ time.sleep(2)
+
+
+def setup_externals():
+
+ # Try something harmless first to make sure the command line is
+ # installed and in the PATH
+ try:
+ info("SVN version:")
+ subprocess.check_call(["svn", "--version", "--quiet"])
+ except BaseException as e:
+ print (type(e).__name__ + ":", e)
+ die("Failed to run Subversion command line, please make sure it is installed and in the PATH")
+
+ # Make room
+ for old_dir in [ '.svn', ADHOC_PATH ]:
+ if os.path.exists(old_dir):
+ warning("Removing older", old_dir)
+ for p, dirs, files in os.walk(old_dir):
+ for f in files:
+ # print (os.path.join(p,f))
+ os.chmod(os.path.join(p,f), stat.S_IWRITE)
+
+ shutil.rmtree(old_dir)
+
+
+ my_system([ "svnadmin", "create", ADHOC_PATH ])
+
+ my_system([ "svn", "checkout", "file:///" + ADHOC_PATH, os.path.join(os.getcwd(), ADHOC) ])
+
+ # Don't do this at home
+ shutil.move(os.path.join(ADHOC, '.svn'), '.')
+ os.rmdir(ADHOC)
+
+ # Note: if you want ever want to do this from TortoiseSVN graphical
+ # interface go to the "New->Advanced->Load" menu item in the
+ # Properties dialog box
+ my_system([ "svn", "propset", "svn:externals", "-F", SVN_EXTERNALS_FILE, "." ])
+ my_system([ "svn", "commit", "--depth", "empty", "--message", "Add svn:externals", "." ])
+
+
+def get_external_dirs():
+ "Parses the SVN_EXTERNALS_FILE and returns the list of directories from it"
+
+ def get_dir(external):
+ location = external.split()[-1]
+ return os.path.split(location)[-1]
+
+ with open(SVN_EXTERNALS_FILE) as f:
+ return [ get_dir(lin) for lin in f ]
+
+
+def parse_arguments():
+ from optparse import OptionParser
+ parser = OptionParser(usage="usage: %prog [options]")
+ parser.add_option("--gitignore", action="store_true", dest="gitignore",
+ help="Appends SVN objects to .gitignore (does not commit)")
+ parser.add_option("--download", action="store_true", dest="download",
+ help="Runs svn update to download externals once setup is complete (takes time)")
+ parser.add_option("--delete", action="store_true", dest="wipeout",
+ help="Deletes everything that is or would be in the way of --download. \
+This is a destructive way to help --download succeed. \
+Does NOT imply --download: both can be used independently")
+
+ (options, args) = parser.parse_args()
+
+ # Gather parsed command line and defaults and define the parameters
+ global svn_update, wipeout, gitignore
+ svn_update, wipeout, gitignore = options.download, options.wipeout, options.gitignore
+
+
+def mainf(*m_args):
+ # Overrides sys.argv when testing (interactive or in main below)
+ if m_args:
+ info("testing with args:", m_args)
+ sys.argv = ["testing main"] + list(m_args)
+
+ parse_arguments()
+
+ setup_externals()
+
+ # svn:ignore the stuff tracked by git
+ # TODO: could this somehow work on Windows with Git Extensions?
+ if os.path.exists(".git") and not isWindows():
+ with tempfile.NamedTemporaryFile(prefix="setupSVNext_") as tempf:
+ subprocess.check_call(["git", "ls-tree", "HEAD", "--name-only"], stdout=tempf)
+ tempf.write(b'.git')
+ my_system([ "svn", "propset", "svn:ignore", "-F", tempf.name, "." ])
+
+ # .gitignore the stuff tracked by svn
+ if gitignore:
+ info("Updating .gitignore")
+ with open (".gitignore", 'a') as gi:
+ ignored = get_external_dirs() + [ '.svn' ]
+ for dir in ignored:
+ print('/' + dir, file=gi )
+
+ if wipeout:
+ ext_directories = get_external_dirs()
+ for e in ext_directories:
+ if os.path.exists(e):
+ warning("Now removing previous ", e, "/")
+ shutil.rmtree(e)
+
+ if svn_update:
+ my_system([ "svn", "update" ])
+
+
+if __name__ == "__main__":
+ if True: # make it False to run test code below
+ ret = mainf()
+ else:
+ # Test/sample invocations (can test multiple in one run)
+ # mainf("--help")
+ ret = mainf(--gitignore)
+ # ret = mainf("--wipeout", "--download")
+ # mainf("--download")
+
+ if isWindows():
+ # We assume the user double-clicked on the script and we give a chance to see what happened
+ # Before the window goes away
+ subprocess.call("cmd /c PAUSE")
+
+ sys.exit(ret)